Switched design screen from modals to standard routes

refs https://github.com/TryGhost/Team/issues/1130

- added `ui.contextualNavMenu` property that when set will switch the main nav menu between components, if it's not set then it will show the default "main" menu component
- added `design` menu sub-component of `gh-nav-menu` ready for use via `contextualNavMenu`
  - moved sidebar contents from the design modal into this component
- updated design route to set/reset `ui.contextualNavMenu` to `design` on entering/leaving the route
  - all other design routes are sub-routes so this works across all other design screens
- moved base design modal preview into the `settings/design/index` controller/template
  - using index means that it's the default screen for `/settings/design` but will be automatically replaced by any other `design.x` routes
- moved `design/advanced` modal content into the `settings.design.advanced` controller/template and removed the modal handling from the route
This commit is contained in:
Kevin Ansfield 2021-10-11 15:24:46 +01:00
parent 7eda410dc3
commit 595018098d
13 changed files with 147 additions and 186 deletions

View File

@ -1,3 +1,7 @@
<nav class="gh-nav" ...attributes>
<GhNavMenu::Main @icon={{this.settings.settledIcon}} />
{{#if this.ui.contextualNavMenu}}
{{component (concat "gh-nav-menu/" ui.contextualNavMenu)}}
{{else}}
<GhNavMenu::Main @icon={{this.settings.settledIcon}} />
{{/if}}
</nav>

View File

@ -3,4 +3,5 @@ import {inject as service} from '@ember/service';
export default class GhNavMenuComponent extends Component {
@service settings;
@service ui;
}

View File

@ -0,0 +1,81 @@
<header class="gh-nav-menu">
<LinkTo @route="settings" class="gh-nav-menu-title">{{svg-jar "arrow-left-tail"}} Site design</LinkTo>
</header>
<section class="gh-nav-body">
<div class="gh-nav-top">
<div class="pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "brand")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Brand</span>
<span class="db">{{svg-jar (if (set-has this.openSections "brand") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "brand")}}
<div class="pt4">
<Settings::Design::GeneralSettingsForm
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{#if this.themeSettings}}
{{#if this.siteWideSettings}}
<div class="mt4 pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "site-wide")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Site-wide</span>
<span class="db">{{svg-jar (if (set-has this.openSections "site-wide") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "site-wide")}}
<div class="pt4">
<Settings::Design::ThemeSettingsForm
@themeSettings={{this.siteWideSettings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{/if}}
{{#if this.homepageSettings}}
<div class="mt4 pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "homepage")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Homepage</span>
<span class="db">{{svg-jar (if (set-has this.openSections "homepage") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "homepage")}}
<div class="pt4">
<Settings::Design::ThemeSettingsForm
@themeSettings={{this.homepageSettings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{/if}}
{{#if this.postPageSettings}}
<div class="mt4 pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "post")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Post</span>
<span class="db">{{svg-jar (if (set-has this.openSections "post") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "post")}}
<div class="pt4">
<Settings::Design::ThemeSettingsForm
@themeSettings={{this.postPageSettings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{/if}}
{{/if}}
</div>
<div class="gh-nav-bottom">
<LinkTo @route="settings.design.advanced" class="gh-btn gh-btn-icon gh-btn-text"><span>{{svg-jar "settings"}} Advanced theme settings</span></LinkTo>
</div>
</section>

View File

@ -5,7 +5,7 @@ import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {tracked} from '@glimmer/tracking';
export default class ModalsDesignCustomizeComponent extends Component {
export default class DesignMenuComponent extends Component {
@service customThemeSettings;
@service settings;
@service themeManagement;

View File

@ -1,114 +0,0 @@
<div class="gh-viewport h-100">
<nav class="gh-nav">
<header class="gh-nav-menu">
<LinkTo @route="settings" class="gh-nav-menu-title">{{svg-jar "arrow-left-tail"}} Site design</LinkTo>
</header>
<section class="gh-nav-body">
<div class="gh-nav-top">
<div class="pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "brand")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Brand</span>
<span class="db">{{svg-jar (if (set-has this.openSections "brand") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "brand")}}
<div class="pt4">
<Settings::Design::GeneralSettingsForm
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{#if this.themeSettings}}
{{#if this.siteWideSettings}}
<div class="mt4 pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "site-wide")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Site-wide</span>
<span class="db">{{svg-jar (if (set-has this.openSections "site-wide") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "site-wide")}}
<div class="pt4">
<Settings::Design::ThemeSettingsForm
@themeSettings={{this.siteWideSettings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{/if}}
{{#if this.homepageSettings}}
<div class="mt4 pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "homepage")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Homepage</span>
<span class="db">{{svg-jar (if (set-has this.openSections "homepage") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "homepage")}}
<div class="pt4">
<Settings::Design::ThemeSettingsForm
@themeSettings={{this.homepageSettings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{/if}}
{{#if this.postPageSettings}}
<div class="mt4 pl6 pt4 pr6">
<button type="button" {{on "click" (fn this.toggleSection "post")}} class="flex flex-row w-100">
<span class="db tl flex-grow-1">{{svg-jar "house" class="w4"}} Post</span>
<span class="db">{{svg-jar (if (set-has this.openSections "post") "arrow-up-small" "arrow-down-small") class="w4"}}</span>
</button>
{{#if (set-has this.openSections "post")}}
<div class="pt4">
<Settings::Design::ThemeSettingsForm
@themeSettings={{this.postPageSettings}}
@updatePreview={{perform this.themeManagement.updatePreviewHtmlTask}}
/>
</div>
{{/if}}
</div>
{{/if}}
{{/if}}
</div>
<div class="gh-nav-bottom">
<LinkTo @route="settings.design.advanced" class="gh-btn gh-btn-icon gh-btn-text"><span>{{svg-jar "settings"}} Advanced theme settings</span></LinkTo>
</div>
</section>
</nav>
<main class="relative flex flex-column flex-grow-1" role="main">
<section class="gh-canvas relative w-100">
<GhCanvasHeader class="gh-canvas-header">
<h2 class="gh-canvas-title">{{this.config.blogTitle}}</h2>
<section class="view-actions">
<div class="gh-contentfilter gh-btn-group">
<button type="button" class="gh-btn gh-design-preview-mode gh-btn-group-selected"><span>{{svg-jar "desktop"}}</span></button>
<button type="button" class="gh-btn gh-design-preview-mode"><span>{{svg-jar "mobile-phone"}}</span></button>
</div>
<GhTaskButton
@buttonText="Save changes"
@task={{@data.saveTask}}
@successText="Saved"
@runningText="Saving"
@class="gh-btn gh-btn-primary gh-btn-icon"
data-test-button="save-settings"
/>
</section>
</GhCanvasHeader>
<div style="height: calc(100% - 96px)">
<GhBrowserPreview @icon={{this.settings.icon}} @title={{this.config.blogTitle}}>
<GhHtmlIframe id="site-frame" class="site-frame gh-branding-settings-preview" @html={{this.themeManagement.previewHtml}} />
</GhBrowserPreview>
</div>
</section>
</main>
</div>

View File

@ -1,21 +0,0 @@
import Component from '@glimmer/component';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
export default class ModalsDesignAdvancedComponent extends Component {
@service store;
get themes() {
return this.store.peekAll('theme');
}
constructor() {
super(...arguments);
this.loadThemesTask.perform();
}
@task
*loadThemesTask() {
yield this.store.findAll('theme');
}
}

View File

@ -0,0 +1,10 @@
import Controller from '@ember/controller';
import {inject as service} from '@ember/service';
export default class AdvancedThemeSettingsController extends Controller {
@service store;
get themes() {
return this.store.peekAll('theme');
}
}

View File

@ -0,0 +1,8 @@
import Controller from '@ember/controller';
import {inject as service} from '@ember/service';
export default class DesignIndexController extends Controller {
@service config;
@service settings;
@service themeManagement
}

View File

@ -1,6 +1,5 @@
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 SettingsDesignRoute extends AuthenticatedRoute {
@ -8,8 +7,8 @@ export default class SettingsDesignRoute extends AuthenticatedRoute {
@service feature;
@service modals;
@service settings;
@service ui;
designModal = null;
confirmModal = null;
hasConfirmed = false;
@ -30,13 +29,7 @@ export default class SettingsDesignRoute extends AuthenticatedRoute {
}
activate() {
this.designModal = this.modals.open('modals/design', {
saveTask: this.controllerFor('settings.design').saveTask
}, {
className: 'fullscreen-modal-total-overlay',
omitBackdrop: true,
beforeClose: bind(this, this.beforeModalClose)
});
this.ui.contextualNavMenu = 'design';
}
@action
@ -57,8 +50,7 @@ export default class SettingsDesignRoute extends AuthenticatedRoute {
}
deactivate() {
this.designModal?.close();
this.designModal = null;
this.ui.contextualNavMenu = null;
this.confirmModal = null;
this.hasConfirmed = false;
}

View File

@ -1,35 +1,10 @@
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 SettingsDesignAdvancedRoute extends AuthenticatedRoute {
@service modals;
@service store;
activate() {
this.advancedModal = this.modals.open('modals/design/advanced', {}, {
className: 'fullscreen-modal-action fullscreen-modal-wide',
beforeClose: bind(this, this.beforeModalClose)
});
}
@action
willTransition() {
this.isTransitioning = true;
return true;
}
deactivate() {
this.advancedModal?.close();
this.advancedModal = null;
this.isTransitioning = false;
}
beforeModalClose() {
if (this.isTransitioning) {
return;
}
this.transitionTo('settings.design');
model() {
this.store.findAll('theme');
}
}

View File

@ -48,6 +48,7 @@ export default class UiService extends Service {
@service router;
@service settings;
@tracked contextualNavMenu = null;
@tracked isFullScreen = false;
@tracked mainClass = '';
@tracked showMobileMenu = false;

View File

@ -1,10 +1,9 @@
<div class="modal-content">
<header class="modal-header">
<h1>Advanced theme options</h1>
</header>
<button type="button" class="close" title="Close" {{on "click" @close}}>{{svg-jar "close"}}<span class="hidden">Close</span></button>
<section class="gh-canvas">
<GhCanvasHeader class="gh-canvas-header">
<span class="gh-canvas-title">Advanced</span>
</GhCanvasHeader>
<div class="modal-body">
<section class="view-container">
<div class="gh-setting-header">Installed Themes</div>
<div class="gh-themes-container">
<GhThemeTableLabs @themes={{this.themes}} />
@ -13,9 +12,8 @@
<a href="https://ghost.org/docs/themes/" target=_"blank" rel="noopener noreferrer" class="gh-btn gh-btn-outline">
<span>Theme developer docs</span>
</a>
<button type="button" class="gh-btn gh-btn-black" {{on "click" @close}}><span>Done</span></button>
</div>
</div>
</div>
</div>
</section>
</section>

View File

@ -0,0 +1,26 @@
<section class="gh-canvas relative w-100">
<GhCanvasHeader class="gh-canvas-header">
<h2 class="gh-canvas-title">{{this.config.blogTitle}}</h2>
<section class="view-actions">
<div class="gh-contentfilter gh-btn-group">
<button type="button" class="gh-btn gh-design-preview-mode gh-btn-group-selected"><span>{{svg-jar "desktop"}}</span></button>
<button type="button" class="gh-btn gh-design-preview-mode"><span>{{svg-jar "mobile-phone"}}</span></button>
</div>
<GhTaskButton
@buttonText="Save changes"
@task={{@data.saveTask}}
@successText="Saved"
@runningText="Saving"
@class="gh-btn gh-btn-primary gh-btn-icon"
data-test-button="save-settings"
/>
</section>
</GhCanvasHeader>
<div style="height: calc(100% - 96px)">
<GhBrowserPreview @icon={{this.settings.icon}} @title={{this.config.blogTitle}}>
<GhHtmlIframe id="site-frame" class="site-frame gh-branding-settings-preview" @html={{this.themeManagement.previewHtml}} />
</GhBrowserPreview>
</div>
</section>