a small relational database with user-editable schema for manual data entry
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.
 
 
 
 
 
 
yopa/yopa-web/resources/src/components/EditObjectForm.vue

165 lines
3.9 KiB

<script>
import {castId, keyBy, objCopy, isEmpty} from "../utils";
import forEach from "lodash-es/forEach";
import isEqual from "lodash-es/isEqual";
import axios from "axios";
export default {
props: ['object', 'schema', 'objects'],
name: "EditObjectForm",
data() {
let object = this.object;
const model = this.schema.obj_models.find((m) => m.id === object.model);
let properties = this.schema.prop_models.filter((m) => m.object === model.id);
let relations = this.schema.rel_models.filter((m) => m.object === model.id);
let values = {};
properties.forEach((p) => {
let existing = object.values[p.id] || [];
if (existing.length) {
values[p.id] = existing;
} else {
if (p.optional) {
values[p.id] = [];
} else {
values[p.id] = [
// this is the format used for values
{
// it can also have model: ... here
value: objCopy(p.default)
}
];
}
}
});
let propertiesById = keyBy(properties, 'id');
let relationsById = keyBy(relations, 'id');
let model_names = {};
this.schema.obj_models.forEach((m) => {
model_names[m.id] = m.name;
});
return {
model,
properties,
propertiesById,
relations,
relationsById,
haveRelations: !isEmpty(relations),
model_names,
values,
name: object.name,
relationRefs: [],
}
},
methods: {
/** Get values in the raw format without grouping */
collectData() {
if (isEmpty(this.name)) {
throw new Error("Name is required");
}
let values = [];
forEach(objCopy(this.values), (vv, prop_model_id) => {
for (let v of vv) {
if (isEqual(v.value, {"String": ""}) && this.propertiesById[prop_model_id].optional) {
continue;
}
v.model = castId(prop_model_id);
values.push(v);
}
})
let relations = [];
for (let rref of this.relationRefs) {
for (let r of rref.collectData()) {
relations.push(r);
}
}
return {
model: this.object.model, // string is fine
id: this.object.id,
values,
relations,
};
},
trySave() {
let data;
try {
data = this.collectData();
} catch (e) {
alert(e.message);
return;
}
console.log('Try save', data);
axios({
method: 'post',
url: `/object/update/${this.object.id}`,
data: data
})
.then((response) => {
location.href = `/object/detail/${this.object.id}`;
})
.catch((error) => {
// TODO show error toast instead
alert(error.response ?
error.response.data :
error)
});
},
setRelationRef(el) {
if (el) {
this.relationRefs.push(el)
}
},
},
beforeUpdate() {
this.relationRefs = []
},
mounted() {
this.$el.parentNode
.classList.add('EditForm');
}
}
</script>
<template>
<div class="container">
<div class="cols">
<div class="col col-9">
<h1>Edit {{ model.name }}</h1>
</div>
<div class="col col-3 text-right">
<button type="button" @click="trySave" class="btn btn-primary">
<i class="icon icon-check"></i>Save
</button>
</div>
</div>
</div>
<div class="form-horizontal container">
<edit-property v-for="property in properties" :model="property" :values="values[property.id]" :key="property.id"></edit-property>
</div>
<div v-if="haveRelations">
<h3>Relations</h3>
<edit-relation
v-for="relation in relations"
:ref="setRelationRef"
:model_id="relation.id"
:objects="objects"
:initialInstances="object.relations[relation.id]"
:schema="schema"
></edit-relation>
</div>
</template>