Skip to content

Commit

Permalink
feat: Add prompt to overwrite changes when concurrent editing occurs (#…
Browse files Browse the repository at this point in the history
…4817)

* feat: Add prompt to overwrite changes when concurrent editing occurs

* chore: undo config schema update
  • Loading branch information
alexgrozav authored Dec 5, 2022
1 parent 46c75b9 commit af6ac42
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 5 deletions.
2 changes: 1 addition & 1 deletion packages/editor-ui/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export interface IRestApi {
removeTestWebhook(workflowId: string): Promise<boolean>;
runWorkflow(runData: IStartRunData): Promise<IExecutionPushResponse>;
createNewWorkflow(sendData: IWorkflowDataUpdate): Promise<IWorkflowDb>;
updateWorkflow(id: string, data: IWorkflowDataUpdate): Promise<IWorkflowDb>;
updateWorkflow(id: string, data: IWorkflowDataUpdate, forceSave?: boolean): Promise<IWorkflowDb>;
deleteWorkflow(name: string): Promise<void>;
getWorkflow(id: string): Promise<IWorkflowDb>;
getWorkflows(filter?: object): Promise<IWorkflowShortResponse[]>;
Expand Down
4 changes: 2 additions & 2 deletions packages/editor-ui/src/mixins/restApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ export const restApi = Vue.extend({
},

// Updates an existing workflow
updateWorkflow: (id: string, data: IWorkflowDataUpdate): Promise<IWorkflowDb> => {
return self.restApi().makeRestApiRequest('PATCH', `/workflows/${id}`, data);
updateWorkflow: (id: string, data: IWorkflowDataUpdate, forceSave = false): Promise<IWorkflowDb> => {
return self.restApi().makeRestApiRequest('PATCH', `/workflows/${id}${forceSave ? '?forceSave=true' : ''}`, data);
},

// Deletes a workflow
Expand Down
20 changes: 18 additions & 2 deletions packages/editor-ui/src/mixins/workflowHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ export const workflowHelpers = mixins(
}
},

async saveCurrentWorkflow({id, name, tags}: {id?: string, name?: string, tags?: string[]} = {}, redirect = true): Promise<boolean> {
async saveCurrentWorkflow({id, name, tags}: {id?: string, name?: string, tags?: string[]} = {}, redirect = true, forceSave = false): Promise<boolean> {
const currentWorkflow = id || this.$route.params.name;

if (!currentWorkflow || ['new', PLACEHOLDER_EMPTY_WORKFLOW_ID].includes(currentWorkflow)) {
Expand All @@ -726,7 +726,7 @@ export const workflowHelpers = mixins(

workflowDataRequest.hash = this.workflowsStore.workflowHash;

const workflowData = await this.restApi().updateWorkflow(currentWorkflow, workflowDataRequest);
const workflowData = await this.restApi().updateWorkflow(currentWorkflow, workflowDataRequest, forceSave);
this.workflowsStore.setWorkflowHash(workflowData.hash);

if (name) {
Expand All @@ -747,6 +747,22 @@ export const workflowHelpers = mixins(
} catch (error) {
this.uiStore.removeActiveAction('workflowSaving');

if (error.errorCode === 400 && error.message.startsWith('Your most recent changes may be lost')) {
const overwrite = await this.confirmMessage(
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.message'),
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.title'),
null,
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.confirmButtonText'),
this.$locale.baseText('workflows.concurrentChanges.confirmMessage.cancelButtonText'),
);

if (overwrite) {
return this.saveCurrentWorkflow({id, name, tags}, redirect, true);
}

return false;
}

this.$showMessage({
title: this.$locale.baseText('workflowHelpers.showMessage.title'),
message: error.message,
Expand Down
4 changes: 4 additions & 0 deletions packages/editor-ui/src/plugins/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,10 @@
"workflows.shareModal.notAvailable": "Sharing workflows with others is currently available only on n8n cloud, our hosted offering.",
"workflows.shareModal.notAvailable.button": "Explore n8n cloud",
"workflows.roles.editor": "Editor",
"workflows.concurrentChanges.confirmMessage.title": "Workflow was edited by someone else",
"workflows.concurrentChanges.confirmMessage.message": "Another user made <strong>an edit</strong> to this workflow since you last saved it. Do you want to overwrite their changes?",
"workflows.concurrentChanges.confirmMessage.cancelButtonText": "Cancel",
"workflows.concurrentChanges.confirmMessage.confirmButtonText": "Overwrite then save",
"importCurlModal.title": "Import cURL command",
"importCurlModal.input.label": "cURL Command",
"importCurlModal.input.placeholder": "Paste the cURL command here",
Expand Down

0 comments on commit af6ac42

Please sign in to comment.