refactor(editor): Convert MultipleParameter to composition API (no-changelog) (#11568)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-11-05 19:23:45 +01:00 committed by GitHub
parent 2ed4ce3d7a
commit cb28b5cd60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 159 additions and 118 deletions

View file

@ -0,0 +1,44 @@
import { createTestingPinia } from '@pinia/testing';
import { createComponentRenderer } from '@/__tests__/render';
import MultipleParameter from './MultipleParameter.vue';
describe('MultipleParameter', () => {
const renderComponent = createComponentRenderer(MultipleParameter, {
props: {
path: 'parameters.additionalFields',
parameter: {
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
options: [
{
displayName: 'Currency',
name: 'currency',
type: 'string',
default: 'USD',
},
{
displayName: 'Value',
name: 'value',
type: 'number',
},
],
},
nodeValues: {
parameters: {
additionalFields: {},
},
},
values: [],
isReadOnly: false,
},
pinia: createTestingPinia({ initialState: {} }),
});
it('should render correctly', () => {
const wrapper = renderComponent();
expect(wrapper.html()).toMatchSnapshot();
});
});

View file

@ -1,133 +1,113 @@
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue'; import { ref, watch, computed } from 'vue';
import type { PropType } from 'vue'; import { get } from 'lodash-es';
import type { IUpdateInformation } from '@/Interface';
import type { INodeParameters, INodeProperties } from 'n8n-workflow'; import type { INodeParameters, INodeProperties } from 'n8n-workflow';
import { deepCopy } from 'n8n-workflow'; import { deepCopy } from 'n8n-workflow';
import { useI18n } from '@/composables/useI18n';
import type { IUpdateInformation } from '@/Interface';
import CollectionParameter from '@/components/CollectionParameter.vue'; import CollectionParameter from '@/components/CollectionParameter.vue';
import ParameterInputFull from '@/components/ParameterInputFull.vue'; import ParameterInputFull from '@/components/ParameterInputFull.vue';
import { get } from 'lodash-es'; defineOptions({ name: 'MultipleParameter' });
export default defineComponent({ const props = withDefaults(
name: 'MultipleParameter', defineProps<{
components: { nodeValues: INodeParameters;
CollectionParameter, parameter: INodeProperties;
ParameterInputFull, path: string;
values?: INodeParameters[];
isReadOnly?: boolean;
}>(),
{
values: () => [] as INodeParameters[],
isReadOnly: false,
}, },
props: { );
nodeValues: {
type: Object as PropType<INodeParameters>, const emit = defineEmits<{
required: true, valueChanged: [parameterData: IUpdateInformation];
}>();
const i18n = useI18n();
const mutableValues = ref<INodeParameters[]>(deepCopy(props.values));
watch(
() => props.values,
(newValues) => {
mutableValues.value = deepCopy(newValues);
}, },
parameter: { { deep: true },
type: Object as PropType<INodeProperties>, );
required: true,
}, const addButtonText = computed(() => {
path: { if (!props.parameter.typeOptions || !props.parameter.typeOptions.multipleValueButtonText) {
type: String, return i18n.baseText('multipleParameter.addItem');
required: true,
},
values: {
type: Array as PropType<INodeParameters[]>,
default: () => [],
},
isReadOnly: {
type: Boolean,
default: false,
},
},
data() {
return {
mutableValues: [] as INodeParameters[],
};
},
computed: {
addButtonText(): string {
if (
!this.parameter.typeOptions ||
(this.parameter.typeOptions && !this.parameter.typeOptions.multipleValueButtonText)
) {
return this.$locale.baseText('multipleParameter.addItem');
} }
return this.$locale.nodeText().multipleValueButtonText(this.parameter); return i18n.nodeText().multipleValueButtonText(props.parameter);
}, });
hideDelete(): boolean {
return this.parameter.options?.length === 1;
},
sortable(): boolean {
return !!this.parameter.typeOptions?.sortable;
},
},
watch: {
values: {
handler(newValues: INodeParameters[]) {
this.mutableValues = deepCopy(newValues);
},
deep: true,
},
},
created() {
this.mutableValues = deepCopy(this.values);
},
methods: {
addItem() {
const name = this.getPath();
const currentValue = get(this.nodeValues, name, []) as INodeParameters[];
currentValue.push(deepCopy(this.parameter.default as INodeParameters)); const hideDelete = computed(() => props.parameter.options?.length === 1);
const sortable = computed(() => !!props.parameter.typeOptions?.sortable);
const addItem = () => {
const name = getPath();
const currentValue = get(props.nodeValues, name, []) as INodeParameters[];
currentValue.push(deepCopy(props.parameter.default as INodeParameters));
const parameterData = { const parameterData = {
name, name,
value: currentValue, value: currentValue,
}; };
this.$emit('valueChanged', parameterData); emit('valueChanged', parameterData);
}, };
deleteItem(index: number) {
const deleteItem = (index: number) => {
const parameterData = { const parameterData = {
name: this.getPath(index), name: getPath(index),
value: undefined, value: undefined,
}; };
this.$emit('valueChanged', parameterData); emit('valueChanged', parameterData);
},
getPath(index?: number): string {
return this.path + (index !== undefined ? `[${index}]` : '');
},
moveOptionDown(index: number) {
this.mutableValues.splice(index + 1, 0, this.mutableValues.splice(index, 1)[0]);
const parameterData = {
name: this.path,
value: this.mutableValues,
}; };
this.$emit('valueChanged', parameterData); const getPath = (index?: number) => {
}, return props.path + (index !== undefined ? `[${index}]` : '');
moveOptionUp(index: number) {
this.mutableValues.splice(index - 1, 0, this.mutableValues.splice(index, 1)[0]);
const parameterData = {
name: this.path,
value: this.mutableValues,
}; };
this.$emit('valueChanged', parameterData); const moveOptionDown = (index: number) => {
}, mutableValues.value.splice(index + 1, 0, mutableValues.value.splice(index, 1)[0]);
valueChanged(parameterData: IUpdateInformation) {
this.$emit('valueChanged', parameterData); emit('valueChanged', {
}, name: props.path,
}, value: mutableValues.value,
}); });
};
const moveOptionUp = (index: number) => {
mutableValues.value.splice(index - 1, 0, mutableValues.value.splice(index, 1)[0]);
emit('valueChanged', {
name: props.path,
value: mutableValues.value,
});
};
const valueChanged = (parameterData: IUpdateInformation) => {
emit('valueChanged', parameterData);
};
</script> </script>
<template> <template>
<div class="duplicate-parameter" @keydown.stop> <div class="duplicate-parameter" @keydown.stop>
<n8n-input-label <n8n-input-label
:label="$locale.nodeText().inputLabelDisplayName(parameter, path)" :label="i18n.nodeText().inputLabelDisplayName(parameter, path)"
:tooltip-text="$locale.nodeText().inputLabelDescription(parameter, path)" :tooltip-text="i18n.nodeText().inputLabelDescription(parameter, path)"
:underline="true" :underline="true"
size="small" size="small"
color="text-dark" color="text-dark"
@ -142,7 +122,7 @@ export default defineComponent({
<div v-if="!isReadOnly" class="delete-item clickable"> <div v-if="!isReadOnly" class="delete-item clickable">
<font-awesome-icon <font-awesome-icon
icon="trash" icon="trash"
:title="$locale.baseText('multipleParameter.deleteItem')" :title="i18n.baseText('multipleParameter.deleteItem')"
@click="deleteItem(index)" @click="deleteItem(index)"
/> />
<div v-if="sortable"> <div v-if="sortable">
@ -150,14 +130,14 @@ export default defineComponent({
v-if="index !== 0" v-if="index !== 0"
icon="angle-up" icon="angle-up"
class="clickable" class="clickable"
:title="$locale.baseText('multipleParameter.moveUp')" :title="i18n.baseText('multipleParameter.moveUp')"
@click="moveOptionUp(index)" @click="moveOptionUp(index)"
/> />
<font-awesome-icon <font-awesome-icon
v-if="index !== mutableValues.length - 1" v-if="index !== mutableValues.length - 1"
icon="angle-down" icon="angle-down"
class="clickable" class="clickable"
:title="$locale.baseText('multipleParameter.moveDown')" :title="i18n.baseText('multipleParameter.moveDown')"
@click="moveOptionDown(index)" @click="moveOptionDown(index)"
/> />
</div> </div>
@ -194,7 +174,7 @@ export default defineComponent({
class="no-items-exist" class="no-items-exist"
> >
<n8n-text size="small">{{ <n8n-text size="small">{{
$locale.baseText('multipleParameter.currentlyNoItemsExist') i18n.baseText('multipleParameter.currentlyNoItemsExist')
}}</n8n-text> }}</n8n-text>
</div> </div>
<n8n-button <n8n-button

View file

@ -0,0 +1,17 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`MultipleParameter > should render correctly 1`] = `
"<div data-v-a47e4507="" class="duplicate-parameter">
<div data-v-a47e4507="" class="container" data-test-id="input-label"><label class="n8n-input-label inputLabel heading underline small">
<div class="title"><span class="n8n-text text-dark size-small bold">Additional Fields <!--v-if--></span></div>
<!--v-if-->
<!--v-if-->
<!--v-if-->
</label></div>
<div data-v-a47e4507="" class="add-item-wrapper">
<div data-v-a47e4507="" class="no-items-exist"><span data-v-a47e4507="" class="n8n-text size-small regular">Currently no items exist</span></div><button data-v-a47e4507="" class="button button tertiary medium block" aria-live="polite">
<!--v-if--><span>Add item</span>
</button>
</div>
</div>"
`;