From 2c4c457348d991167efbad8133cffd86c8723934 Mon Sep 17 00:00:00 2001 From: Oleg Ivaniv Date: Thu, 5 Dec 2024 12:00:14 +0100 Subject: [PATCH] feat(editor): Allow to create new tags during evaluation edit --- .../editor-ui/src/components/TagsDropdown.vue | 35 +++++++++++++++---- .../EditDefinition/TagsInput.vue | 9 ++--- .../TestDefinition/TestDefinitionEditView.vue | 18 ++++++++-- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/packages/editor-ui/src/components/TagsDropdown.vue b/packages/editor-ui/src/components/TagsDropdown.vue index 67799b1657..bb3c75e725 100644 --- a/packages/editor-ui/src/components/TagsDropdown.vue +++ b/packages/editor-ui/src/components/TagsDropdown.vue @@ -16,6 +16,8 @@ interface TagsDropdownProps { allTags: ITag[]; isLoading: boolean; tagsById: Record; + createEnabled?: boolean; + manageEnabled?: boolean; createTag?: (name: string) => Promise; } @@ -27,6 +29,9 @@ const props = withDefaults(defineProps(), { placeholder: '', modelValue: () => [], eventBus: null, + createEnabled: true, + manageEnabled: true, + createTag: undefined, }); const emit = defineEmits<{ @@ -59,6 +64,24 @@ const appliedTags = computed(() => { return props.modelValue.filter((id: string) => props.tagsById[id]); }); +const containerClasses = computed(() => { + return { 'tags-container': true, focused: focused.value }; +}); + +const dropdownClasses = computed(() => { + const classes = ['tags-dropdown', 'tags-dropdown-' + dropdownId]; + + if (props.createEnabled) { + classes.push('tags-dropdown-create-enabled'); + } + + if (props.manageEnabled) { + classes.push('tags-dropdown-manage-enabled'); + } + + return classes.join(' '); +}); + watch( () => props.allTags, () => { @@ -189,7 +212,7 @@ onClickOutside( diff --git a/packages/editor-ui/src/views/TestDefinition/TestDefinitionEditView.vue b/packages/editor-ui/src/views/TestDefinition/TestDefinitionEditView.vue index e17c164472..893eb2bd9b 100644 --- a/packages/editor-ui/src/views/TestDefinition/TestDefinitionEditView.vue +++ b/packages/editor-ui/src/views/TestDefinition/TestDefinitionEditView.vue @@ -24,8 +24,11 @@ const route = useRoute(); const locale = useI18n(); const { debounce } = useDebounce(); const toast = useToast(); -const { isLoading, allTags, tagsById, fetchAll } = useAnnotationTagsStore(); +const tagsStore = useAnnotationTagsStore(); +const isLoading = computed(() => tagsStore.isLoading); +const allTags = computed(() => tagsStore.allTags); +const tagsById = computed(() => tagsStore.tagsById); const testId = computed(() => props.testId ?? (route.params.testId as string)); const currentWorkflowId = computed(() => route.params.name as string); const buttonLabel = computed(() => @@ -48,7 +51,7 @@ const { } = useTestDefinitionForm(); onMounted(async () => { - await fetchAll(); + await tagsStore.fetchAll(); if (testId.value) { await loadTestData(testId.value); } else { @@ -83,6 +86,16 @@ function hasIssues(key: string) { return fieldsIssues.value.some((issue) => issue.field === key); } +async function handleCreateTag(tagName: string) { + try { + const newTag = await tagsStore.create(tagName); + return newTag; + } catch (error) { + toast.showError(error, 'Error', error.message); + throw error; + } +} + watch(() => state.value, debounce(onSaveTest, { debounceTime: 400 }), { deep: true }); @@ -126,6 +139,7 @@ watch(() => state.value, debounce(onSaveTest, { debounceTime: 400 }), { deep: tr :start-editing="startEditing" :save-changes="saveChanges" :cancel-editing="cancelEditing" + :create-tag="handleCreateTag" />