You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
3.5 KiB
144 lines
3.5 KiB
<script>
|
|
import {castId, keyBy, objCopy, isEmpty} from "../utils";
|
|
import forEach from "lodash-es/forEach";
|
|
import isEqual from "lodash-es/isEqual";
|
|
|
|
export default {
|
|
props: ['model_id', 'schema', 'objects'],
|
|
name: "NewRelationForm",
|
|
data() {
|
|
const model = this.schema.rel_models.find((m) => m.id === this.model_id);
|
|
if(!model) throw Error("Relation model not exist");
|
|
|
|
let properties = this.schema.prop_models.filter((m) => m.object === model.id);
|
|
|
|
properties.sort((a, b) => a.name.localeCompare(b.name));
|
|
|
|
if (isEmpty(properties)) {
|
|
properties = [];
|
|
} else {
|
|
properties = keyBy(properties, 'id');
|
|
}
|
|
|
|
let related_model = this.schema.obj_models.find((m) => m.id === model.related);
|
|
|
|
if(!related_model) throw Error("Related model not exist");
|
|
|
|
let choices = {};
|
|
this.objects.forEach((obj) => {
|
|
if (obj.model === model.related) {
|
|
choices[obj.id] = obj.name;
|
|
}
|
|
});
|
|
|
|
let instances = [];
|
|
if (!model.optional) {
|
|
// TODO avoid duplicated code
|
|
let values = {};
|
|
forEach(this.properties, (p) => {
|
|
if (p.optional) {
|
|
values[p.id] = [];
|
|
} else {
|
|
values[p.id] = [objCopy(p.default)];
|
|
}
|
|
});
|
|
instances.push({
|
|
related: '',
|
|
values
|
|
})
|
|
}
|
|
|
|
return {
|
|
model,
|
|
related_model,
|
|
properties,
|
|
object_names: choices,
|
|
instances,
|
|
}
|
|
},
|
|
methods: {
|
|
collectData() {
|
|
let relations = [];
|
|
forEach(objCopy(this.instances), (instance) => {
|
|
if (isEmpty(instance.related)) {
|
|
if (!this.model.optional) {
|
|
throw new Error(`Relation "${this.model.name}" is required`)
|
|
}
|
|
return; // continue
|
|
}
|
|
|
|
let values = [];
|
|
forEach(instance.values, (vv, prop_model_id) => {
|
|
|
|
for (let v of vv) {
|
|
if (isEqual(v, {"String": ""}) && this.properties[prop_model_id].optional) {
|
|
continue;
|
|
}
|
|
|
|
values.push({
|
|
model: castId(prop_model_id),
|
|
value: v
|
|
});
|
|
}
|
|
})
|
|
|
|
relations.push({
|
|
model: this.model.id,
|
|
related: castId(instance.related),
|
|
values
|
|
});
|
|
})
|
|
return relations;
|
|
},
|
|
|
|
addInstance() {
|
|
let values = {};
|
|
forEach(this.properties, (p) => {
|
|
if (p.optional) {
|
|
values[p.id] = [];
|
|
} else {
|
|
values[p.id] = [objCopy(p.default)];
|
|
}
|
|
});
|
|
this.instances.push({
|
|
model: this.model.id,
|
|
related: '',
|
|
values
|
|
})
|
|
},
|
|
|
|
removeInstance(ri) {
|
|
this.instances.splice(ri, 1)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.new-relation {
|
|
border: 1px dashed gray;
|
|
margin: 10px 0;
|
|
padding: 10px;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<div class="new-relation" v-for="(instance, ri) in instances" :key="ri">
|
|
<b>{{ model.name }} -> {{ related_model.name }}
|
|
<select v-model="instance.related">
|
|
<option v-for="(name, id) in object_names" :value="id">{{name}}</option>
|
|
</select>
|
|
</b>
|
|
|
|
<a href="#" v-if="model.multiple || model.optional && instances.length > 0"
|
|
style="margin-left: 5px"
|
|
@click="removeInstance(ri)">X</a>
|
|
|
|
<table v-if="properties">
|
|
<property v-for="(property, id) in properties" :model="property" :values="instance.values[id]" :key="id"></property>
|
|
</table>
|
|
</div>
|
|
|
|
<a href="#" v-if="model.multiple || model.optional && instances.length==0"
|
|
@click="addInstance">Add {{ model.name }} -> {{ related_model.name }}</a><br>
|
|
</template>
|
|
|