mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
fix(editor): Render assignments without ID correctly (#13252)
This commit is contained in:
parent
66acb1bcb6
commit
d116f121e3
|
@ -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 () => {
|
it('can add assignments by drag and drop (and infer type)', async () => {
|
||||||
const { getByTestId, findAllByTestId } = renderComponent();
|
const { getByTestId, findAllByTestId } = renderComponent();
|
||||||
const dropArea = getByTestId('drop-area');
|
const dropArea = getByTestId('drop-area');
|
||||||
|
|
|
@ -8,7 +8,6 @@ import type {
|
||||||
INode,
|
INode,
|
||||||
INodeProperties,
|
INodeProperties,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
import { computed, reactive, watch } from 'vue';
|
import { computed, reactive, watch } from 'vue';
|
||||||
import DropArea from '../DropArea/DropArea.vue';
|
import DropArea from '../DropArea/DropArea.vue';
|
||||||
import ParameterOptions from '../ParameterOptions.vue';
|
import ParameterOptions from '../ParameterOptions.vue';
|
||||||
|
@ -35,7 +34,11 @@ const i18n = useI18n();
|
||||||
|
|
||||||
const state = reactive<{ paramValue: AssignmentCollectionValue }>({
|
const state = reactive<{ paramValue: AssignmentCollectionValue }>({
|
||||||
paramValue: {
|
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 {
|
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 {
|
function dropAssignment(expression: string): void {
|
||||||
state.paramValue.assignments.push({
|
state.paramValue.assignments.push({
|
||||||
id: uuid(),
|
id: crypto.randomUUID(),
|
||||||
name: propertyNameFromExpression(expression),
|
name: propertyNameFromExpression(expression),
|
||||||
value: `=${expression}`,
|
value: `=${expression}`,
|
||||||
type: typeFromExpression(expression),
|
type: typeFromExpression(expression),
|
||||||
|
|
|
@ -22,7 +22,6 @@ import { useDebounce } from '@/composables/useDebounce';
|
||||||
import Condition from './Condition.vue';
|
import Condition from './Condition.vue';
|
||||||
import CombinatorSelect from './CombinatorSelect.vue';
|
import CombinatorSelect from './CombinatorSelect.vue';
|
||||||
import { resolveParameter } from '@/composables/useWorkflowHelpers';
|
import { resolveParameter } from '@/composables/useWorkflowHelpers';
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
import Draggable from 'vuedraggable';
|
import Draggable from 'vuedraggable';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -46,7 +45,12 @@ const { debounce } = useDebounce();
|
||||||
const debouncedEmitChange = debounce(emitChange, { debounceTime: 1000 });
|
const debouncedEmitChange = debounce(emitChange, { debounceTime: 1000 });
|
||||||
|
|
||||||
function createCondition(): FilterConditionValue {
|
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<FilterTypeCombinator[]>(
|
const allowedCombinators = computed<FilterTypeCombinator[]>(
|
||||||
|
@ -56,7 +60,10 @@ const allowedCombinators = computed<FilterTypeCombinator[]>(
|
||||||
const state = reactive<{ paramValue: FilterValue }>({
|
const state = reactive<{ paramValue: FilterValue }>({
|
||||||
paramValue: {
|
paramValue: {
|
||||||
options: props.value?.options ?? DEFAULT_FILTER_OPTIONS,
|
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],
|
combinator: props.value?.combinator ?? allowedCombinators.value[0],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -163,8 +170,8 @@ function getIssues(index: number): string[] {
|
||||||
<div :class="$style.content">
|
<div :class="$style.content">
|
||||||
<div :class="$style.conditions">
|
<div :class="$style.conditions">
|
||||||
<Draggable
|
<Draggable
|
||||||
item-key="id"
|
|
||||||
v-model="state.paramValue.conditions"
|
v-model="state.paramValue.conditions"
|
||||||
|
item-key="id"
|
||||||
handle=".drag-handle"
|
handle=".drag-handle"
|
||||||
:drag-class="$style.dragging"
|
:drag-class="$style.dragging"
|
||||||
:ghost-class="$style.ghost"
|
:ghost-class="$style.ghost"
|
||||||
|
|
Loading…
Reference in a new issue