diff --git a/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts b/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts index 534c734638fb4..39a9638fa00c7 100644 --- a/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts +++ b/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.test.ts @@ -107,6 +107,31 @@ describe('AssignmentCollection.vue', () => { ); }); + it('does not break with saved assignments that have no ID (legacy)', async () => { + const { findAllByTestId } = renderComponent({ + props: { + value: { + assignments: [ + { name: 'key1', value: 'value1', type: 'string' }, + { name: 'key2', value: 'value2', type: 'string' }, + { name: 'key3', value: 'value3', type: 'string' }, + ], + }, + }, + }); + + let assignments = await findAllByTestId('assignment'); + + expect(assignments.length).toEqual(3); + + // Remove 2nd assignment + await userEvent.click(within(assignments[1]).getByTestId('assignment-remove')); + assignments = await findAllByTestId('assignment'); + expect(assignments.length).toEqual(2); + expect(getInput(within(assignments[0]).getByTestId('assignment-value'))).toHaveValue('value1'); + expect(getInput(within(assignments[1]).getByTestId('assignment-value'))).toHaveValue('value3'); + }); + it('can add assignments by drag and drop (and infer type)', async () => { const { getByTestId, findAllByTestId } = renderComponent(); const dropArea = getByTestId('drop-area'); diff --git a/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue b/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue index 0aebc16bb64fe..d1828c3647f79 100644 --- a/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue +++ b/packages/editor-ui/src/components/AssignmentCollection/AssignmentCollection.vue @@ -8,7 +8,6 @@ import type { INode, INodeProperties, } from 'n8n-workflow'; -import { v4 as uuid } from 'uuid'; import { computed, reactive, watch } from 'vue'; import DropArea from '../DropArea/DropArea.vue'; import ParameterOptions from '../ParameterOptions.vue'; @@ -35,7 +34,11 @@ const i18n = useI18n(); const state = reactive<{ paramValue: AssignmentCollectionValue }>({ paramValue: { - assignments: props.value.assignments ?? [], + assignments: + props.value.assignments?.map((assignment) => { + if (!assignment.id) assignment.id = crypto.randomUUID(); + return assignment; + }) ?? [], }, }); @@ -75,12 +78,17 @@ watch(state.paramValue, (value) => { }); function addAssignment(): void { - state.paramValue.assignments.push({ id: uuid(), name: '', value: '', type: 'string' }); + state.paramValue.assignments.push({ + id: crypto.randomUUID(), + name: '', + value: '', + type: 'string', + }); } function dropAssignment(expression: string): void { state.paramValue.assignments.push({ - id: uuid(), + id: crypto.randomUUID(), name: propertyNameFromExpression(expression), value: `=${expression}`, type: typeFromExpression(expression), diff --git a/packages/editor-ui/src/components/FilterConditions/FilterConditions.vue b/packages/editor-ui/src/components/FilterConditions/FilterConditions.vue index 41ef0f7430ce8..b891b0c3bc98c 100644 --- a/packages/editor-ui/src/components/FilterConditions/FilterConditions.vue +++ b/packages/editor-ui/src/components/FilterConditions/FilterConditions.vue @@ -22,7 +22,6 @@ import { useDebounce } from '@/composables/useDebounce'; import Condition from './Condition.vue'; import CombinatorSelect from './CombinatorSelect.vue'; import { resolveParameter } from '@/composables/useWorkflowHelpers'; -import { v4 as uuid } from 'uuid'; import Draggable from 'vuedraggable'; interface Props { @@ -46,7 +45,12 @@ const { debounce } = useDebounce(); const debouncedEmitChange = debounce(emitChange, { debounceTime: 1000 }); function createCondition(): FilterConditionValue { - return { id: uuid(), leftValue: '', rightValue: '', operator: DEFAULT_OPERATOR_VALUE }; + return { + id: crypto.randomUUID(), + leftValue: '', + rightValue: '', + operator: DEFAULT_OPERATOR_VALUE, + }; } const allowedCombinators = computed( @@ -56,7 +60,10 @@ const allowedCombinators = computed( const state = reactive<{ paramValue: FilterValue }>({ paramValue: { options: props.value?.options ?? DEFAULT_FILTER_OPTIONS, - conditions: props.value?.conditions ?? [createCondition()], + conditions: props.value?.conditions?.map((condition) => { + if (!condition.id) condition.id = crypto.randomUUID(); + return condition; + }) ?? [createCondition()], combinator: props.value?.combinator ?? allowedCombinators.value[0], }, }); @@ -163,8 +170,8 @@ function getIssues(index: number): string[] {