gitlab-org--gitlab-foss/app/assets/javascripts/pipeline_wizard/components/input.vue

99 lines
2.3 KiB
Vue

<script>
import { isNode, isDocument, isSeq, visit } from 'yaml';
import { capitalize } from 'lodash';
import TextWidget from '~/pipeline_wizard/components/widgets/text.vue';
import ListWidget from '~/pipeline_wizard/components/widgets/list.vue';
const widgets = {
TextWidget,
ListWidget,
};
function isNullOrUndefined(v) {
return [undefined, null].includes(v);
}
export default {
components: {
...widgets,
},
props: {
template: {
type: Object,
required: true,
validator: (v) => isNode(v),
},
compiled: {
type: Object,
required: true,
validator: (v) => isDocument(v) || isNode(v),
},
target: {
type: String,
required: true,
validator: (v) => /^\$.*/g.test(v),
},
widget: {
type: String,
required: true,
validator: (v) => {
return Object.keys(widgets).includes(`${capitalize(v)}Widget`);
},
},
validate: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
path() {
let res;
visit(this.template, (seqKey, node, path) => {
if (node && node.value === this.target) {
// `path` is an array of objects (all the node's parents)
// So this reducer will reduce it to an array of the path's keys,
// e.g. `[ 'foo', 'bar', '0' ]`
res = path.reduce((p, { key }) => (key ? [...p, `${key}`] : p), []);
const parent = path[path.length - 1];
if (isSeq(parent)) {
res.push(seqKey);
}
}
});
return res;
},
},
methods: {
compile(v) {
if (!this.path) return;
if (isNullOrUndefined(v)) {
this.compiled.deleteIn(this.path);
}
this.compiled.setIn(this.path, v);
},
onModelChange(v) {
this.$emit('beforeUpdate:compiled');
this.compile(v);
this.$emit('update:compiled', this.compiled);
this.$emit('highlight', this.path);
},
onValidationStateChange(v) {
this.$emit('update:valid', v);
},
},
};
</script>
<template>
<div>
<component
:is="`${widget}-widget`"
ref="widget"
:validate="validate"
v-bind="$attrs"
@input="onModelChange"
@update:valid="onValidationStateChange"
/>
</div>
</template>