AppReports/src/components/ConfigEditor.vue
2020-08-15 15:20:11 +02:00

181 lines
3.7 KiB
Vue

<template>
<div
v-if="enabled"
class="config-editor"
>
<p
class="label"
v-text="template.name"
/>
<!-- editor -->
<div
v-if="template.type === 'object'"
class="editor"
>
<ConfigEditor
v-for="(prop,key) of template.properties"
:key="key"
v-model="config[prop.name]"
:template="prop"
:enabled="is_enabled(prop.if)"
/>
</div>
<div
v-else-if="template.type === 'array'"
class="editor"
>
<ConfigEditor
v-for="(child,key) of config"
:key="key"
v-model="config[key]"
:template="template.child"
:enabled="is_enabled(template.child.if)"
/>
<button
type="button"
@click="add_item"
>
add
</button>
</div>
<div
v-else-if="template.type === 'string'"
class="editor"
>
<select
v-if="Array.isArray(template.choices)"
v-model="config"
>
<option
v-for="(opt,optkey) in template.choices"
:key="optkey"
v-text="opt"
/>
</select>
<input
v-else
v-model="config"
type="text"
>
</div>
<div
v-else-if="template.type === 'number'"
class="editor"
>
<input
v-model="config"
type="number"
>
</div>
<div
v-else-if="template.type === 'boolean'"
class="editor"
>
<input
v-model="config"
type="checkbox"
>
</div>
<pre v-else>
invalid config
</pre>
</div>
</template>
<script>
import { resolve_data } from '../helper';
export default {
name: 'ConfigEditor',
props: {
// eslint-disable-next-line vue/require-prop-types
value: { required: true },
template: {
type: Object,
required: true,
enabled: { type: Boolean, default: true }
},
enabled: {
type: Boolean,
default: true
}
},
data () {
return { temp: this.value };
},
computed: {
config: {
get () {
return this.temp;
},
set (val) {
this.$emit ('input', val);
this.temp = val;
}
}
},
methods: {
is_enabled (condition) {
if (typeof condition === 'undefined')
return true;
switch (condition.op) {
case '=':
return resolve_data (this.config, condition.prop) === condition.val;
case '<':
return resolve_data (this.config, condition.prop) < condition.val;
case '>':
return resolve_data (this.config, condition.prop) > condition.val;
default:
return false;
}
},
add_item () {
if (
typeof this.config === 'undefined'
|| !Array.isArray (this.config)
)
this.config = [];
this.config.push (this.create_default (this.template.child));
},
create_default (template) {
if (typeof template.default !== 'undefined')
return template.default;
if (template.type === 'string')
return '';
if (template.type === 'number')
return 0;
if (template.type === 'boolean')
return false;
if (template.type === 'array')
return [];
if (template.type === 'object') {
const res = {};
for (const prop of template.properties)
res[prop.name] = this.create_default (prop);
return res;
}
return null;
}
}
};
</script>
<style scoped>
.config-editor {
display: grid;
grid-template-areas: 'label editor';
grid-template-columns: auto 1fr;
}
.editor {
border: 1px solid black;
margin-left: 10px;
grid-column: editor;
}
.label {
display: inline-block;
grid-column: label;
}
</style>