Skip to content

Commit

Permalink
feat(ui): task edit as a form
Browse files Browse the repository at this point in the history
  • Loading branch information
Skraye authored and tchiotludo committed Feb 24, 2023
1 parent 092230e commit d7fc07f
Show file tree
Hide file tree
Showing 24 changed files with 1,030 additions and 23 deletions.
2 changes: 1 addition & 1 deletion ui/src/components/Tabs.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div>
<el-tabs v-model="activeName">
<el-tabs class="router-link" v-model="activeName">
<el-tab-pane
v-for="tab in tabs"
:key="tab.name"
Expand Down
47 changes: 33 additions & 14 deletions ui/src/components/flows/TaskEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,36 @@
</div>
</template>

<div v-loading="isLoading">
<editor
v-if="taskYaml"
:read-only="isReadOnly"
ref="editor"
@save="saveTask"
v-model="taskYaml"
:schema-type="mapSectionWithSchema()"
:full-height="false"
:navbar="false"
lang="yaml"
/>
</div>
<el-tabs v-if="taskYaml" v-model="activeTabs">
<el-tab-pane name="source">
<template #label>
<span>{{ $t('source') }}</span>
</template>
<editor
v-if="taskYaml"
:read-only="isReadOnly"
ref="editor"
@save="saveTask"
v-model="taskYaml"
:schema-type="mapSectionWithSchema()"
:full-height="false"
:navbar="false"
lang="yaml"
/>
</el-tab-pane>
<el-tab-pane name="form">
<template #label>
<span>
{{ $t('form') }}
<el-badge type="primary" value="Alpha" />
</span>
</template>
<task-editor
ref="editor"
v-model="taskYaml"
/>
</el-tab-pane>
</el-tabs>
</el-drawer>
</component>
</template>
Expand All @@ -50,12 +67,13 @@
<script>
import YamlUtils from "../../utils/yamlUtils";
import Editor from "../inputs/Editor.vue";
import TaskEditor from "./TaskEditor.vue";
import {canSaveFlowTemplate, saveFlowTemplate} from "../../utils/flowTemplate";
import {mapState} from "vuex";
import Utils from "../../utils/utils";
export default {
components: {Editor},
components: {Editor, TaskEditor},
props: {
component: {
type: String,
Expand Down Expand Up @@ -139,6 +157,7 @@
uuid: Utils.uid(),
taskYaml: undefined,
isModalOpen: false,
activeTabs: "form",
};
},
created() {
Expand Down
95 changes: 95 additions & 0 deletions ui/src/components/flows/TaskEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<el-form label-position="top">
<el-form-item>
<template #label>
<code>{{ $t('type') }}</code>&nbsp;
</template>
<plugin-select
v-model="selectedTaskType"
@update:model-value="onTaskTypeSelect"
/>
</el-form-item>
</el-form>

<task-root
v-loading="isLoading"
v-if="plugin"
name="root"
:model-value="taskObject"
@update:model-value="onInput"
:schema="plugin.schema"
:definitions="plugin.schema.definitions"
/>
</template>
<script>
import TaskRoot from "./tasks/TaskRoot.vue";
import YamlUtils from "../../utils/yamlUtils";
import PluginSelect from "../../components/plugins/PluginSelect.vue";
export default {
components: {
TaskRoot,
PluginSelect
},
emits: ["update:modelValue"],
created() {
if (this.modelValue) {
this.taskObject = YamlUtils.parse(this.modelValue);
this.selectedTaskType = this.taskObject.type;
this.load();
}
},
props: {
modelValue : {
type: String,
required: false,
default: undefined,
},
},
data() {
return {
selectedTaskType: undefined,
taskObject: undefined,
isLoading: false,
plugin: undefined
};
},
computed: {
taskModels() {
const taskModels = [];
for (const plugin of this.plugins || []) {
taskModels.push.apply(taskModels, plugin.tasks);
}
return taskModels;
},
},
methods: {
load() {
this.isLoading = true;
this.$store
.dispatch("plugin/load", {
cls: this.selectedTaskType,
})
.then((response) => {
this.plugin = response;
this.isLoading = false;
})
},
onInput(value) {
this.taskObject = value;
this.$emit("update:modelValue", YamlUtils.stringify(value));
},
onTaskTypeSelect() {
this.load();
this.onInput({
id: this.taskObject && this.taskObject.id ? this.taskObject.id : "",
type: this.selectedTaskType
});
},
},
};
</script>

87 changes: 87 additions & 0 deletions ui/src/components/flows/tasks/Task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
export default {
props: {
modelValue: {
default: undefined
},
schema: {
type: Object,
required: true
},
required: {
type: Boolean,
default: false
},
root: {
type: String,
default: undefined
},
definitions: {
type: Object,
default: () => undefined
}
},
emits: ["update:modelValue"],
created() {
// if (this.schema.default && this.modelValue === undefined) {
// this.$emit("update:modelValue", this.schema.default);
// }
},
methods: {
getKey(property) {
return this.root ? this.root + "." + property : property;
},
isRequired(key) {
return this.schema.required && this.schema.required.includes(key);
},
getType(property) {
if (property.enum !== undefined) {
return "enum";
}

if (Object.prototype.hasOwnProperty.call(property, "$ref")) {
if (property.$ref.includes("Task")) {
return "task"
}
}

if (Object.prototype.hasOwnProperty.call(property, "additionalProperties")) {
return "dict";
}

if (property.type === "integer") {
return "number";
}

if (property.type === "object" && property.properties && Object.keys(property.properties).length >= 1) {
return "complex";
}

return property.type || "dynamic";
},
// eslint-disable-next-line no-unused-vars
onShow(key) {
},

onInput(value) {
this.$emit("update:modelValue", value === "" || value === null || JSON.stringify(value) === "{}" ? undefined : value);
}
},
computed: {
values() {
if (this.modelValue === undefined) {
return this.schema.default;
}

return this.modelValue;
},
editorValue() {
return this.values ? this.values : "";
},
info() {
return `${this.schema.title || this.schema.type}`
},
isValid() {
return true;
}
}
}
88 changes: 88 additions & 0 deletions ui/src/components/flows/tasks/TaskArray.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<div class="d-flex w-100 task-array" v-for="(item, index) in values" :key="'array-' + index">
<div class="flex-fill flex-grow-1 w-100 me-2">
<!--{{ `task-${getType(schema.items)}` + schema.items }}-->
<component
:is="`task-${getType(schema.items)}`"
:model-value="item"
@update:model-value="onInput(index, $event)"
:root="getKey(index)"
:schema="schema.items"
/>
</div>
<div class="flex-shrink-1">
<el-button-group class="d-flex flex-nowrap">
<el-button :icon="Plus" @click="addItem" />
<el-button :icon="Minus" @click="removeItem(index)" :disabled="index === 0 && values.length === 1" />
</el-button-group>
</div>
</div>
</template>

<script setup>
import Plus from "vue-material-design-icons/Plus.vue";
import Minus from "vue-material-design-icons/Minus.vue";
</script>

<script>
import {toRaw} from "vue";
import Task from "./Task";
export default {
mixins: [Task],
emits: ["update:modelValue"],
computed: {
values() {
if (this.modelValue === undefined) {
return this.schema.default || [undefined];
}
return this.modelValue;
},
},
methods: {
getPropertiesValue(properties) {
return this.modelValue && this.modelValue[properties]
? this.modelValue[properties]
: undefined;
},
onInput(index, value) {
const local = this.modelValue || [];
local[index] = value;
this.$emit("update:modelValue", local);
},
addItem() {
let local = this.modelValue || [];
local.push(undefined);
// click on + when there is no items
if (this.modelValue === undefined) {
local.push(undefined);
}
this.$emit("update:modelValue", local);
},
removeItem(x) {
let local = this.modelValue || [];
local.splice(x, 1);
if (local.length === 1) {
let raw = toRaw(local[0]);
if (raw === null || raw === undefined) {
local = undefined;
}
}
this.$emit("update:modelValue", local);
},
},
};
</script>
<style lang="scss" scoped>
.task-array {
margin-bottom: 2px;
}
</style>
15 changes: 15 additions & 0 deletions ui/src/components/flows/tasks/TaskBoolean.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<template>
<el-checkbox
:model-value="values"
@update:model-value="onInput"
:value="true"
/>
</template>

<script>
import Task from "./Task";
export default {
mixins: [Task],
};
</script>
Loading

0 comments on commit d7fc07f

Please sign in to comment.