Announcement
- Announcement visibility
+ Visibility
-
+
+
+ {{!--
{{#each this.options as |settingOption|}}
@@ -13,6 +46,6 @@
{{/each}}
{{svg-jar "arrow-down-small"}}
-
+ --}}
\ No newline at end of file
diff --git a/ghost/admin/app/components/gh-nav-menu/announcement-bar.hbs b/ghost/admin/app/components/gh-nav-menu/announcement-bar.hbs
new file mode 100644
index 0000000000..d9bc633e10
--- /dev/null
+++ b/ghost/admin/app/components/gh-nav-menu/announcement-bar.hbs
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/ghost/admin/app/components/gh-nav-menu/announcement-bar.js b/ghost/admin/app/components/gh-nav-menu/announcement-bar.js
new file mode 100644
index 0000000000..2d0934d0be
--- /dev/null
+++ b/ghost/admin/app/components/gh-nav-menu/announcement-bar.js
@@ -0,0 +1,86 @@
+import Component from '@glimmer/component';
+import {action} from '@ember/object';
+import {bind} from '@ember/runloop';
+import {inject} from 'ghost-admin/decorators/inject';
+import {isEmpty} from '@ember/utils';
+import {inject as service} from '@ember/service';
+import {tracked} from '@glimmer/tracking';
+
+export default class AnnouncementBarMenuComponent extends Component {
+ @service customThemeSettings;
+ @service router;
+ @service settings;
+ @service store;
+ @service themeManagement;
+
+ @inject config;
+
+ @tracked openSection = null;
+
+ themes = this.store.peekAll('theme');
+
+ constructor() {
+ super(...arguments);
+
+ // fetch all themes in the background so we can show the active theme
+ this.store.findAll('theme');
+
+ if (this.router.currentRouteName === 'settings.announcement-bar.index') {
+ this.openDefaultSection();
+ }
+
+ this.routeDidChangeHandler = bind(this, this.handleRouteDidChange);
+ this.router.on('routeDidChange', this.routeDidChangeHandler);
+ }
+
+ willDestroy() {
+ super.willDestroy(...arguments);
+ this.router.off('routeDidChange', this.routeDidChangeHandler);
+ }
+
+ get activeTheme() {
+ return this.themes.findBy('active', true);
+ }
+
+ @action
+ toggleSection(section) {
+ if (this.openSection === section) {
+ this.openSection = null;
+ } else {
+ this.openSection = section;
+
+ const group = this.customThemeSettings.KNOWN_GROUPS.findBy('key', section);
+ if (group && group.previewType) {
+ this.themeManagement.setPreviewType(group.previewType);
+ } else {
+ this.themeManagement.setPreviewType('homepage');
+ }
+ }
+ }
+
+ @action
+ transitionBackToIndex() {
+ if (this.router.currentRouteName !== 'settings.announcement-bar.index') {
+ this.router.transitionTo('settings.announcement-bar.index');
+ }
+ }
+
+ @action
+ closeAllSections() {
+ this.openSection = null;
+ }
+
+ openDefaultSection() {
+ const noCustomSettings = isEmpty(this.customThemeSettings.settings);
+
+ if (noCustomSettings) {
+ this.openSection = 'brand';
+ }
+ }
+
+ handleRouteDidChange(transition) {
+ if (!transition.isAborted && transition.to?.name === 'settings.announcement-bar.index') {
+ this.openDefaultSection();
+ }
+ }
+}
diff --git a/ghost/admin/app/components/settings/design/theme-settings-form.hbs b/ghost/admin/app/components/settings/design/theme-settings-form.hbs
index f3078ad61d..8e12981bd2 100644
--- a/ghost/admin/app/components/settings/design/theme-settings-form.hbs
+++ b/ghost/admin/app/components/settings/design/theme-settings-form.hbs
@@ -17,10 +17,5 @@
{{/if}}
{{/each}}
- {{#if (feature 'announcementBar')}}
-
-
-
- {{/if}}
\ No newline at end of file
diff --git a/ghost/admin/app/controllers/settings/announcement-bar/index.js b/ghost/admin/app/controllers/settings/announcement-bar/index.js
new file mode 100644
index 0000000000..32f8fecb74
--- /dev/null
+++ b/ghost/admin/app/controllers/settings/announcement-bar/index.js
@@ -0,0 +1,63 @@
+import Controller from '@ember/controller';
+import {action} from '@ember/object';
+import {inject} from 'ghost-admin/decorators/inject';
+import {inject as service} from '@ember/service';
+import {task} from 'ember-concurrency';
+import {tracked} from '@glimmer/tracking';
+
+export default class SettingsAnnouncementBarIndexController extends Controller {
+ @service customThemeSettings;
+ @service notifications;
+ @service settings;
+ @service themeManagement;
+
+ @inject config;
+
+ @tracked previewSize = 'desktop';
+
+ get isDesktopPreview() {
+ return this.previewSize === 'desktop';
+ }
+
+ get isMobilePreview() {
+ return this.previewSize === 'mobile';
+ }
+
+ @action
+ setPreviewSize(size) {
+ this.previewSize = size;
+ }
+
+ @action
+ saveFromKeyboard() {
+ document.activeElement.blur?.();
+ return this.saveTask.perform();
+ }
+
+ @task
+ *saveTask() {
+ try {
+ if (this.settings.errors.length !== 0) {
+ return;
+ }
+
+ yield Promise.all([
+ this.settings.save(),
+ this.customThemeSettings.save()
+ ]);
+
+ // ensure task button switches to success state
+ return true;
+ } catch (error) {
+ if (error) {
+ this.notifications.showAPIError(error);
+ throw error;
+ }
+ }
+ }
+
+ reset() {
+ this.previewSize = 'desktop';
+ this.themeManagement.setPreviewType('homepage');
+ }
+}
diff --git a/ghost/admin/app/router.js b/ghost/admin/app/router.js
index b1130b8580..65d632ce1d 100644
--- a/ghost/admin/app/router.js
+++ b/ghost/admin/app/router.js
@@ -56,6 +56,7 @@ Router.map(function () {
this.route('settings.code-injection', {path: '/settings/code-injection'});
this.route('settings.history', {path: '/settings/history'});
this.route('settings.analytics', {path: '/settings/analytics'});
+ this.route('settings.announcement-bar', {path: '/settings/announcement-bar'}, function () {});
// testing websockets
this.route('websockets');
diff --git a/ghost/admin/app/routes/settings/announcement-bar.js b/ghost/admin/app/routes/settings/announcement-bar.js
new file mode 100644
index 0000000000..69b6ffe4cd
--- /dev/null
+++ b/ghost/admin/app/routes/settings/announcement-bar.js
@@ -0,0 +1,52 @@
+import AdminRoute from 'ghost-admin/routes/authenticated';
+import {inject as service} from '@ember/service';
+
+export default class SettingsDesignRoute extends AdminRoute {
+ @service customThemeSettings;
+ @service feature;
+ @service modals;
+ @service settings;
+ @service themeManagement;
+ @service ui;
+ @service session;
+ @service store;
+
+ model() {
+ // background refresh of preview
+ // not doing it on the 'index' route so that we don't reload going to/from the index,
+ // any actions performed on child routes that need a refresh should trigger it explicitly
+ this.themeManagement.updatePreviewHtmlTask.perform();
+
+ // wait for settings to be loaded - we need the data to be present before display
+ return Promise.all([
+ this.settings.reload(),
+ this.customThemeSettings.load(),
+ this.store.findAll('theme')
+ ]);
+ }
+
+ beforeModel() {
+ super.beforeModel(...arguments);
+
+ const user = this.session.user;
+
+ if (!user.isAdmin) {
+ return this.transitionTo('settings.staff.user', user);
+ }
+ }
+
+ activate() {
+ this.ui.contextualNavMenu = 'announcement-bar';
+ }
+
+ deactivate() {
+ this.ui.contextualNavMenu = null;
+ }
+
+ buildRouteInfoMetadata() {
+ return {
+ titleToken: 'Settings - Announcement bar',
+ mainClasses: ['gh-main-fullwidth']
+ };
+ }
+}
diff --git a/ghost/admin/app/templates/settings.hbs b/ghost/admin/app/templates/settings.hbs
index 8e7e093f07..c26997c24f 100644
--- a/ghost/admin/app/templates/settings.hbs
+++ b/ghost/admin/app/templates/settings.hbs
@@ -49,6 +49,16 @@
Manage authors, editor and collaborators