diff options
Diffstat (limited to 'app/assets/javascripts/pipeline_wizard/components/input.vue')
-rw-r--r-- | app/assets/javascripts/pipeline_wizard/components/input.vue | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/app/assets/javascripts/pipeline_wizard/components/input.vue b/app/assets/javascripts/pipeline_wizard/components/input.vue new file mode 100644 index 00000000000..9a0c8026648 --- /dev/null +++ b/app/assets/javascripts/pipeline_wizard/components/input.vue @@ -0,0 +1,99 @@ +<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> |