mirror of
https://github.com/kestra-io/kestra.git
synced 2025-12-25 02:14:38 -05:00
fix(ui): [nocode] make dag tasks work (#9506)
This commit is contained in:
committed by
Bart Ledoux
parent
c320323371
commit
cb31ef642f
@@ -15,19 +15,15 @@
|
||||
<slot v-else />
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
tooltip: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
placement:{
|
||||
type: String,
|
||||
default: "top"
|
||||
},
|
||||
},
|
||||
}
|
||||
<script lang="ts" setup>
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
tooltip?: string;
|
||||
placement?: string;
|
||||
}>(),{
|
||||
tooltip: "",
|
||||
placement: "",
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="h-100 overflow-y-auto no-code">
|
||||
<div class="no-code">
|
||||
<Breadcrumbs />
|
||||
|
||||
<hr class="m-0">
|
||||
@@ -92,4 +92,13 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss" src="./styles/code.scss" />
|
||||
<style lang="scss" scoped>
|
||||
.no-code {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
hr {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<NoCode
|
||||
:flow="lastValidFlowYaml"
|
||||
:parent-path="parentPath"
|
||||
:ref-path="refPath"
|
||||
:block-type="blockType"
|
||||
:creating-task="creatingTask"
|
||||
:editing-task="editingTask"
|
||||
:position
|
||||
@update-metadata="(e) => onUpdateMetadata(e)"
|
||||
@update-task="(e) => editorUpdate(e)"
|
||||
@reorder="(yaml) => handleReorder(yaml)"
|
||||
@close-task="() => emit('closeTask')"
|
||||
/>
|
||||
</div>
|
||||
<NoCode
|
||||
:flow="lastValidFlowYaml"
|
||||
:parent-path="parentPath"
|
||||
:ref-path="refPath"
|
||||
:block-type="blockType"
|
||||
:creating-task="creatingTask"
|
||||
:editing-task="editingTask"
|
||||
:position
|
||||
@update-metadata="(e) => onUpdateMetadata(e)"
|
||||
@update-task="(e) => editorUpdate(e)"
|
||||
@reorder="(yaml) => handleReorder(yaml)"
|
||||
@close-task="() => emit('closeTask')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -147,6 +147,25 @@
|
||||
|
||||
}
|
||||
|
||||
function removeNullAndUndefined(obj: any): any {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.filter(item => item !== null && item !== undefined)
|
||||
.map(item => removeNullAndUndefined(item));
|
||||
}
|
||||
if (typeof obj === "object") {
|
||||
const newObj: any = {};
|
||||
for (const key in obj) {
|
||||
const rawValue = obj[key]
|
||||
if(rawValue === null || rawValue === undefined) {
|
||||
continue;
|
||||
}
|
||||
newObj[key] = removeNullAndUndefined(rawValue);
|
||||
}
|
||||
return newObj;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function onTaskInput(val: PartialCodeElement | undefined) {
|
||||
taskObject.value = val;
|
||||
if (isPluginDefaults.value) {
|
||||
@@ -165,7 +184,7 @@
|
||||
};
|
||||
}
|
||||
}
|
||||
modelValue.value = YAML_UTILS.stringify(toRaw(val));
|
||||
modelValue.value = YAML_UTILS.stringify(removeNullAndUndefined(toRaw(val)));
|
||||
}
|
||||
|
||||
function onTaskTypeSelect() {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
:is="componentType"
|
||||
:model-value="element"
|
||||
:task="modelValue"
|
||||
root="array"
|
||||
:root="`${root}[${index}]`"
|
||||
:properties="{}"
|
||||
:schema="props.schema.items"
|
||||
:definitions="props.definitions"
|
||||
@@ -40,7 +40,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, ref} from "vue";
|
||||
import {computed} from "vue";
|
||||
|
||||
import {DeleteOutline, ChevronUp, ChevronDown} from "../../code/utils/icons";
|
||||
|
||||
@@ -56,11 +56,13 @@
|
||||
definitions: any;
|
||||
modelValue?: (string | number | boolean | undefined)[] | string | number | boolean;
|
||||
required?: boolean;
|
||||
root?: string;
|
||||
}>(), {
|
||||
modelValue: undefined,
|
||||
schema: () => ({}),
|
||||
definitions: () => ({}),
|
||||
required: false,
|
||||
root: undefined,
|
||||
});
|
||||
|
||||
const componentType = computed(() => {
|
||||
@@ -68,47 +70,59 @@
|
||||
});
|
||||
|
||||
const needWrapper = computed(() => {
|
||||
return componentType.value.ksTaskName !== "string" &&
|
||||
componentType.value.ksTaskName !== "number" &&
|
||||
componentType.value.ksTaskName !== "boolean" &&
|
||||
componentType.value.ksTaskName !== "expression";
|
||||
return ![
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
"expression",
|
||||
].includes(componentType.value.ksTaskName)
|
||||
});
|
||||
|
||||
const items = ref(
|
||||
const items = computed(() =>
|
||||
props.modelValue === undefined && !props.required
|
||||
// we want to avoid displaying an item completely empty when modelValue is undefined
|
||||
// except if the field is required
|
||||
// we want to avoid displaying an item completely empty when
|
||||
// modelValue is undefined except if the field is required
|
||||
? []
|
||||
: !Array.isArray(props.modelValue) ? [props.modelValue] : props.modelValue,
|
||||
);
|
||||
|
||||
const handleInput = (value: string, index: number) => {
|
||||
items.value[index] = value;
|
||||
emits("update:modelValue", items.value);
|
||||
emits("update:modelValue", items.value.toSpliced(index, 1, value));
|
||||
};
|
||||
|
||||
const newEmptyValue = computed(() => {
|
||||
if (props.schema.items?.type === "string") {
|
||||
return "";
|
||||
}
|
||||
return props.schema.items?.default ?? undefined;
|
||||
})
|
||||
|
||||
const addItem = () => {
|
||||
items.value.push(undefined);
|
||||
emits("update:modelValue", items.value);
|
||||
emits("update:modelValue", [...items.value, newEmptyValue.value]);
|
||||
};
|
||||
|
||||
const removeItem = (index: number) => {
|
||||
items.value.splice(index, 1);
|
||||
emits("update:modelValue", items.value);
|
||||
if (items.value.length <= 1) {
|
||||
emits("update:modelValue", undefined);
|
||||
return;
|
||||
}
|
||||
emits("update:modelValue", items.value.toSpliced(index, 1));
|
||||
};
|
||||
|
||||
const moveItem = (index: number, direction: "up" | "down") => {
|
||||
const tempValue = items.value
|
||||
if (direction === "up" && index > 0) {
|
||||
[items.value[index - 1], items.value[index]] = [
|
||||
items.value[index],
|
||||
items.value[index - 1],
|
||||
[tempValue[index - 1], tempValue[index]] = [
|
||||
tempValue[index],
|
||||
tempValue[index - 1],
|
||||
];
|
||||
} else if (direction === "down" && index < items.value.length - 1) {
|
||||
[items.value[index + 1], items.value[index]] = [
|
||||
items.value[index],
|
||||
items.value[index + 1],
|
||||
} else if (direction === "down" && index < tempValue.length - 1) {
|
||||
[tempValue[index + 1], tempValue[index]] = [
|
||||
tempValue[index],
|
||||
tempValue[index + 1],
|
||||
];
|
||||
}
|
||||
emits("update:modelValue", items.value);
|
||||
emits("update:modelValue", tempValue);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
:schema
|
||||
:definitions
|
||||
:properties="computedProperties"
|
||||
:root="root"
|
||||
:task="task"
|
||||
:required="required"
|
||||
merge
|
||||
@update:model-value="onInput"
|
||||
/>
|
||||
|
||||
@@ -151,6 +151,7 @@
|
||||
"onUpdate:modelValue": (value) => {
|
||||
this.onObjectInput(key, value);
|
||||
},
|
||||
root: this.root,
|
||||
fieldKey: key,
|
||||
task: this.modelValue,
|
||||
schema: schema,
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
const props = defineProps<{
|
||||
schema: any;
|
||||
definitions: any;
|
||||
root?: string;
|
||||
fieldKey: string;
|
||||
task: any;
|
||||
modelValue?: Record<string, any> | string | number | boolean | Array<any>,
|
||||
@@ -80,7 +81,7 @@
|
||||
const taskComponent = templateRef<{resetSelectType?: () => void}>("taskComponent");
|
||||
|
||||
const required = computed(() => {
|
||||
return props.required?.includes(props.fieldKey);
|
||||
return props.required?.includes(props.fieldKey) && props.schema.$required
|
||||
})
|
||||
|
||||
const componentProps = computed(() => {
|
||||
@@ -90,7 +91,7 @@
|
||||
emit("update:modelValue", value);
|
||||
},
|
||||
task: props.task,
|
||||
root: props.fieldKey,
|
||||
root: props.root ? `${props.root}.${props.fieldKey}` : props.fieldKey,
|
||||
schema: props.schema,
|
||||
required: required.value,
|
||||
definitions: props.definitions
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
schema-type="flow"
|
||||
lang="plaintext"
|
||||
input
|
||||
:placeholder="`Your ${root || 'value'} here...`"
|
||||
@update:model-value="onInput"
|
||||
:large-suggestions="false"
|
||||
/>
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, inject} from "vue";
|
||||
import {PARENT_PATH_INJECTION_KEY, REF_PATH_INJECTION_KEY, CREATING_TASK_INJECTION_KEY} from "../../code/injectionKeys";
|
||||
import {
|
||||
PARENT_PATH_INJECTION_KEY,
|
||||
REF_PATH_INJECTION_KEY,
|
||||
CREATING_TASK_INJECTION_KEY
|
||||
} from "../../code/injectionKeys";
|
||||
import Element from "../../code/components/collapse/Element.vue";
|
||||
|
||||
const model = defineModel({
|
||||
@@ -24,7 +28,6 @@
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
root: {
|
||||
type: String,
|
||||
required: true
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable", "ES2021.String"],
|
||||
"lib": ["ES2023.Array", "ES2020", "DOM", "DOM.Iterable", "ES2021.String"],
|
||||
"skipLibCheck": true,
|
||||
"incremental": true,
|
||||
"types": ["vitest/globals"],
|
||||
|
||||
Reference in New Issue
Block a user