mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
Refactor evaluation form and improve error handling in workflow evaluation
• Remove dependency on tagsStore • Add field-specific error handling • Simplify loadTestData and saveTest methods • Update EvaluationEditView component • Improve UI feedback for form errors
This commit is contained in:
parent
3dff63fe93
commit
b8073c70fb
|
@ -1,7 +1,6 @@
|
|||
import { ref, computed } from 'vue';
|
||||
import type { ComponentPublicInstance } from 'vue';
|
||||
import type { INodeParameterResourceLocator } from 'n8n-workflow';
|
||||
import { useAnnotationTagsStore } from '@/stores/tags.store';
|
||||
import { useEvaluationsStore } from '@/stores/evaluations.store.ee';
|
||||
import type AnnotationTagsDropdownEe from '@/components/AnnotationTagsDropdown.ee.vue';
|
||||
import type { N8nInput } from 'n8n-design-system';
|
||||
|
@ -28,9 +27,8 @@ type FormRefs = {
|
|||
tagsInput: ComponentPublicInstance<typeof AnnotationTagsDropdownEe>;
|
||||
};
|
||||
|
||||
export function useEvaluationForm(testId?: number) {
|
||||
export function useEvaluationForm() {
|
||||
// Stores
|
||||
const tagsStore = useAnnotationTagsStore();
|
||||
const evaluationsStore = useEvaluationsStore();
|
||||
|
||||
// Form state
|
||||
|
@ -55,20 +53,16 @@ export function useEvaluationForm(testId?: number) {
|
|||
|
||||
// Loading states
|
||||
const isSaving = ref(false);
|
||||
const isLoading = computed(() => tagsStore.isLoading);
|
||||
const fieldsIssues = ref<Array<{ field: string; message: string }>>([]);
|
||||
|
||||
// Computed
|
||||
const isEditing = computed(() => !!testId);
|
||||
const allTags = computed(() => tagsStore.allTags);
|
||||
const tagsById = computed(() => tagsStore.tagsById);
|
||||
// const isEditing = computed(() => !!testId);
|
||||
|
||||
// Field refs
|
||||
const fields = ref<FormRefs>({} as FormRefs);
|
||||
|
||||
// Methods
|
||||
const loadTestData = async () => {
|
||||
if (!testId) return;
|
||||
|
||||
const loadTestData = async (testId: number) => {
|
||||
try {
|
||||
await evaluationsStore.fetchAll({ force: true });
|
||||
const testDefinition = evaluationsStore.testDefinitionsById[testId];
|
||||
|
@ -99,11 +93,16 @@ export function useEvaluationForm(testId?: number) {
|
|||
}
|
||||
};
|
||||
|
||||
const saveTest = async () => {
|
||||
const saveTest = async (testId?: number) => {
|
||||
if (isSaving.value) return;
|
||||
|
||||
isSaving.value = true;
|
||||
fieldsIssues.value = [];
|
||||
try {
|
||||
if (!state.value.evaluationWorkflow.value) {
|
||||
addFieldIssue('evaluationWorkflow', 'Evaluation workflow is required');
|
||||
}
|
||||
|
||||
const params = {
|
||||
name: state.value.name.value,
|
||||
...(state.value.tags.appliedTagIds[0] && {
|
||||
|
@ -114,7 +113,7 @@ export function useEvaluationForm(testId?: number) {
|
|||
}),
|
||||
};
|
||||
|
||||
if (isEditing.value && testId) {
|
||||
if (testId) {
|
||||
await evaluationsStore.update({
|
||||
id: testId,
|
||||
...params,
|
||||
|
@ -132,6 +131,10 @@ export function useEvaluationForm(testId?: number) {
|
|||
}
|
||||
};
|
||||
|
||||
const addFieldIssue = (field: string, message: string) => {
|
||||
fieldsIssues.value.push({ field, message });
|
||||
};
|
||||
|
||||
const startEditing = async (field: string) => {
|
||||
if (field === 'name') {
|
||||
state.value.name.tempValue = state.value.name.value;
|
||||
|
@ -167,22 +170,12 @@ export function useEvaluationForm(testId?: number) {
|
|||
}
|
||||
};
|
||||
|
||||
const init = async () => {
|
||||
await tagsStore.fetchAll();
|
||||
if (testId) {
|
||||
await loadTestData();
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
state,
|
||||
fields,
|
||||
isEditing,
|
||||
isLoading,
|
||||
isSaving,
|
||||
allTags,
|
||||
tagsById,
|
||||
init,
|
||||
isSaving: computed(() => isSaving.value),
|
||||
fieldsIssues: computed(() => fieldsIssues.value),
|
||||
loadTestData,
|
||||
saveTest,
|
||||
startEditing,
|
||||
saveChanges,
|
||||
|
|
|
@ -10,6 +10,7 @@ import WorkflowSelector from '@/components/WorkflowEvaluation/EditEvaluation/Wor
|
|||
import MetricsInput from '@/components/WorkflowEvaluation/EditEvaluation/MetricsInput.vue';
|
||||
import { useEvaluationForm } from '@/components/WorkflowEvaluation/composables/useEvaluationForm';
|
||||
import { useI18n } from '@/composables/useI18n';
|
||||
import { useAnnotationTagsStore } from '@/stores/tags.store';
|
||||
|
||||
const props = defineProps<{
|
||||
testId?: number;
|
||||
|
@ -20,33 +21,36 @@ const route = useRoute();
|
|||
const locale = useI18n();
|
||||
const testId = computed(() => props.testId ?? (route.params.testId as unknown as number));
|
||||
const buttonLabel = computed(() =>
|
||||
isEditing.value
|
||||
// No testId means we're creating a new one
|
||||
testId.value
|
||||
? locale.baseText('workflowEvaluation.edit.updateTest')
|
||||
: locale.baseText('workflowEvaluation.edit.saveTest'),
|
||||
);
|
||||
const toast = useToast();
|
||||
const {
|
||||
state,
|
||||
isEditing,
|
||||
isLoading,
|
||||
fieldsIssues,
|
||||
isSaving,
|
||||
allTags,
|
||||
tagsById,
|
||||
init,
|
||||
loadTestData,
|
||||
saveTest,
|
||||
startEditing,
|
||||
saveChanges,
|
||||
cancelEditing,
|
||||
handleKeydown,
|
||||
} = useEvaluationForm(testId.value);
|
||||
} = useEvaluationForm();
|
||||
|
||||
onMounted(() => {
|
||||
void init();
|
||||
const { isLoading, allTags, tagsById, fetchAll } = useAnnotationTagsStore();
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchAll();
|
||||
if (testId.value) {
|
||||
await loadTestData(testId.value);
|
||||
}
|
||||
});
|
||||
|
||||
async function onSaveTest() {
|
||||
try {
|
||||
await saveTest();
|
||||
await saveTest(testId.value);
|
||||
toast.showMessage({
|
||||
title: locale.baseText('workflowEvaluation.edit.testSaved'),
|
||||
type: 'success',
|
||||
|
@ -56,12 +60,19 @@ async function onSaveTest() {
|
|||
toast.showError(e, locale.baseText('workflowEvaluation.edit.testSaveFailed'));
|
||||
}
|
||||
}
|
||||
|
||||
function hasIssues(key: string) {
|
||||
const result = fieldsIssues.value.some((issue) => issue.field === key);
|
||||
|
||||
return result;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="$style.container">
|
||||
<EvaluationHeader
|
||||
v-model="state.name"
|
||||
:class="{ 'has-issues': hasIssues('name') }"
|
||||
:start-editing="startEditing"
|
||||
:save-changes="saveChanges"
|
||||
:handle-keydown="handleKeydown"
|
||||
|
@ -71,6 +82,7 @@ async function onSaveTest() {
|
|||
|
||||
<TagsInput
|
||||
v-model="state.tags"
|
||||
:class="{ 'has-issues': hasIssues('tags') }"
|
||||
:all-tags="allTags"
|
||||
:tags-by-id="tagsById"
|
||||
:is-loading="isLoading"
|
||||
|
@ -79,9 +91,12 @@ async function onSaveTest() {
|
|||
:cancel-editing="cancelEditing"
|
||||
/>
|
||||
|
||||
<WorkflowSelector v-model="state.evaluationWorkflow" />
|
||||
<WorkflowSelector
|
||||
v-model="state.evaluationWorkflow"
|
||||
:class="{ 'has-issues': hasIssues('evaluationWorkflow') }"
|
||||
/>
|
||||
|
||||
<MetricsInput v-model="state.metrics" />
|
||||
<MetricsInput v-model="state.metrics" :class="{ 'has-issues': hasIssues('metrics') }" />
|
||||
|
||||
<div :class="$style.footer">
|
||||
<n8n-button type="primary" :label="buttonLabel" :loading="isSaving" @click="onSaveTest" />
|
||||
|
|
Loading…
Reference in a new issue