From f4022c6cd543886ba150ae3da554d973cb6aaa70 Mon Sep 17 00:00:00 2001 From: Erin Date: Tue, 7 Jul 2020 10:35:20 -0400 Subject: [PATCH 1/4] :wrench: Prompt User to Save Before Page Unload --- packages/editor-ui/src/views/NodeView.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index de89534e09..573849eb39 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -1328,6 +1328,10 @@ export default mixins( document.addEventListener('keydown', this.keyDown); document.addEventListener('keyup', this.keyUp); + window.onbeforeunload = this.confirmSave; + }, + async confirmSave(e: Event) { + window.confirm(); }, __addConnection (connection: [IConnection, IConnection], addVisualConnection = false) { if (addVisualConnection === true) { From ad1228e0ea310b10c81c9bbea3562396f2ece8e9 Mon Sep 17 00:00:00 2001 From: Erin Date: Thu, 9 Jul 2020 16:54:50 -0400 Subject: [PATCH 2/4] :sparkles: Everything works except refresh --- .../editor-ui/src/components/MainSidebar.vue | 27 +++++++++++++---- .../editor-ui/src/components/WorkflowOpen.vue | 17 +++++++++-- .../src/components/mixins/workflowHelpers.ts | 29 ++++++++++++++++++ packages/editor-ui/src/views/NodeView.vue | 30 ++++++++++++++----- 4 files changed, 87 insertions(+), 16 deletions(-) diff --git a/packages/editor-ui/src/components/MainSidebar.vue b/packages/editor-ui/src/components/MainSidebar.vue index 71388c2cd3..57096c0f29 100644 --- a/packages/editor-ui/src/components/MainSidebar.vue +++ b/packages/editor-ui/src/components/MainSidebar.vue @@ -443,13 +443,28 @@ export default mixins( } else if (key === 'workflow-settings') { this.workflowSettingsDialogVisible = true; } else if (key === 'workflow-new') { - this.$router.push({ name: 'NodeViewNew' }); + const workflowId = this.$store.getters.workflowId; + const result = await this.dataHasChanged(workflowId); + if(result) { + const importConfirm = await this.confirmMessage(`When you switch workflows your current workflow changes will be lost.`, 'Save your Changes?', 'warning', 'Yes, switch workflows and forget changes'); + if (importConfirm === true) { + this.$router.push({ name: 'NodeViewNew' }); - this.$showMessage({ - title: 'Workflow created', - message: 'A new workflow got created!', - type: 'success', - }); + this.$showMessage({ + title: 'Workflow created', + message: 'A new workflow got created!', + type: 'success', + }); + } + } else { + this.$router.push({ name: 'NodeViewNew' }); + + this.$showMessage({ + title: 'Workflow created', + message: 'A new workflow got created!', + type: 'success', + }); + } } else if (key === 'credentials-open') { this.credentialOpenDialogVisible = true; } else if (key === 'credentials-new') { diff --git a/packages/editor-ui/src/components/WorkflowOpen.vue b/packages/editor-ui/src/components/WorkflowOpen.vue index 9592ecb4d5..9ef5e94eb0 100644 --- a/packages/editor-ui/src/components/WorkflowOpen.vue +++ b/packages/editor-ui/src/components/WorkflowOpen.vue @@ -33,6 +33,7 @@ import WorkflowActivator from '@/components/WorkflowActivator.vue'; import { restApi } from '@/components/mixins/restApi'; import { genericHelpers } from '@/components/mixins/genericHelpers'; +import { workflowHelpers } from '@/components/mixins/workflowHelpers'; import { showMessage } from '@/components/mixins/showMessage'; import { IWorkflowShortResponse } from '@/Interface'; @@ -42,6 +43,7 @@ export default mixins( genericHelpers, restApi, showMessage, + workflowHelpers, ).extend({ name: 'WorkflowOpen', props: [ @@ -87,9 +89,20 @@ export default mixins( this.$emit('closeDialog'); return false; }, - openWorkflow (data: IWorkflowShortResponse, column: any) { // tslint:disable-line:no-any + async openWorkflow (data: IWorkflowShortResponse, column: any) { // tslint:disable-line:no-any if (column.label !== 'Active') { - this.$emit('openWorkflow', data.id); + const workflowId = this.$store.getters.workflowId; + const result = await this.dataHasChanged(workflowId); + if(result) { + const importConfirm = await this.confirmMessage(`When you switch workflows your current workflow changes will be lost.`, 'Save your Changes?', 'warning', 'Yes, switch workflows and forget changes'); + if (importConfirm === false) { + return; + } else { + this.$emit('openWorkflow', data.id); + } + } else { + this.$emit('openWorkflow', data.id); + } } }, openDialog () { diff --git a/packages/editor-ui/src/components/mixins/workflowHelpers.ts b/packages/editor-ui/src/components/mixins/workflowHelpers.ts index 507d6d31e4..76ad77cdb9 100644 --- a/packages/editor-ui/src/components/mixins/workflowHelpers.ts +++ b/packages/editor-ui/src/components/mixins/workflowHelpers.ts @@ -22,6 +22,7 @@ import { INodeTypesMaxCount, INodeUi, IWorkflowData, + IWorkflowDb, IWorkflowDataUpdate, XYPositon, } from '../../Interface'; @@ -30,6 +31,8 @@ import { restApi } from '@/components/mixins/restApi'; import { nodeHelpers } from '@/components/mixins/nodeHelpers'; import { showMessage } from '@/components/mixins/showMessage'; +import { isEqual } from 'lodash'; + import mixins from 'vue-typed-mixins'; export const workflowHelpers = mixins( @@ -478,5 +481,31 @@ export const workflowHelpers = mixins( node.position[1] += offsetPosition[1]; } }, + async dataHasChanged(id: string) { + const currentData = await this.getWorkflowDataToSave(); + + let data: IWorkflowDb; + data = await this.restApi().getWorkflow(id); + + if(data !== undefined) { + console.log(currentData); + console.log(data); + const x = { + nodes: data.nodes, + connections: data.connections, + settings: data.settings, + name: data.name + }; + const y = { + nodes: currentData.nodes, + connections: currentData.connections, + settings: currentData.settings, + name: currentData.name + }; + return !isEqual(x, y); + } + + return true; + }, }, }); diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index 573849eb39..8ce1378d52 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -126,7 +126,7 @@ import RunData from '@/components/RunData.vue'; import mixins from 'vue-typed-mixins'; -import { debounce } from 'lodash'; +import { debounce, isEqual } from 'lodash'; import axios from 'axios'; import { IConnection, @@ -330,6 +330,8 @@ export default mixins( this.$store.commit('setWorkflowSettings', data.settings || {}); await this.addNodes(data.nodes, data.connections); + + return data; }, mouseDown (e: MouseEvent) { // Save the location of the mouse click @@ -1309,6 +1311,7 @@ export default mixins( if (this.$route.name === 'ExecutionById') { // Load an execution const executionId = this.$route.params.id; + await this.openExecution(executionId); } else { // Load a workflow @@ -1316,7 +1319,6 @@ export default mixins( if (this.$route.params.name) { workflowId = this.$route.params.name; } - if (workflowId !== null) { // Open existing workflow await this.openWorkflow(workflowId); @@ -1328,10 +1330,22 @@ export default mixins( document.addEventListener('keydown', this.keyDown); document.addEventListener('keyup', this.keyUp); - window.onbeforeunload = this.confirmSave; - }, - async confirmSave(e: Event) { - window.confirm(); + + window.addEventListener("beforeunload", (e) => { + let workflowId = null as string | null; + if (this.$route.params.name) { + workflowId = this.$route.params.name; + } + if(workflowId !== null) { + //const dataHasChanged = await this.dataHasChanged(workflowId); + } + + const confirmationMessage = 'It looks like you have been editing something. ' + + 'If you leave before saving, your changes will be lost.'; + + (e || window.event).returnValue = confirmationMessage; //Gecko + IE + return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc. + }); }, __addConnection (connection: [IConnection, IConnection], addVisualConnection = false) { if (addVisualConnection === true) { @@ -1876,13 +1890,13 @@ export default mixins( async mounted () { this.$root.$on('importWorkflowData', async (data: IDataObject) => { - await this.importWorkflowData(data.data as IWorkflowDataUpdate); + const resData = await this.importWorkflowData(data.data as IWorkflowDataUpdate); }); this.$root.$on('importWorkflowUrl', async (data: IDataObject) => { const workflowData = await this.getWorkflowDataFromUrl(data.url as string); if (workflowData !== undefined) { - await this.importWorkflowData(workflowData); + const resData = await this.importWorkflowData(workflowData); } }); From 70a584a46d419f83b05034a7cd3eacfd8bea248c Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 20 Jul 2020 10:57:58 -0400 Subject: [PATCH 3/4] :tada: Works with ctrl s, now working on a user saving from the side bar --- packages/editor-ui/src/views/NodeView.vue | 55 +++++++++++++++++------ 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index 8ce1378d52..5f2a08e3fc 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -186,6 +186,38 @@ export default mixins( // When a node gets set as active deactivate the create-menu this.createNodeActive = false; }, + nodes: { + handler: async function (val, oldVal) { + // Load a workflow + let workflowId = null as string | null; + if (this.$route && this.$route.params.name) { + workflowId = this.$route.params.name; + } + if(workflowId !== null) { + this.isDirty = await this.dataHasChanged(workflowId); + } else { + this.isDirty = true; + } + console.log(this.isDirty); + }, + deep: true + }, + connections: { + handler: async function (val, oldVal) { + // Load a workflow + let workflowId = null as string | null; + if (this.$route && this.$route.params.name) { + workflowId = this.$route.params.name; + } + if(workflowId !== null) { + this.isDirty = await this.dataHasChanged(workflowId); + } else { + this.isDirty = true; + } + console.log(this.isDirty); + }, + deep: true + }, }, computed: { activeNode (): INodeUi | null { @@ -259,6 +291,7 @@ export default mixins( ctrlKeyPressed: false, debouncedFunctions: [] as any[], // tslint:disable-line:no-any stopExecutionInProgress: false, + isDirty: false, }; }, beforeDestroy () { @@ -433,6 +466,8 @@ export default mixins( e.stopPropagation(); e.preventDefault(); + this.isDirty = false; + this.callDebounced('saveCurrentWorkflow', 1000); } else if (e.key === 'Enter') { // Activate the last selected node @@ -1305,6 +1340,7 @@ export default mixins( if (this.$route.params.action === 'workflowSave') { // In case the workflow got saved we do not have to run init // as only the route changed but all the needed data is already loaded + this.isDirty = false; return Promise.resolve(); } @@ -1331,20 +1367,13 @@ export default mixins( document.addEventListener('keydown', this.keyDown); document.addEventListener('keyup', this.keyUp); - window.addEventListener("beforeunload", (e) => { - let workflowId = null as string | null; - if (this.$route.params.name) { - workflowId = this.$route.params.name; + window.addEventListener("beforeunload", (e) => { + if(this.isDirty === true) { + const confirmationMessage = 'It looks like you have been editing something. ' + + 'If you leave before saving, your changes will be lost.'; + (e || window.event).returnValue = confirmationMessage; //Gecko + IE + return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc. } - if(workflowId !== null) { - //const dataHasChanged = await this.dataHasChanged(workflowId); - } - - const confirmationMessage = 'It looks like you have been editing something. ' - + 'If you leave before saving, your changes will be lost.'; - - (e || window.event).returnValue = confirmationMessage; //Gecko + IE - return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc. }); }, __addConnection (connection: [IConnection, IConnection], addVisualConnection = false) { From 5f32341a9ea14a50b405ed0606949ae660706bd1 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 20 Jul 2020 11:52:24 -0400 Subject: [PATCH 4/4] Remove logs --- packages/editor-ui/src/components/MainSidebar.vue | 2 ++ .../editor-ui/src/components/mixins/workflowHelpers.ts | 2 -- packages/editor-ui/src/views/NodeView.vue | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/editor-ui/src/components/MainSidebar.vue b/packages/editor-ui/src/components/MainSidebar.vue index 57096c0f29..5cb68b4ee3 100644 --- a/packages/editor-ui/src/components/MainSidebar.vue +++ b/packages/editor-ui/src/components/MainSidebar.vue @@ -435,8 +435,10 @@ export default mixins( saveAs(blob, workflowName + '.json'); } else if (key === 'workflow-save') { + console.log("saving......"); this.saveCurrentWorkflow(); } else if (key === 'workflow-save-as') { + console.log("saving......"); this.saveCurrentWorkflow(true); } else if (key === 'help-about') { this.aboutDialogVisible = true; diff --git a/packages/editor-ui/src/components/mixins/workflowHelpers.ts b/packages/editor-ui/src/components/mixins/workflowHelpers.ts index 76ad77cdb9..b3c2416b28 100644 --- a/packages/editor-ui/src/components/mixins/workflowHelpers.ts +++ b/packages/editor-ui/src/components/mixins/workflowHelpers.ts @@ -488,8 +488,6 @@ export const workflowHelpers = mixins( data = await this.restApi().getWorkflow(id); if(data !== undefined) { - console.log(currentData); - console.log(data); const x = { nodes: data.nodes, connections: data.connections, diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index 5f2a08e3fc..c75899424d 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -187,7 +187,7 @@ export default mixins( this.createNodeActive = false; }, nodes: { - handler: async function (val, oldVal) { + async handler (val, oldVal) { // Load a workflow let workflowId = null as string | null; if (this.$route && this.$route.params.name) { @@ -198,12 +198,11 @@ export default mixins( } else { this.isDirty = true; } - console.log(this.isDirty); }, deep: true }, connections: { - handler: async function (val, oldVal) { + async handler (val, oldVal) { // Load a workflow let workflowId = null as string | null; if (this.$route && this.$route.params.name) { @@ -214,7 +213,6 @@ export default mixins( } else { this.isDirty = true; } - console.log(this.isDirty); }, deep: true }, @@ -1373,6 +1371,8 @@ export default mixins( + 'If you leave before saving, your changes will be lost.'; (e || window.event).returnValue = confirmationMessage; //Gecko + IE return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc. + } else { + return; } }); },