chore(executions): properly handle the label create/update sequence (#13500)

Closes https://github.com/kestra-io/kestra/issues/13498.

Co-authored-by: Miloš Paunović <paun992@hotmail.com>
This commit is contained in:
Shivansh Sharma
2025-12-11 17:21:59 +05:30
committed by GitHub
parent c3861a5532
commit 3af003e5e4

View File

@@ -18,10 +18,10 @@
</template>
<template #footer>
<el-button @click="isOpen = false">
<el-button @click="onCancel">
{{ t("cancel") }}
</el-button>
<el-button type="primary" @click="setLabels()">
<el-button type="primary" :loading="isSaving" @click="setLabels()">
{{ t("ok") }}
</el-button>
</template>
@@ -32,7 +32,7 @@
<el-form-item :label="t('execution labels')">
<LabelInput
v-model:labels="executionLabels"
:existingLabels="execution.labels"
:existingLabels="executionLabels"
/>
</el-form-item>
</el-form>
@@ -86,6 +86,7 @@
const isOpen = ref(false);
const executionLabels = ref<Label[]>([]);
const isSaving = ref(false);
const enabled = computed(() => {
if (
@@ -100,6 +101,12 @@
return !State.isRunning(props.execution.state.current);
});
const onCancel = () => {
// discard temp and close dialog without mutating parent
isOpen.value = false;
executionLabels.value = [];
};
const setLabels = async () => {
const filtered = filterValidLabels(executionLabels.value);
@@ -108,31 +115,42 @@
return;
}
isOpen.value = false;
isSaving.value = true;
try {
const response = await executionsStore.setLabels({
labels: filtered.labels,
executionId: props.execution.id,
});
executionsStore.execution = response.data;
if (response && response.data) {
executionsStore.execution = response.data;
}
toast.success(t("Set labels done"));
// close and clear only after success
isOpen.value = false;
executionLabels.value = [];
} catch (err) {
console.error(err); // Error handling is done by the store/interceptor
console.error(err); // keep dialog open so user can fix / retry
} finally {
isSaving.value = false;
}
};
watch(isOpen, () => {
executionLabels.value = [];
// initialize the temp clone only when opening the dialog
watch(isOpen, (open) => {
if (open) {
const toIgnore = miscStore.configs?.hiddenLabelsPrefixes || [];
const source = props.execution.labels || [];
const toIgnore = miscStore.configs?.hiddenLabelsPrefixes || [];
// deep clone so child edits never mutate the original
executionLabels.value = JSON.parse(JSON.stringify(source || []))
.filter((label: Label) => !toIgnore.some((prefix: string) => label.key?.startsWith(prefix)));
if (props.execution.labels) {
executionLabels.value = props.execution.labels.filter(
(label) =>
!toIgnore.some((prefix: string) =>
label.key?.startsWith(prefix),
),
);
} else {
// when dialog closed, clear temp state (safe-guard)
executionLabels.value = [];
}
});
</script>