feat(editor): Support pasting an expression into a number parameter (#15722)

This commit is contained in:
Elias Meire
2025-05-30 12:02:38 +02:00
committed by GitHub
parent 7dc94b61cb
commit 2a1475d671
2 changed files with 62 additions and 26 deletions

View File

@@ -224,39 +224,65 @@ describe('ParameterInput.vue', () => {
expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]); expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]);
}); });
test('should correctly handle paste events', async () => { describe('paste events', () => {
const { container, emitted } = renderComponent({ async function paste(input: HTMLInputElement, text: string) {
props: {
path: 'tag',
parameter: {
displayName: 'Tag',
name: 'tag',
type: 'string',
},
modelValue: '',
},
});
const input = container.querySelector('input') as HTMLInputElement;
expect(input).toBeInTheDocument();
await userEvent.click(input);
async function paste(text: string) {
const expression = new DataTransfer(); const expression = new DataTransfer();
expression.setData('text', text); expression.setData('text', text);
await userEvent.clear(input); await userEvent.clear(input);
await userEvent.paste(expression); await userEvent.paste(expression);
} }
await paste('foo'); test('should handle pasting into a string parameter', async () => {
expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]); const { container, emitted } = renderComponent({
props: {
path: 'tag',
parameter: {
displayName: 'Tag',
name: 'tag',
type: 'string',
},
modelValue: '',
},
});
const input = container.querySelector('input') as HTMLInputElement;
expect(input).toBeInTheDocument();
await userEvent.click(input);
await paste('={{ $json.foo }}'); await paste(input, 'foo');
expect(emitted('update')).toContainEqual([ expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]);
expect.objectContaining({ value: '={{ $json.foo }}' }),
]);
await paste('=flDvzj%y1nP'); await paste(input, '={{ $json.foo }}');
expect(emitted('update')).toContainEqual([expect.objectContaining({ value: '==flDvzj%y1nP' })]); expect(emitted('update')).toContainEqual([
expect.objectContaining({ value: '={{ $json.foo }}' }),
]);
await paste(input, '=flDvzj%y1nP');
expect(emitted('update')).toContainEqual([
expect.objectContaining({ value: '==flDvzj%y1nP' }),
]);
});
test('should handle pasting an expression into a number parameter', async () => {
const { container, emitted } = renderComponent({
props: {
path: 'percentage',
parameter: {
displayName: 'Percentage',
name: 'percentage',
type: 'number',
},
modelValue: 1,
},
});
const input = container.querySelector('input') as HTMLInputElement;
expect(input).toBeInTheDocument();
await userEvent.click(input);
await paste(input, '{{ $json.foo }}');
expect(emitted('update')).toContainEqual([
expect.objectContaining({ value: '={{ $json.foo }}' }),
]);
});
}); });
test('should not reset the value of a multi-select with loadOptionsMethod on load', async () => { test('should not reset the value of a multi-select with loadOptionsMethod on load', async () => {

View File

@@ -786,6 +786,16 @@ function onPaste(event: ClipboardEvent) {
} }
} }
function onPasteNumber(event: ClipboardEvent) {
const pastedText = event.clipboardData?.getData('text');
if (shouldConvertToExpression(pastedText)) {
event.preventDefault();
valueChanged('=' + pastedText);
return;
}
}
function onResourceLocatorDrop(data: string) { function onResourceLocatorDrop(data: string) {
emit('drop', data); emit('drop', data);
} }
@@ -1596,7 +1606,7 @@ onUpdated(async () => {
@update:model-value="onUpdateTextInput" @update:model-value="onUpdateTextInput"
@focus="setFocus" @focus="setFocus"
@blur="onBlur" @blur="onBlur"
@keydown.stop @paste="onPasteNumber"
/> />
<CredentialsSelect <CredentialsSelect