diff --git a/cypress/e2e/26-resource-locator.cy.ts b/cypress/e2e/26-resource-locator.cy.ts index 60d33374d7..9cea4e25a3 100644 --- a/cypress/e2e/26-resource-locator.cy.ts +++ b/cypress/e2e/26-resource-locator.cy.ts @@ -1,5 +1,5 @@ import { WorkflowPage, NDV, CredentialsModal } from '../pages'; -import { getPopper, getVisiblePopper, getVisibleSelect } from '../utils'; +import { getVisiblePopper, getVisibleSelect } from '../utils'; const workflowPage = new WorkflowPage(); const ndv = new NDV(); @@ -66,6 +66,8 @@ describe('Resource Locator', () => { workflowPage.actions.addInitialNodeToCanvas('E2e Test', { action: 'Resource Locator' }); ndv.getters.resourceLocatorInput('rlc').click(); + + cy.getByTestId('rlc-item').should('exist'); getVisiblePopper() .should('have.length', 1) .findChildByTestId('rlc-item') @@ -73,9 +75,11 @@ describe('Resource Locator', () => { ndv.actions.setInvalidExpression({ fieldName: 'fieldId' }); - ndv.getters.container().click(); // remove focus from input, hide expression preview + ndv.getters.nodeParameters().click(); // remove focus from input, hide expression preview ndv.getters.resourceLocatorInput('rlc').click(); + + cy.getByTestId('rlc-item').should('exist'); getVisiblePopper() .should('have.length', 1) .findChildByTestId('rlc-item') diff --git a/cypress/e2e/5-ndv.cy.ts b/cypress/e2e/5-ndv.cy.ts index 0599d4798d..14097255f2 100644 --- a/cypress/e2e/5-ndv.cy.ts +++ b/cypress/e2e/5-ndv.cy.ts @@ -302,7 +302,7 @@ describe('NDV', () => { ndv.actions.setInvalidExpression({ fieldName: 'fieldId', delay: 200 }); - ndv.getters.container().click(); // remove focus from input, hide expression preview + ndv.getters.nodeParameters().click(); // remove focus from input, hide expression preview ndv.getters.parameterInput('remoteOptions').click(); @@ -320,7 +320,7 @@ describe('NDV', () => { ndv.actions.setInvalidExpression({ fieldName: 'otherField', delay: 50 }); - ndv.getters.container().click(); // remove focus from input, hide expression preview + ndv.getters.nodeParameters().click(); // remove focus from input, hide expression preview ndv.getters.parameterInput('remoteOptions').click(); getVisibleSelect().find('.el-select-dropdown__item').should('have.length', 3); @@ -360,6 +360,15 @@ describe('NDV', () => { ndv.getters.nodeExecuteButton().should('be.visible'); }); + it('should allow editing code in fullscreen in the Code node', () => { + workflowPage.actions.addInitialNodeToCanvas('Code', { keepNdvOpen: true }); + ndv.actions.openCodeEditorFullscreen(); + + ndv.getters.codeEditorFullscreen().type('{selectall}').type('{backspace}').type('foo()'); + ndv.getters.codeEditorDialog().find('.el-dialog__close').click(); + ndv.getters.parameterInput('jsCode').get('.cm-content').should('contain.text', 'foo()'); + }); + it('should not retrieve remote options when a parameter value changes', () => { cy.intercept('/rest/dynamic-node-parameters/options?**', cy.spy().as('fetchParameterOptions')); workflowPage.actions.addInitialNodeToCanvas('E2e Test', { action: 'Remote Options' }); @@ -370,106 +379,126 @@ describe('NDV', () => { }); describe('floating nodes', () => { - function getFloatingNodeByPosition(position: 'inputMain' | 'outputMain' | 'outputSub'| 'inputSub') { + function getFloatingNodeByPosition( + position: 'inputMain' | 'outputMain' | 'outputSub' | 'inputSub', + ) { return cy.get(`[data-node-placement=${position}]`); } beforeEach(() => { cy.createFixtureWorkflow('Floating_Nodes.json', `Floating Nodes`); - workflowPage.getters.canvasNodes().first().dblclick() - getFloatingNodeByPosition("inputMain").should('not.exist'); - getFloatingNodeByPosition("outputMain").should('exist'); + workflowPage.getters.canvasNodes().first().dblclick(); + getFloatingNodeByPosition('inputMain').should('not.exist'); + getFloatingNodeByPosition('outputMain').should('exist'); }); it('should traverse floating nodes with mouse', () => { // Traverse 4 connected node forwards - Array.from(Array(4).keys()).forEach(i => { - getFloatingNodeByPosition("outputMain").click({ force: true}); + Array.from(Array(4).keys()).forEach((i) => { + getFloatingNodeByPosition('outputMain').click({ force: true }); ndv.getters.nodeNameContainer().should('contain', `Node ${i + 1}`); - getFloatingNodeByPosition("inputMain").should('exist'); - getFloatingNodeByPosition("outputMain").should('exist'); + getFloatingNodeByPosition('inputMain').should('exist'); + getFloatingNodeByPosition('outputMain').should('exist'); ndv.actions.close(); workflowPage.getters.selectedNodes().should('have.length', 1); - workflowPage.getters.selectedNodes().first().should('contain', `Node ${i + 1}`); + workflowPage.getters + .selectedNodes() + .first() + .should('contain', `Node ${i + 1}`); workflowPage.getters.selectedNodes().first().dblclick(); - }) + }); - getFloatingNodeByPosition("outputMain").click({ force: true}); + getFloatingNodeByPosition('outputMain').click({ force: true }); ndv.getters.nodeNameContainer().should('contain', 'Chain'); - getFloatingNodeByPosition("inputSub").should('exist'); - getFloatingNodeByPosition("inputSub").click({ force: true}); + getFloatingNodeByPosition('inputSub').should('exist'); + getFloatingNodeByPosition('inputSub').click({ force: true }); ndv.getters.nodeNameContainer().should('contain', 'Model'); - getFloatingNodeByPosition("inputSub").should('not.exist'); - getFloatingNodeByPosition("inputMain").should('not.exist'); - getFloatingNodeByPosition("outputMain").should('not.exist'); - getFloatingNodeByPosition("outputSub").should('exist'); + getFloatingNodeByPosition('inputSub').should('not.exist'); + getFloatingNodeByPosition('inputMain').should('not.exist'); + getFloatingNodeByPosition('outputMain').should('not.exist'); + getFloatingNodeByPosition('outputSub').should('exist'); ndv.actions.close(); workflowPage.getters.selectedNodes().should('have.length', 1); workflowPage.getters.selectedNodes().first().should('contain', 'Model'); workflowPage.getters.selectedNodes().first().dblclick(); - getFloatingNodeByPosition("outputSub").click({ force: true}); + getFloatingNodeByPosition('outputSub').click({ force: true }); ndv.getters.nodeNameContainer().should('contain', 'Chain'); // Traverse 4 connected node backwards - Array.from(Array(4).keys()).forEach(i => { - getFloatingNodeByPosition("inputMain").click({ force: true}); - ndv.getters.nodeNameContainer().should('contain', `Node ${4 - (i)}`); - getFloatingNodeByPosition("outputMain").should('exist'); - getFloatingNodeByPosition("inputMain").should('exist'); - }) - getFloatingNodeByPosition("inputMain").click({ force: true}); - workflowPage.getters.selectedNodes().first().should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); - getFloatingNodeByPosition("inputMain").should('not.exist'); - getFloatingNodeByPosition("inputSub").should('not.exist'); - getFloatingNodeByPosition("outputSub").should('not.exist'); + Array.from(Array(4).keys()).forEach((i) => { + getFloatingNodeByPosition('inputMain').click({ force: true }); + ndv.getters.nodeNameContainer().should('contain', `Node ${4 - i}`); + getFloatingNodeByPosition('outputMain').should('exist'); + getFloatingNodeByPosition('inputMain').should('exist'); + }); + getFloatingNodeByPosition('inputMain').click({ force: true }); + workflowPage.getters + .selectedNodes() + .first() + .should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); + getFloatingNodeByPosition('inputMain').should('not.exist'); + getFloatingNodeByPosition('inputSub').should('not.exist'); + getFloatingNodeByPosition('outputSub').should('not.exist'); ndv.actions.close(); workflowPage.getters.selectedNodes().should('have.length', 1); - workflowPage.getters.selectedNodes().first().should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); + workflowPage.getters + .selectedNodes() + .first() + .should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); }); it('should traverse floating nodes with mouse', () => { // Traverse 4 connected node forwards - Array.from(Array(4).keys()).forEach(i => { - cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowRight']) + Array.from(Array(4).keys()).forEach((i) => { + cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowRight']); ndv.getters.nodeNameContainer().should('contain', `Node ${i + 1}`); - getFloatingNodeByPosition("inputMain").should('exist'); - getFloatingNodeByPosition("outputMain").should('exist'); + getFloatingNodeByPosition('inputMain').should('exist'); + getFloatingNodeByPosition('outputMain').should('exist'); ndv.actions.close(); workflowPage.getters.selectedNodes().should('have.length', 1); - workflowPage.getters.selectedNodes().first().should('contain', `Node ${i + 1}`); + workflowPage.getters + .selectedNodes() + .first() + .should('contain', `Node ${i + 1}`); workflowPage.getters.selectedNodes().first().dblclick(); - }) + }); - cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowRight']) + cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowRight']); ndv.getters.nodeNameContainer().should('contain', 'Chain'); - getFloatingNodeByPosition("inputSub").should('exist'); - cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowDown']) + getFloatingNodeByPosition('inputSub').should('exist'); + cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowDown']); ndv.getters.nodeNameContainer().should('contain', 'Model'); - getFloatingNodeByPosition("inputSub").should('not.exist'); - getFloatingNodeByPosition("inputMain").should('not.exist'); - getFloatingNodeByPosition("outputMain").should('not.exist'); - getFloatingNodeByPosition("outputSub").should('exist'); + getFloatingNodeByPosition('inputSub').should('not.exist'); + getFloatingNodeByPosition('inputMain').should('not.exist'); + getFloatingNodeByPosition('outputMain').should('not.exist'); + getFloatingNodeByPosition('outputSub').should('exist'); ndv.actions.close(); workflowPage.getters.selectedNodes().should('have.length', 1); workflowPage.getters.selectedNodes().first().should('contain', 'Model'); workflowPage.getters.selectedNodes().first().dblclick(); - cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowUp']) + cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowUp']); ndv.getters.nodeNameContainer().should('contain', 'Chain'); // Traverse 4 connected node backwards - Array.from(Array(4).keys()).forEach(i => { - cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowLeft']) - ndv.getters.nodeNameContainer().should('contain', `Node ${4 - (i)}`); - getFloatingNodeByPosition("outputMain").should('exist'); - getFloatingNodeByPosition("inputMain").should('exist'); - }) - cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowLeft']) - workflowPage.getters.selectedNodes().first().should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); - getFloatingNodeByPosition("inputMain").should('not.exist'); - getFloatingNodeByPosition("inputSub").should('not.exist'); - getFloatingNodeByPosition("outputSub").should('not.exist'); + Array.from(Array(4).keys()).forEach((i) => { + cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowLeft']); + ndv.getters.nodeNameContainer().should('contain', `Node ${4 - i}`); + getFloatingNodeByPosition('outputMain').should('exist'); + getFloatingNodeByPosition('inputMain').should('exist'); + }); + cy.realPress(['ShiftLeft', 'Meta', 'AltLeft', 'ArrowLeft']); + workflowPage.getters + .selectedNodes() + .first() + .should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); + getFloatingNodeByPosition('inputMain').should('not.exist'); + getFloatingNodeByPosition('inputSub').should('not.exist'); + getFloatingNodeByPosition('outputSub').should('not.exist'); ndv.actions.close(); workflowPage.getters.selectedNodes().should('have.length', 1); - workflowPage.getters.selectedNodes().first().should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); + workflowPage.getters + .selectedNodes() + .first() + .should('contain', MANUAL_TRIGGER_NODE_DISPLAY_NAME); }); }); @@ -501,23 +530,34 @@ describe('NDV', () => { ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Table'); - ndv.getters.outputTableRow(1).should('include.text', ' '); + ndv.getters + .outputTableRow(1) + .should('include.text', ' '); cy.document().trigger('keyup', { key: '/' }); ndv.getters.searchInput().filter(':focus').type(' Introduction to XML John Doe 2020 1234567890 Data Science Basics Jane Smith 2019 0987654321 Programming in Python Bob Johnson 2021 5432109876 "}]'); - ndv.getters.outputDataContainer().find('mark').should('have.text', ' Introduction to XML John Doe 2020 1234567890 Data Science Basics Jane Smith 2019 0987654321 Programming in Python Bob Johnson 2021 5432109876 "}]', + ); + ndv.getters.outputDataContainer().find('mark').should('have.text', ' span').should('include.text', ''); + ndv.getters.outputDisplayMode().find('label').eq(2).click({ force: true }); + ndv.getters + .outputDataContainer() + .findChildByTestId('run-data-schema-item') + .find('> span') + .should('include.text', ''); }); it('should properly show node execution indicator', () => { @@ -546,7 +586,10 @@ describe('NDV', () => { }); it('Should handle mismatched option attributes', () => { - workflowPage.actions.addInitialNodeToCanvas('LDAP', { keepNdvOpen: true, action: 'Create a new entry' }); + workflowPage.actions.addInitialNodeToCanvas('LDAP', { + keepNdvOpen: true, + action: 'Create a new entry', + }); // Add some attributes in Create operation cy.getByTestId('parameter-item').contains('Add Attributes').click(); ndv.actions.changeNodeOperation('Update'); @@ -556,7 +599,10 @@ describe('NDV', () => { it('Should keep RLC values after operation change', () => { const TEST_DOC_ID = '1111'; - workflowPage.actions.addInitialNodeToCanvas('Google Sheets', { keepNdvOpen: true, action: 'Append row in sheet' }); + workflowPage.actions.addInitialNodeToCanvas('Google Sheets', { + keepNdvOpen: true, + action: 'Append row in sheet', + }); ndv.actions.setRLCValue('documentId', TEST_DOC_ID); ndv.actions.changeNodeOperation('Update Row'); ndv.getters.resourceLocatorInput('documentId').find('input').should('have.value', TEST_DOC_ID); diff --git a/cypress/pages/ndv.ts b/cypress/pages/ndv.ts index 66116b0fc4..449ad75eb4 100644 --- a/cypress/pages/ndv.ts +++ b/cypress/pages/ndv.ts @@ -98,6 +98,9 @@ export class NDV extends BasePage { pagination: () => cy.getByTestId('ndv-data-pagination'), nodeVersion: () => cy.getByTestId('node-version'), nodeSettingsTab: () => cy.getByTestId('tab-settings'), + codeEditorFullscreenButton: () => cy.getByTestId('code-editor-fullscreen-button'), + codeEditorDialog: () => cy.getByTestId('code-editor-fullscreen'), + codeEditorFullscreen: () => this.getters.codeEditorDialog().find('.cm-content'), nodeRunSuccessIndicator: () => cy.getByTestId('node-run-info-success'), nodeRunErrorIndicator: () => cy.getByTestId('node-run-info-danger'), }; @@ -251,9 +254,15 @@ export class NDV extends BasePage { openSettings: () => { this.getters.nodeSettingsTab().click(); }, + + openCodeEditorFullscreen: () => { + this.getters.codeEditorFullscreenButton().click({ force: true }); + }, changeNodeOperation: (operation: string) => { this.getters.parameterInput('operation').click(); - cy.get('.el-select-dropdown__item').contains(new RegExp(`^${operation}$`)).click({ force: true }); + cy.get('.el-select-dropdown__item') + .contains(new RegExp(`^${operation}$`)) + .click({ force: true }); this.getters.parameterInput('operation').find('input').should('have.value', operation); }, }; diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 6a0f122464..23460c365f 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -160,6 +160,7 @@ Cypress.Commands.add('draganddrop', (draggableSelector, droppableSelector) => { cy.get(draggableSelector).trigger('mousedown'); } // We don't chain these commands to make sure cy.get is re-trying correctly + cy.get(droppableSelector).realMouseMove(0, 0); cy.get(droppableSelector).realMouseMove(pageX, pageY); cy.get(droppableSelector).realHover(); cy.get(droppableSelector).realMouseUp(); diff --git a/packages/design-system/src/css/dialog.scss b/packages/design-system/src/css/dialog.scss index e7bc062106..2ddb2bfcde 100644 --- a/packages/design-system/src/css/dialog.scss +++ b/packages/design-system/src/css/dialog.scss @@ -18,7 +18,8 @@ height: 100%; display: flex; flex-direction: column; - align-items: inherit; + align-items: center; + justify-content: center; overflow-x: hidden; overflow-y: auto; } @@ -60,7 +61,6 @@ @include mixins.e(header) { padding: var.$dialog-padding-primary; - padding-bottom: 0px; } @include mixins.e(headerbtn) { @@ -95,6 +95,7 @@ @include mixins.e(body) { padding: var.$dialog-padding-primary; + padding-top: 0; color: var(--color-text-base); } diff --git a/packages/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue b/packages/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue index 9827cd5567..d45468210b 100644 --- a/packages/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue +++ b/packages/editor-ui/src/components/CodeNodeEditor/CodeNodeEditor.vue @@ -17,7 +17,11 @@ name="code" data-test-id="code-node-tab-code" > -
+
+ -
+
+
+ +
@@ -82,6 +89,10 @@ export default defineComponent({ type: Boolean, default: false, }, + fillParent: { + type: Boolean, + default: false, + }, mode: { type: String as PropType, validator: (value: CodeExecutionMode): boolean => CODE_EXECUTION_MODES.includes(value), @@ -193,7 +204,12 @@ export default defineComponent({ ...readOnlyEditorExtensions, EditorState.readOnly.of(isReadOnly), EditorView.editable.of(!isReadOnly), - codeNodeEditorTheme({ isReadOnly, customMinHeight: this.rows }), + codeNodeEditorTheme({ + isReadOnly, + maxHeight: this.fillParent ? '100%' : '40vh', + minHeight: '20vh', + rows: this.rows, + }), ]; if (!isReadOnly) { @@ -384,15 +400,9 @@ export default defineComponent({ diff --git a/packages/editor-ui/src/components/CodeNodeEditor/baseExtensions.ts b/packages/editor-ui/src/components/CodeNodeEditor/baseExtensions.ts index 45855d3bc4..bed55df677 100644 --- a/packages/editor-ui/src/components/CodeNodeEditor/baseExtensions.ts +++ b/packages/editor-ui/src/components/CodeNodeEditor/baseExtensions.ts @@ -6,12 +6,14 @@ import { highlightSpecialChars, keymap, lineNumbers, + type KeyBinding, } from '@codemirror/view'; import { bracketMatching, foldGutter, indentOnInput } from '@codemirror/language'; -import { acceptCompletion } from '@codemirror/autocomplete'; +import { acceptCompletion, selectedCompletion } from '@codemirror/autocomplete'; import { history, - indentWithTab, + indentLess, + indentMore, insertNewlineAndIndent, toggleComment, redo, @@ -19,7 +21,7 @@ import { undo, } from '@codemirror/commands'; import { lintGutter } from '@codemirror/lint'; -import type { Extension } from '@codemirror/state'; +import { type Extension, Prec } from '@codemirror/state'; import { codeInputHandler } from '@/plugins/codemirror/inputHandlers/code.inputHandler'; @@ -29,6 +31,42 @@ export const readOnlyEditorExtensions: readonly Extension[] = [ highlightSpecialChars(), ]; +export const tabKeyMap: KeyBinding[] = [ + { + any(editor, event) { + if (event.key === 'Tab' || (event.key === 'Escape' && selectedCompletion(editor.state))) { + event.stopPropagation(); + } + + return false; + }, + }, + { + key: 'Tab', + run: (editor) => { + if (selectedCompletion(editor.state)) { + return acceptCompletion(editor); + } + + return indentMore(editor); + }, + }, + { key: 'Shift-Tab', run: indentLess }, +]; + +export const enterKeyMap: KeyBinding[] = [ + { + key: 'Enter', + run: (editor) => { + if (selectedCompletion(editor.state)) { + return acceptCompletion(editor); + } + + return insertNewlineAndIndent(editor); + }, + }, +]; + export const writableEditorExtensions: readonly Extension[] = [ history(), lintGutter(), @@ -39,14 +77,14 @@ export const writableEditorExtensions: readonly Extension[] = [ bracketMatching(), highlightActiveLine(), highlightActiveLineGutter(), - keymap.of([ - { key: 'Enter', run: insertNewlineAndIndent }, - { key: 'Tab', run: acceptCompletion }, - { key: 'Enter', run: acceptCompletion }, - { key: 'Mod-/', run: toggleComment }, - { key: 'Mod-z', run: undo }, - { key: 'Mod-Shift-z', run: redo }, - { key: 'Backspace', run: deleteCharBackward, shift: deleteCharBackward }, - indentWithTab, - ]), + Prec.highest( + keymap.of([ + ...tabKeyMap, + ...enterKeyMap, + { key: 'Mod-/', run: toggleComment }, + { key: 'Mod-z', run: undo }, + { key: 'Mod-Shift-z', run: redo }, + { key: 'Backspace', run: deleteCharBackward, shift: deleteCharBackward }, + ]), + ), ]; diff --git a/packages/editor-ui/src/components/CodeNodeEditor/theme.ts b/packages/editor-ui/src/components/CodeNodeEditor/theme.ts index 64184abd7d..b39c310ab4 100644 --- a/packages/editor-ui/src/components/CodeNodeEditor/theme.ts +++ b/packages/editor-ui/src/components/CodeNodeEditor/theme.ts @@ -29,14 +29,18 @@ const BASE_STYLING = { interface ThemeSettings { isReadOnly?: boolean; - customMaxHeight?: string; - customMinHeight?: number; + maxHeight?: string; + minHeight?: string; + rows?: number; + highlightColors?: 'default' | 'html'; } export const codeNodeEditorTheme = ({ isReadOnly, - customMaxHeight, - customMinHeight, + minHeight, + maxHeight, + rows, + highlightColors, }: ThemeSettings) => [ EditorView.theme({ '&': { @@ -85,11 +89,13 @@ export const codeNodeEditorTheme = ({ }, '.cm-scroller': { overflow: 'auto', - - maxHeight: customMaxHeight ?? '100%', + maxHeight: maxHeight ?? '100%', ...(isReadOnly ? {} - : { minHeight: customMinHeight ? `${Number(customMinHeight) * 1.3}em` : '10em' }), + : { minHeight: rows && rows !== -1 ? `${Number(rows + 1) * 1.3}em` : 'auto' }), + }, + '.cm-gutter,.cm-content': { + minHeight: rows && rows !== -1 ? 'auto' : minHeight ?? 'calc(35vh - var(--spacing-2xl))', }, '.cm-diagnosticAction': { backgroundColor: BASE_STYLING.diagnosticButton.backgroundColor, @@ -106,47 +112,97 @@ export const codeNodeEditorTheme = ({ color: 'var(--color-text-base)', }, }), - syntaxHighlighting( - HighlightStyle.define([ - { - tag: tags.comment, - color: 'var(--color-code-tags-comment)', - }, - { - tag: [tags.string, tags.special(tags.brace)], - color: 'var(--color-code-tags-string)', - }, - { - tag: [tags.number, tags.self, tags.bool, tags.null], - color: 'var(--color-code-tags-primitive)', - }, - { - tag: tags.keyword, - color: 'var(--color-code-tags-keyword)', - }, - { - tag: tags.operator, - color: 'var(--color-code-tags-operator)', - }, - { - tag: [ - tags.variableName, - tags.propertyName, - tags.attributeName, - tags.regexp, - tags.className, - tags.typeName, - ], - color: 'var(--color-code-tags-variable)', - }, - { - tag: [ - tags.definition(tags.typeName), - tags.definition(tags.propertyName), - tags.function(tags.variableName), - ], - color: 'var(--color-code-tags-definition)', - }, - ]), - ), + highlightColors === 'html' + ? syntaxHighlighting( + HighlightStyle.define([ + { tag: tags.keyword, color: '#c678dd' }, + { + tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], + color: '#e06c75', + }, + { tag: [tags.function(tags.variableName), tags.labelName], color: '#61afef' }, + { + tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], + color: '#d19a66', + }, + { tag: [tags.definition(tags.name), tags.separator], color: '#abb2bf' }, + { + tag: [ + tags.typeName, + tags.className, + tags.number, + tags.changed, + tags.annotation, + tags.modifier, + tags.self, + tags.namespace, + ], + color: '#e06c75', + }, + { + tag: [ + tags.operator, + tags.operatorKeyword, + tags.url, + tags.escape, + tags.regexp, + tags.link, + tags.special(tags.string), + ], + color: '#56b6c2', + }, + { tag: [tags.meta, tags.comment], color: '#7d8799' }, + { tag: tags.strong, fontWeight: 'bold' }, + { tag: tags.emphasis, fontStyle: 'italic' }, + { tag: tags.strikethrough, textDecoration: 'line-through' }, + { tag: tags.link, color: '#7d8799', textDecoration: 'underline' }, + { tag: tags.heading, fontWeight: 'bold', color: '#e06c75' }, + { tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: '#d19a66' }, + { tag: [tags.processingInstruction, tags.string, tags.inserted], color: '#98c379' }, + { tag: tags.invalid, color: 'red', 'font-weight': 'bold' }, + ]), + ) + : syntaxHighlighting( + HighlightStyle.define([ + { + tag: tags.comment, + color: 'var(--color-code-tags-comment)', + }, + { + tag: [tags.string, tags.special(tags.brace)], + color: 'var(--color-code-tags-string)', + }, + { + tag: [tags.number, tags.self, tags.bool, tags.null], + color: 'var(--color-code-tags-primitive)', + }, + { + tag: tags.keyword, + color: 'var(--color-code-tags-keyword)', + }, + { + tag: tags.operator, + color: 'var(--color-code-tags-operator)', + }, + { + tag: [ + tags.variableName, + tags.propertyName, + tags.attributeName, + tags.regexp, + tags.className, + tags.typeName, + ], + color: 'var(--color-code-tags-variable)', + }, + { + tag: [ + tags.definition(tags.typeName), + tags.definition(tags.propertyName), + tags.function(tags.variableName), + ], + color: 'var(--color-code-tags-definition)', + }, + ]), + ), ]; diff --git a/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue b/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue index 1b91d9c00d..5aba6b063a 100644 --- a/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue +++ b/packages/editor-ui/src/components/HtmlEditor/HtmlEditor.vue @@ -1,44 +1,48 @@ - + diff --git a/packages/editor-ui/src/components/HtmlEditor/theme.ts b/packages/editor-ui/src/components/HtmlEditor/theme.ts deleted file mode 100644 index 78e90039ad..0000000000 --- a/packages/editor-ui/src/components/HtmlEditor/theme.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'; -import { EditorView } from '@codemirror/view'; -import { tags } from '@lezer/highlight'; - -export const theme = ({ isReadOnly }: { isReadOnly: boolean }) => [ - EditorView.theme({ - '&': { - 'font-size': '0.8em', - border: 'var(--border-base)', - borderRadius: 'var(--border-radius-base)', - backgroundColor: 'var(--color-code-background)', - color: 'var(--color-code-foreground)', - }, - '.cm-content': { - fontFamily: "Menlo, Consolas, 'DejaVu Sans Mono', monospace !important", - caretColor: 'var(--color-code-caret)', - }, - '.cm-cursor, .cm-dropCursor': { - borderLeftColor: 'var(--color-code-caret)', - }, - '&.cm-editor': { - ...(isReadOnly ? { backgroundColor: 'var(--color-code-background-readonly)' } : {}), - borderColor: 'var(--border-color-base)', - }, - '&.cm-editor.cm-focused': { - outline: '0', - }, - '&.cm-focused .cm-selectionBackgroundm .cm-selectionBackground, .cm-content ::selection': { - backgroundColor: 'var(--color-code-selection)', - }, - '.cm-activeLine': { - backgroundColor: 'var(--color-code-lineHighlight)', - }, - '.cm-activeLineGutter': { - backgroundColor: 'var(--color-code-lineHighlight)', - }, - '.cm-gutters': { - backgroundColor: isReadOnly - ? 'var(--color-code-background-readonly)' - : 'var(--color-code-gutterBackground)', - color: 'var(--color-code-gutterForeground)', - borderTopLeftRadius: 'var(--border-radius-base)', - borderBottomLeftRadius: 'var(--border-radius-base)', - borderRightColor: 'var(--border-color-base)', - }, - '.cm-scroller': { - overflow: 'auto', - maxHeight: '350px', - }, - }), - syntaxHighlighting( - HighlightStyle.define([ - { tag: tags.keyword, color: '#c678dd' }, - { - tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], - color: '#e06c75', - }, - { tag: [tags.function(tags.variableName), tags.labelName], color: '#61afef' }, - { tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: '#d19a66' }, - { tag: [tags.definition(tags.name), tags.separator], color: '#abb2bf' }, - { - tag: [ - tags.typeName, - tags.className, - tags.number, - tags.changed, - tags.annotation, - tags.modifier, - tags.self, - tags.namespace, - ], - color: '#e06c75', - }, - { - tag: [ - tags.operator, - tags.operatorKeyword, - tags.url, - tags.escape, - tags.regexp, - tags.link, - tags.special(tags.string), - ], - color: '#56b6c2', - }, - { tag: [tags.meta, tags.comment], color: '#7d8799' }, - { tag: tags.strong, fontWeight: 'bold' }, - { tag: tags.emphasis, fontStyle: 'italic' }, - { tag: tags.strikethrough, textDecoration: 'line-through' }, - { tag: tags.link, color: '#7d8799', textDecoration: 'underline' }, - { tag: tags.heading, fontWeight: 'bold', color: '#e06c75' }, - { tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: '#d19a66' }, - { tag: [tags.processingInstruction, tags.string, tags.inserted], color: '#98c379' }, - { tag: tags.invalid, color: 'red', 'font-weight': 'bold' }, - ]), - ), -]; diff --git a/packages/editor-ui/src/components/JsEditor/JsEditor.vue b/packages/editor-ui/src/components/JsEditor/JsEditor.vue index 805eb13893..cb9c60c85b 100644 --- a/packages/editor-ui/src/components/JsEditor/JsEditor.vue +++ b/packages/editor-ui/src/components/JsEditor/JsEditor.vue @@ -1,26 +1,30 @@ + + diff --git a/packages/editor-ui/src/components/JsonEditor/JsonEditor.vue b/packages/editor-ui/src/components/JsonEditor/JsonEditor.vue index be5762f5d8..82ab0bfe99 100644 --- a/packages/editor-ui/src/components/JsonEditor/JsonEditor.vue +++ b/packages/editor-ui/src/components/JsonEditor/JsonEditor.vue @@ -1,26 +1,30 @@ + + diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 2186e23717..79a0e6c8f3 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -1166,7 +1166,7 @@ export default defineComponent({ .node-parameters-wrapper { overflow-y: auto; - padding: 0 var(--spacing-m) 200px var(--spacing-m); + padding: 0 var(--spacing-m) var(--spacing-l) var(--spacing-m); flex-grow: 1; } diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 7860c2030d..e57702929f 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -15,7 +15,7 @@ :is-read-only="isReadOnly" :redact-values="shouldRedactValue" @closeDialog="closeExpressionEditDialog" - @update:modelValue="expressionUpdated" + @update:model-value="expressionUpdated" >
-
+
+ + + + +
@@ -90,11 +127,12 @@ :path="path" :is-read-only="isReadOnly" @closeDialog="closeTextEditDialog" - @update:modelValue="expressionUpdated" + @update:model-value="expressionUpdated" > + @update:model-value="valueChangedDebounced" + > + + + @update:model-value="valueChangedDebounced" + > + + + @update:model-value="valueChangedDebounced" + > + + + @update:model-value="valueChangedDebounced" + > + + + @update:model-value="valueChangedDebounced" + > + +
@@ -283,7 +380,7 @@ :loading="remoteParameterOptionsLoading" :disabled="isReadOnly || remoteParameterOptionsLoading" :title="displayTitle" - @update:modelValue="valueChanged" + @update:model-value="valueChanged" @keydown.stop @focus="setFocus" @blur="onBlur" @@ -321,7 +418,7 @@ :disabled="isReadOnly || remoteParameterOptionsLoading" :title="displayTitle" :placeholder="i18n.baseText('parameterInput.select')" - @update:modelValue="valueChanged" + @update:model-value="valueChanged" @keydown.stop @focus="setFocus" @blur="onBlur" @@ -358,7 +455,7 @@ active-color="#13ce66" :model-value="displayValue" :disabled="isReadOnly" - @update:modelValue="valueChanged" + @update:model-value="valueChanged" />
@@ -1056,7 +1153,7 @@ export default defineComponent({ return; } - if (this.editorType) { + if (this.editorType || this.parameter.type === 'json') { this.codeEditDialogVisible = true; } else { this.textEditDialogVisible = true; @@ -1418,4 +1515,12 @@ export default defineComponent({ .invalid { border-color: var(--color-danger); } + +.code-edit-dialog { + height: 70vh; + + .code-node-editor { + height: 100%; + } +} diff --git a/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue b/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue index 7847cc75f8..fd33c1ea02 100644 --- a/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue +++ b/packages/editor-ui/src/components/SqlEditor/SqlEditor.vue @@ -1,7 +1,9 @@