From f1c4f880a627ab99d47108c12a2b047b97527aba Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Fri, 9 Sep 2022 17:05:57 +0100 Subject: [PATCH] Switched FirstPromoter unsaved changes modal to new modal pattern refs https://github.com/TryGhost/Team/issues/1734 refs https://github.com/TryGhost/Team/issues/559 refs https://github.com/TryGhost/Ghost/issues/14101 - switches to newer modal patterns ready for later Ember upgrades --- ghost/admin/.lint-todo | 2 + .../settings/integrations/firstpromoter.js | 54 +------------ .../settings/integrations/firstpromoter.js | 77 +++++++++++++------ .../settings/integrations/firstpromoter.hbs | 7 -- 4 files changed, 61 insertions(+), 79 deletions(-) diff --git a/ghost/admin/.lint-todo b/ghost/admin/.lint-todo index 59e0e14ba0..90e7aa333e 100644 --- a/ghost/admin/.lint-todo +++ b/ghost/admin/.lint-todo @@ -1048,3 +1048,5 @@ remove|ember-template-lint|no-action|15|21|15|21|df631bb317cb737790ce8fd9a9b107f remove|ember-template-lint|no-action|16|19|16|19|35178fb4b4e564116d2012fda7d3977a471fc8e7|1658102400000|1668474000000|1673658000000|app/templates/settings/navigation.hbs remove|ember-template-lint|no-action|17|21|17|21|df631bb317cb737790ce8fd9a9b107f5a196a10d|1658102400000|1668474000000|1673658000000|app/templates/settings/integrations/amp.hbs remove|ember-template-lint|no-action|18|19|18|19|35178fb4b4e564116d2012fda7d3977a471fc8e7|1658102400000|1668474000000|1673658000000|app/templates/settings/integrations/amp.hbs +remove|ember-template-lint|no-action|17|21|17|21|df631bb317cb737790ce8fd9a9b107f5a196a10d|1658102400000|1668474000000|1673658000000|app/templates/settings/integrations/firstpromoter.hbs +remove|ember-template-lint|no-action|18|19|18|19|35178fb4b4e564116d2012fda7d3977a471fc8e7|1658102400000|1668474000000|1673658000000|app/templates/settings/integrations/firstpromoter.hbs diff --git a/ghost/admin/app/controllers/settings/integrations/firstpromoter.js b/ghost/admin/app/controllers/settings/integrations/firstpromoter.js index a8b99179dd..d6a64b30f5 100644 --- a/ghost/admin/app/controllers/settings/integrations/firstpromoter.js +++ b/ghost/admin/app/controllers/settings/integrations/firstpromoter.js @@ -1,17 +1,12 @@ -import classic from 'ember-classic-decorator'; +import Controller from '@ember/controller'; import {action} from '@ember/object'; import {inject as service} from '@ember/service'; -/* eslint-disable ghost/ember/alias-model-in-controller */ -import Controller from '@ember/controller'; import {task} from 'ember-concurrency'; -@classic export default class FirstpromoterController extends Controller { @service notifications; @service settings; - leaveSettingsTransition = null; - @action update(value) { this.settings.set('firstpromoter', value); @@ -22,48 +17,8 @@ export default class FirstpromoterController extends Controller { this.saveTask.perform(); } - @action - toggleLeaveSettingsModal(transition) { - let leaveTransition = this.leaveSettingsTransition; - - if (!transition && this.showLeaveSettingsModal) { - this.set('leaveSettingsTransition', null); - this.set('showLeaveSettingsModal', false); - return; - } - - if (!leaveTransition || transition.targetName === leaveTransition.targetName) { - this.set('leaveSettingsTransition', transition); - - // if a save is running, wait for it to finish then transition - if (this.saveTask.isRunning) { - return this.saveTask.last.then(() => { - transition.retry(); - }); - } - - // we genuinely have unsaved data, show the modal - this.set('showLeaveSettingsModal', true); - } - } - - @action - leaveSettings() { - let transition = this.leaveSettingsTransition; - let settings = this.settings; - - if (!transition) { - this.notifications.showAlert('Sorry, there was an error in the application. Please let the Ghost team know what happened.', {type: 'error'}); - return; - } - - // roll back changes on settings model - settings.rollbackAttributes(); - - return transition.retry(); - } - - @(task(function* () { + @task({drop: true}) + *saveTask() { try { yield this.settings.validate(); return yield this.settings.save(); @@ -71,6 +26,5 @@ export default class FirstpromoterController extends Controller { this.notifications.showAPIError(error); throw error; } - }).drop()) - saveTask; + } } diff --git a/ghost/admin/app/routes/settings/integrations/firstpromoter.js b/ghost/admin/app/routes/settings/integrations/firstpromoter.js index 4c868eb09a..5772d0d138 100644 --- a/ghost/admin/app/routes/settings/integrations/firstpromoter.js +++ b/ghost/admin/app/routes/settings/integrations/firstpromoter.js @@ -1,36 +1,69 @@ import AdminRoute from 'ghost-admin/routes/admin'; +import ConfirmUnsavedChangesModal from '../../../components/modals/confirm-unsaved-changes'; +import {action} from '@ember/object'; import {inject as service} from '@ember/service'; -export default AdminRoute.extend({ - settings: service(), - - beforeModel() { - this._super(...arguments); +export default class FirstPromotionIntegrationRoute extends AdminRoute { + @service modals; + @service settings; + model() { return this.settings.reload(); - }, + } - actions: { - save() { - this.controller.send('save'); - }, + deactivate() { + this.confirmModal = null; + this.hasConfirmed = false; + } - willTransition(transition) { - let controller = this.controller; - let modelIsDirty = this.settings.get('hasDirtyAttributes'); - - if (modelIsDirty) { - transition.abort(); - controller.send('toggleLeaveSettingsModal', transition); - return; - } + @action + async willTransition(transition) { + if (this.hasConfirmed) { + return true; } - }, + + transition.abort(); + + // wait for any existing confirm modal to be closed before allowing transition + if (this.confirmModal) { + return; + } + + if (this.controller.saveTask?.isRunning) { + await this.controller.saveTask.last; + } + + const shouldLeave = await this.confirmUnsavedChanges(); + + if (shouldLeave) { + this.settings.rollbackAttributes(); + this.hasConfirmed = true; + return transition.retry(); + } + } + + async confirmUnsavedChanges() { + if (this.settings.get('hasDirtyAttributes')) { + this.confirmModal = this.modals + .open(ConfirmUnsavedChangesModal) + .finally(() => { + this.confirmModal = null; + }); + + return this.confirmModal; + } + + return true; + } + + @action + save() { + this.controller.send('save'); + } buildRouteInfoMetadata() { return { titleToken: 'FirstPromoter' }; } - -}); +} diff --git a/ghost/admin/app/templates/settings/integrations/firstpromoter.hbs b/ghost/admin/app/templates/settings/integrations/firstpromoter.hbs index 959de71b47..8ca9eb508f 100644 --- a/ghost/admin/app/templates/settings/integrations/firstpromoter.hbs +++ b/ghost/admin/app/templates/settings/integrations/firstpromoter.hbs @@ -12,13 +12,6 @@ - {{#if this.showLeaveSettingsModal}} - - {{/if}} -