Skip to content

Commit

Permalink
feat(editor): Enable saving workflow when node details view is open (#…
Browse files Browse the repository at this point in the history
…5856)

* feat(editor): Enable saving workflow when node details view is open
* ⚡ Preventing event propagation
* ⚡ Move save event handler to `NodeDetailsView`
* ✅ Added e2e tests
* 👕 Fixing linting and removing unnecessary event logic

---------

Co-authored-by: Oleg Ivaniv <oleg@n8n.io>
MiloradFilipovic and OlegIvaniv authored Mar 31, 2023

Partially verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
1 parent 83aef17 commit 0a59002
Showing 4 changed files with 63 additions and 13 deletions.
8 changes: 8 additions & 0 deletions cypress/e2e/5-ndv.cy.ts
Original file line number Diff line number Diff line change
@@ -90,6 +90,14 @@ describe('NDV', () => {
});
});

it('should save workflow using keyboard shortcut from NDV', () => {
workflowPage.actions.addNodeToCanvas('Manual');
workflowPage.actions.addNodeToCanvas('Set', true, true);
ndv.getters.container().should('be.visible');
workflowPage.actions.saveWorkflowUsingKeyboardShortcut();
workflowPage.getters.isWorkflowSaved();
})

describe('test output schema view', () => {
const schemaKeys = ['id', 'name', 'email', 'notes', 'country', 'created', 'objectValue', 'prop1', 'prop2'];
function setupSchemaWorkflow() {
24 changes: 23 additions & 1 deletion packages/editor-ui/src/components/NodeDetailsView.vue
Original file line number Diff line number Diff line change
@@ -28,7 +28,13 @@
</div>
</n8n-tooltip>

<div class="data-display" v-if="activeNode">
<div
v-if="activeNode"
class="data-display"
ref="container"
@keydown.capture="onKeyDown"
tabindex="0"
>
<div @click="close" :class="$style.modalBackground"></div>
<NDVDraggablePanels
:isTriggerNode="isTriggerNode"
@@ -156,6 +162,7 @@ import { useNDVStore } from '@/stores/ndv';
import { useNodeTypesStore } from '@/stores/nodeTypes';
import { useUIStore } from '@/stores/ui';
import { useSettingsStore } from '@/stores/settings';
import useDeviceSupport from '@/composables/useDeviceSupport';
export default mixins(
externalHooks,
@@ -184,6 +191,11 @@ export default mixins(
default: false,
},
},
setup() {
return {
...useDeviceSupport(),
};
},
data() {
return {
settingsEventBus: new Vue(),
@@ -469,6 +481,16 @@ export default mixins(
},
},
methods: {
onKeyDown(e: KeyboardEvent) {
if (e.key === 's' && this.isCtrlKeyPressed(e)) {
e.stopPropagation();
e.preventDefault();
if (this.readOnly) return;
this.$emit('saveKeyboardShortcut', e);
}
},
onInputItemHover(e: { itemIndex: number; outputIndex: number } | null) {
if (!this.inputNodeName) {
return;
1 change: 1 addition & 0 deletions packages/editor-ui/src/plugins/i18n/locales/en.json
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@
"generic.unsavedWork.confirmMessage.confirmButtonText": "Save",
"generic.unsavedWork.confirmMessage.cancelButtonText": "Leave without saving",
"generic.workflow": "Workflow",
"generic.workflowSaved": "Workflow changes saved",
"generic.editor": "Editor",
"about.aboutN8n": "About n8n",
"about.close": "Close",
43 changes: 31 additions & 12 deletions packages/editor-ui/src/views/NodeView.vue
Original file line number Diff line number Diff line change
@@ -92,6 +92,7 @@
:isProductionExecutionPreview="isProductionExecutionPreview"
@valueChanged="valueChanged"
@stopExecution="stopExecution"
@saveKeyboardShortcut="onSaveKeyboardShortcut"
/>
<node-creation
v-if="!isReadOnly"
@@ -752,9 +753,24 @@ export default mixins(
return uniqueName;
},
async onSaveKeyboardShortcut() {
const saved = await this.saveCurrentWorkflow();
async onSaveKeyboardShortcut(e: KeyboardEvent) {
let saved = await this.saveCurrentWorkflow();
if (saved) await this.settingsStore.fetchPromptsData();
if (this.activeNode) {
// If NDV is open, save will not work from editable input fields
// so don't show success message if this is true
if (e.target instanceof HTMLInputElement) {
saved = e.target.readOnly;
} else {
saved = true;
}
if (saved) {
this.$showMessage({
title: this.$locale.baseText('generic.workflowSaved'),
type: 'success',
});
}
}
},
showTriggerCreator(source: NodeCreatorOpenSource) {
if (this.createNodeActive) return;
@@ -994,6 +1010,19 @@ export default mixins(
}
},
async keyDown(e: KeyboardEvent) {
if (e.key === 's' && this.isCtrlKeyPressed(e)) {
e.stopPropagation();
e.preventDefault();
if (this.isReadOnly) {
return;
}
this.callDebounced('onSaveKeyboardShortcut', { debounceTime: 1000 }, e);
return;
}
// @ts-ignore
const path = e.path || (e.composedPath && e.composedPath());
@@ -1082,16 +1111,6 @@ export default mixins(
title: this.$locale.baseText('nodeView.showMessage.keyDown.title'),
type: 'success',
});
} else if (e.key === 's' && this.isCtrlKeyPressed(e)) {
// Save workflow
e.stopPropagation();
e.preventDefault();
if (this.isReadOnly) {
return;
}
this.callDebounced('onSaveKeyboardShortcut', { debounceTime: 1000 });
} else if (e.key === 'Enter') {
// Activate the last selected node
const lastSelectedNode = this.lastSelectedNode;

0 comments on commit 0a59002

Please sign in to comment.