mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 20:03:12 +03:00
9380209670
refs TryGhost/Team#3008 --- <!-- Leave the line below if you'd like GitHub Copilot to generate a summary from your commit --> <!-- copilot:summary --> ### <samp>🤖 Generated by Copilot at 2a60623</samp> This pull request adds a new experimental feature for displaying an announcement bar at the top of the site. It introduces a new component template and class for the announcement bar, a new feature flag and its UI controls, and some CSS adjustments for the editor input and the announcement bar.
162 lines
5.0 KiB
JavaScript
162 lines
5.0 KiB
JavaScript
import $ from 'jquery';
|
|
import Ember from 'ember';
|
|
import EmberError from '@ember/error';
|
|
import Service, {inject as service} from '@ember/service';
|
|
import classic from 'ember-classic-decorator';
|
|
import {computed, set} from '@ember/object';
|
|
import {inject} from 'ghost-admin/decorators/inject';
|
|
|
|
export function feature(name, options = {}) {
|
|
let {user, onChange} = options;
|
|
let watchedProps = user ? [`accessibility.${name}`] : [`config.${name}`, `labs.${name}`];
|
|
|
|
return computed.apply(Ember, watchedProps.concat({
|
|
get() {
|
|
let enabled = false;
|
|
|
|
if (user) {
|
|
enabled = this.get(`accessibility.${name}`);
|
|
} else if (this.get(`config.${name}`)) {
|
|
enabled = this.get(`config.${name}`);
|
|
} else {
|
|
enabled = this.get(`labs.${name}`) || false;
|
|
}
|
|
|
|
return enabled;
|
|
},
|
|
set(key, value) {
|
|
this.update(key, value, options);
|
|
|
|
if (onChange) {
|
|
// value must be passed here because the value isn't set until
|
|
// the setter function returns
|
|
this.get(onChange).bind(this)(value);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}));
|
|
}
|
|
|
|
@classic
|
|
export default class FeatureService extends Service {
|
|
@service lazyLoader;
|
|
@service notifications;
|
|
@service session;
|
|
@service settings;
|
|
@service store;
|
|
|
|
@inject config;
|
|
|
|
// features
|
|
@feature('emailAnalytics') emailAnalytics;
|
|
|
|
// user-specific flags
|
|
@feature('nightShift', {user: true, onChange: '_setAdminTheme'})
|
|
nightShift;
|
|
|
|
// user-specific referral invitation
|
|
@feature('referralInviteDismissed', {user: true}) referralInviteDismissed;
|
|
|
|
// labs flags
|
|
@feature('urlCache') urlCache;
|
|
@feature('memberAttribution') memberAttribution;
|
|
@feature('sourceAttribution') sourceAttribution;
|
|
@feature('lexicalEditor') lexicalEditor;
|
|
@feature('lexicalMultiplayer') lexicalMultiplayer;
|
|
@feature('audienceFeedback') audienceFeedback;
|
|
@feature('suppressionList') suppressionList;
|
|
@feature('webmentions') webmentions;
|
|
@feature('emailErrors') emailErrors;
|
|
@feature('websockets') websockets;
|
|
@feature('stripeAutomaticTax') stripeAutomaticTax;
|
|
@feature('makingItRain') makingItRain;
|
|
@feature('migrateApp') migrateApp;
|
|
@feature('i18n') i18n;
|
|
@feature('postHistory') postHistory;
|
|
@feature('announcementBar') announcementBar;
|
|
|
|
_user = null;
|
|
|
|
@computed('settings.labs')
|
|
get labs() {
|
|
let labs = this.settings.labs;
|
|
|
|
try {
|
|
return JSON.parse(labs) || {};
|
|
} catch (e) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
@computed('_user.accessibility')
|
|
get accessibility() {
|
|
let accessibility = this.get('_user.accessibility');
|
|
|
|
try {
|
|
return JSON.parse(accessibility) || {};
|
|
} catch (e) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
fetch() {
|
|
return this.settings.fetch().then(() => {
|
|
this.set('_user', this.session.user);
|
|
return this._setAdminTheme().then(() => true);
|
|
});
|
|
}
|
|
|
|
update(key, value, options = {}) {
|
|
let serviceProperty = options.user ? 'accessibility' : 'labs';
|
|
let model = this.get(options.user ? '_user' : 'settings');
|
|
let featureObject = this.get(serviceProperty);
|
|
|
|
// set the new key value for either the labs property or the accessibility property
|
|
set(featureObject, key, value);
|
|
|
|
if (options.requires && value === true) {
|
|
options.requires.forEach((flag) => {
|
|
set(featureObject, flag, true);
|
|
});
|
|
}
|
|
|
|
// update the 'labs' or 'accessibility' key of the model
|
|
model.set(serviceProperty, JSON.stringify(featureObject));
|
|
|
|
return model.save().then(() => {
|
|
// return the labs key value that we get from the server
|
|
this.notifyPropertyChange(serviceProperty);
|
|
return this.get(`${serviceProperty}.${key}`);
|
|
}).catch((error) => {
|
|
model.rollbackAttributes();
|
|
this.notifyPropertyChange(serviceProperty);
|
|
|
|
// we'll always have an errors object unless we hit a
|
|
// validation error
|
|
if (!error) {
|
|
throw new EmberError(`Validation of the feature service ${options.user ? 'user' : 'settings'} model failed when updating ${serviceProperty}.`);
|
|
}
|
|
|
|
this.notifications.showAPIError(error);
|
|
|
|
return this.get(`${serviceProperty}.${key}`);
|
|
});
|
|
}
|
|
|
|
_setAdminTheme(enabled) {
|
|
let nightShift = enabled;
|
|
|
|
if (typeof nightShift === 'undefined') {
|
|
nightShift = enabled || this.nightShift;
|
|
}
|
|
|
|
return this.lazyLoader.loadStyle('dark', 'assets/ghost-dark.css', true).then(() => {
|
|
$('link[title=dark]').prop('disabled', !nightShift);
|
|
}).catch(() => {
|
|
//TODO: Also disable toggle from settings and Labs hover
|
|
$('link[title=dark]').prop('disabled', true);
|
|
});
|
|
}
|
|
}
|