From 7150a59abc101bd66670dfea664ecadc351da1b3 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Fri, 9 Sep 2022 15:20:07 +0100 Subject: [PATCH] Switched offer 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/app/controllers/offer.js | 33 --------------- ghost/admin/app/routes/offer.js | 62 +++++++++++++++++----------- ghost/admin/app/templates/offer.hbs | 10 +---- 3 files changed, 40 insertions(+), 65 deletions(-) diff --git a/ghost/admin/app/controllers/offer.js b/ghost/admin/app/controllers/offer.js index 92107a9a9a..4cdc8c6489 100644 --- a/ghost/admin/app/controllers/offer.js +++ b/ghost/admin/app/controllers/offer.js @@ -24,7 +24,6 @@ export default class OffersController extends Controller { @tracked cadences = []; @tracked tiers = []; @tracked portalPreviewUrl = ''; - @tracked showUnsavedChangesModal = false; @tracked defaultSiteUrl = this.config.get('blogUrl'); @@ -58,7 +57,6 @@ export default class OffersController extends Controller { @tracked isDisplayTitleEdited = false; @tracked isOfferCodeEdited = false; - leaveScreenTransition = null; portalPreviewGuid = Date.now().valueOf(); constructor() { @@ -255,37 +253,6 @@ export default class OffersController extends Controller { return this.saveTask.perform(); } - @action - leaveScreen() { - this.offer.rollbackAttributes(); - return this.leaveScreenTransition.retry(); - } - - @action - toggleUnsavedChangesModal(transition) { - let leaveTransition = this.leaveScreenTransition; - - if (!transition && this.showUnsavedChangesModal) { - this.leaveScreenTransition = null; - this.showUnsavedChangesModal = false; - return; - } - - if (!leaveTransition || transition.targetName === leaveTransition.targetName) { - this.leaveScreenTransition = transition; - - // if a save is running, wait for it to finish then transition - if (this.save.isRunning) { - return this.save.last.then(() => { - transition.retry(); - }); - } - - // we genuinely have unsaved data, show the modal - this.showUnsavedChangesModal = true; - } - } - @action setup() { this.fetchTiers.perform(); diff --git a/ghost/admin/app/routes/offer.js b/ghost/admin/app/routes/offer.js index a0c14d69a8..1f2bf1643c 100644 --- a/ghost/admin/app/routes/offer.js +++ b/ghost/admin/app/routes/offer.js @@ -1,19 +1,14 @@ 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 class OffersRoute extends AdminRoute { + @service modals; @service router; _requiresBackgroundRefresh = true; - constructor() { - super(...arguments); - this.router.on('routeWillChange', (transition) => { - this.showUnsavedChangesModal(transition); - }); - } - model(params) { this._requiresBackgroundRefresh = false; @@ -26,6 +21,7 @@ export default class OffersRoute extends AdminRoute { setupController(controller, offer) { super.setupController(...arguments); + if (this._requiresBackgroundRefresh) { // `offer` is passed directly in `` so it can be a proxy // object used by the sparse list requiring the use of .get() @@ -34,12 +30,47 @@ export default class OffersRoute extends AdminRoute { } deactivate() { - super.deactivate(...arguments); // clean up newly created records and revert unsaved changes to existing this.controller.offer.rollbackAttributes(); this._requiresBackgroundRefresh = true; } + @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; + } + + const shouldLeave = await this.confirmUnsavedChanges(); + + if (shouldLeave) { + this.controller.model.rollbackAttributes(); + this.hasConfirmed = true; + return transition.retry(); + } + } + + async confirmUnsavedChanges() { + if (this.controller.model?.hasDirtyAttributes) { + this.confirmModal = this.modals + .open(ConfirmUnsavedChangesModal) + .finally(() => { + this.confirmModal = null; + }); + + return this.confirmModal; + } + + return true; + } + @action save() { this.controller.save(); @@ -48,19 +79,4 @@ export default class OffersRoute extends AdminRoute { titleToken() { return this.controller.offer.name; } - - showUnsavedChangesModal(transition) { - if (transition.from && transition.from.name === this.routeName && transition.targetName) { - let {controller} = this; - - // offer.changedAttributes is always true for new offers but number of changed attrs is reliable - let isChanged = Object.keys(controller.offer.changedAttributes()).length > 0; - - if (!controller.offer.isDeleted && isChanged) { - transition.abort(); - controller.toggleUnsavedChangesModal(transition); - return; - } - } - } } diff --git a/ghost/admin/app/templates/offer.hbs b/ghost/admin/app/templates/offer.hbs index 39052ac8b7..ff6338506d 100644 --- a/ghost/admin/app/templates/offer.hbs +++ b/ghost/admin/app/templates/offer.hbs @@ -341,12 +341,4 @@ - - -{{#if this.showUnsavedChangesModal}} - -{{/if}} + \ No newline at end of file