mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-29 13:52:10 +03:00
Fixed customize design route-based modal handling + added unsaved change confirmation
refs https://github.com/TryGhost/Team/issues/559 refs https://github.com/TryGhost/Team/issues/1045 - removed need for `{{will-destroy}}` in the modal template by using `willTransition()` in the route that opened the modal instead - used the property of new modals acting as promises to implement an unsaved changes confirmation modal - added `confirmUnsavedChanges()` method that opens a "are you sure you want to leave?" modal that is treated as a promise. If the modal is closed by the "Leave" button the promise returns true in which case we rollback the unsaved changes. The modal is returned so that other behaviour can use this method and wait for the confirmation result - added `willTransition()` route hook that calls `confirmUnsavedChanges()` when there are unsaved changes and will only continue to transition if the "Leave" button is pressed - added `beforeClose()` hook to the customize modal when opening so that we can prevent the customize modal from closing when "Stay" is clicked in the confirmation modal - updated `activate()` hook to store the modal instance so it can be closed later - updated `deactivate()` hook to call `.close()` on the modal instance rather than using private data/methods on the modals service
This commit is contained in:
parent
4f2af95afe
commit
2b0d1ee357
@ -0,0 +1,19 @@
|
||||
<div class="modal-content">
|
||||
<header class="modal-header" data-test-modal="unsaved-settings">
|
||||
<h1>Are you sure you want to leave this page?</h1>
|
||||
</header>
|
||||
<a class="close" href="" role="button" title="Close" {{on "click" @close}}>{{svg-jar "close"}}<span class="hidden">Close</span></a>
|
||||
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Hey there! It looks like you didn't save the changes you made.
|
||||
</p>
|
||||
|
||||
<p>Save before you go!</p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button {{on "click" (fn @close false)}} class="gh-btn" data-test-stay-button><span>Stay</span></button>
|
||||
<button {{on "click" (fn @close true)}} class="gh-btn gh-btn-red" data-test-leave-button><span>Leave</span></button>
|
||||
</div>
|
||||
</div>
|
@ -1,4 +1,4 @@
|
||||
<div class="modal-content" {{will-destroy this.willClose}}>
|
||||
<div class="modal-content">
|
||||
<div class="modal-body gh-ps-modal-body">
|
||||
<div class="gh-branding-settings-header">
|
||||
<h4>Customize</h4>
|
||||
|
@ -5,7 +5,6 @@ import {inject as service} from '@ember/service';
|
||||
export default class ModalsDesignAdvancedComponent extends Component {
|
||||
@service config;
|
||||
@service settings;
|
||||
@service router;
|
||||
|
||||
previewIframe = null;
|
||||
|
||||
@ -13,9 +12,4 @@ export default class ModalsDesignAdvancedComponent extends Component {
|
||||
registerPreviewIframe(iframe) {
|
||||
this.previewIframe = iframe;
|
||||
}
|
||||
|
||||
@action
|
||||
willClose() {
|
||||
this.router.transitionTo('settings.design');
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
|
||||
import {action} from '@ember/object';
|
||||
import {bind} from '@ember/runloop';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default class SettingsDesignCustomizeRoute extends AuthenticatedRoute {
|
||||
@service feature;
|
||||
@service modals;
|
||||
@service settings;
|
||||
|
||||
beforeModel() {
|
||||
super.beforeModel(...arguments);
|
||||
@ -18,14 +21,62 @@ export default class SettingsDesignCustomizeRoute extends AuthenticatedRoute {
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.modals.open('modals/design/customize', {}, {
|
||||
className: 'fullscreen-modal-full-overlay fullscreen-modal-branding-modal'
|
||||
this.customizeModal = this.modals.open('modals/design/customize', {}, {
|
||||
className: 'fullscreen-modal-full-overlay fullscreen-modal-branding-modal',
|
||||
beforeClose: bind(this, this.beforeModalClose)
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
async willTransition(transition) {
|
||||
if (this.settings.get('hasDirtyAttributes')) {
|
||||
transition.abort();
|
||||
|
||||
const shouldLeave = await this.confirmUnsavedChanges();
|
||||
|
||||
if (shouldLeave) {
|
||||
return transition.retry();
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.modals._stack.reverse().forEach((modal) => {
|
||||
modal._componentInstance.closeModal();
|
||||
});
|
||||
this.customizeModal?.close();
|
||||
this.customizeModal = null;
|
||||
this.confirmModal = null;
|
||||
}
|
||||
|
||||
async beforeModalClose() {
|
||||
const shouldLeave = await this.confirmUnsavedChanges();
|
||||
|
||||
if (shouldLeave === true) {
|
||||
this.transitionTo('settings.design');
|
||||
} else {
|
||||
// prevent modal from closing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
confirmUnsavedChanges() {
|
||||
if (!this.settings.get('hasDirtyAttributes')) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
if (!this.confirmModal) {
|
||||
this.confirmModal = this.modals.open('modals/confirm-unsaved-changes', {}, {
|
||||
className: 'fullscreen-modal-action fullscreen-modal-wide'
|
||||
}).then((discardChanges) => {
|
||||
if (discardChanges === true) {
|
||||
this.settings.rollbackAttributes();
|
||||
}
|
||||
return discardChanges;
|
||||
}).finally(() => {
|
||||
this.confirmModal = null;
|
||||
});
|
||||
}
|
||||
|
||||
return this.confirmModal;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user