2018-01-11 17:16:42 +03:00
|
|
|
import $ from 'jquery';
|
2016-01-19 17:25:36 +03:00
|
|
|
import Ember from 'ember';
|
2017-08-22 10:53:26 +03:00
|
|
|
import EmberError from '@ember/error';
|
2017-10-30 12:38:01 +03:00
|
|
|
import Service, {inject as service} from '@ember/service';
|
2022-02-03 01:11:11 +03:00
|
|
|
import classic from 'ember-classic-decorator';
|
2022-01-21 22:25:47 +03:00
|
|
|
import {computed, set} from '@ember/object';
|
2022-11-03 14:14:36 +03:00
|
|
|
import {inject} from 'ghost-admin/decorators/inject';
|
2016-01-19 17:25:36 +03:00
|
|
|
|
2018-01-11 17:16:42 +03:00
|
|
|
export function feature(name, options = {}) {
|
|
|
|
let {user, onChange} = options;
|
2017-03-03 19:14:33 +03:00
|
|
|
let watchedProps = user ? [`accessibility.${name}`] : [`config.${name}`, `labs.${name}`];
|
|
|
|
|
|
|
|
return computed.apply(Ember, watchedProps.concat({
|
2016-01-19 17:25:36 +03:00
|
|
|
get() {
|
2018-01-18 18:36:01 +03:00
|
|
|
let enabled = false;
|
|
|
|
|
2017-03-03 19:14:33 +03:00
|
|
|
if (user) {
|
2018-01-18 18:36:01 +03:00
|
|
|
enabled = this.get(`accessibility.${name}`);
|
|
|
|
} else if (this.get(`config.${name}`)) {
|
|
|
|
enabled = this.get(`config.${name}`);
|
|
|
|
} else {
|
|
|
|
enabled = this.get(`labs.${name}`) || false;
|
2017-03-03 19:14:33 +03:00
|
|
|
}
|
|
|
|
|
2018-01-18 18:36:01 +03:00
|
|
|
return enabled;
|
2016-01-19 17:25:36 +03:00
|
|
|
},
|
|
|
|
set(key, value) {
|
2018-01-18 18:36:01 +03:00
|
|
|
this.update(key, value, options);
|
2018-01-11 17:16:42 +03:00
|
|
|
|
|
|
|
if (onChange) {
|
|
|
|
// value must be passed here because the value isn't set until
|
|
|
|
// the setter function returns
|
|
|
|
this.get(onChange).bind(this)(value);
|
|
|
|
}
|
|
|
|
|
2016-05-05 17:03:09 +03:00
|
|
|
return value;
|
2016-01-19 17:25:36 +03:00
|
|
|
}
|
2017-03-03 19:14:33 +03:00
|
|
|
}));
|
2016-01-19 17:25:36 +03:00
|
|
|
}
|
|
|
|
|
2022-02-03 01:11:11 +03:00
|
|
|
@classic
|
|
|
|
export default class FeatureService extends Service {
|
2022-11-03 14:14:36 +03:00
|
|
|
@service lazyLoader;
|
|
|
|
@service notifications;
|
2022-02-03 22:04:43 +03:00
|
|
|
@service session;
|
|
|
|
@service settings;
|
2022-11-03 14:14:36 +03:00
|
|
|
@service store;
|
2022-02-03 01:11:11 +03:00
|
|
|
|
2022-11-03 14:14:36 +03:00
|
|
|
@inject config;
|
2016-01-19 17:25:36 +03:00
|
|
|
|
2022-01-31 16:05:20 +03:00
|
|
|
// features
|
2022-04-20 18:48:54 +03:00
|
|
|
@feature('emailAnalytics') emailAnalytics;
|
2022-01-31 16:05:20 +03:00
|
|
|
|
|
|
|
// user-specific flags
|
2022-02-03 01:11:11 +03:00
|
|
|
@feature('nightShift', {user: true, onChange: '_setAdminTheme'})
|
2022-02-14 15:15:32 +03:00
|
|
|
nightShift;
|
2022-02-03 01:11:11 +03:00
|
|
|
|
2023-01-26 17:42:11 +03:00
|
|
|
// user-specific referral invitation
|
|
|
|
@feature('referralInviteDismissed', {user: true}) referralInviteDismissed;
|
|
|
|
|
2022-01-31 16:05:20 +03:00
|
|
|
// labs flags
|
2022-04-20 18:48:54 +03:00
|
|
|
@feature('urlCache') urlCache;
|
2022-08-15 23:14:02 +03:00
|
|
|
@feature('memberAttribution') memberAttribution;
|
2022-09-13 11:29:23 +03:00
|
|
|
@feature('sourceAttribution') sourceAttribution;
|
2022-09-16 13:58:56 +03:00
|
|
|
@feature('lexicalEditor') lexicalEditor;
|
2023-04-12 22:24:02 +03:00
|
|
|
@feature('lexicalMultiplayer') lexicalMultiplayer;
|
2022-10-10 10:27:45 +03:00
|
|
|
@feature('audienceFeedback') audienceFeedback;
|
2022-11-18 14:55:21 +03:00
|
|
|
@feature('suppressionList') suppressionList;
|
2023-01-17 00:03:36 +03:00
|
|
|
@feature('webmentions') webmentions;
|
2023-01-25 15:20:50 +03:00
|
|
|
@feature('emailErrors') emailErrors;
|
2023-02-17 13:25:51 +03:00
|
|
|
@feature('websockets') websockets;
|
2023-02-28 10:07:32 +03:00
|
|
|
@feature('stripeAutomaticTax') stripeAutomaticTax;
|
2023-03-13 11:56:35 +03:00
|
|
|
@feature('makingItRain') makingItRain;
|
2023-03-30 17:40:06 +03:00
|
|
|
@feature('migrateApp') migrateApp;
|
2023-03-20 23:31:58 +03:00
|
|
|
@feature('i18n') i18n;
|
2023-04-17 13:08:47 +03:00
|
|
|
@feature('postHistory') postHistory;
|
2023-04-18 12:12:37 +03:00
|
|
|
@feature('announcementBar') announcementBar;
|
2022-02-21 18:45:59 +03:00
|
|
|
|
2022-02-03 01:11:11 +03:00
|
|
|
_user = null;
|
|
|
|
|
|
|
|
@computed('settings.labs')
|
|
|
|
get labs() {
|
2022-10-07 16:23:21 +03:00
|
|
|
let labs = this.settings.labs;
|
2016-01-19 17:25:36 +03:00
|
|
|
|
|
|
|
try {
|
|
|
|
return JSON.parse(labs) || {};
|
|
|
|
} catch (e) {
|
|
|
|
return {};
|
|
|
|
}
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|
2016-05-05 17:03:09 +03:00
|
|
|
|
2022-02-03 01:11:11 +03:00
|
|
|
@computed('_user.accessibility')
|
|
|
|
get accessibility() {
|
2017-03-03 19:14:33 +03:00
|
|
|
let accessibility = this.get('_user.accessibility');
|
|
|
|
|
|
|
|
try {
|
|
|
|
return JSON.parse(accessibility) || {};
|
|
|
|
} catch (e) {
|
|
|
|
return {};
|
|
|
|
}
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|
2017-03-03 19:14:33 +03:00
|
|
|
|
2016-05-05 17:03:09 +03:00
|
|
|
fetch() {
|
2021-07-08 16:37:31 +03:00
|
|
|
return this.settings.fetch().then(() => {
|
|
|
|
this.set('_user', this.session.user);
|
2018-01-11 17:16:42 +03:00
|
|
|
return this._setAdminTheme().then(() => true);
|
2016-05-05 17:03:09 +03:00
|
|
|
});
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|
2016-01-19 17:25:36 +03:00
|
|
|
|
2018-01-18 18:36:01 +03:00
|
|
|
update(key, value, options = {}) {
|
|
|
|
let serviceProperty = options.user ? 'accessibility' : 'labs';
|
|
|
|
let model = this.get(options.user ? '_user' : 'settings');
|
2017-03-03 19:14:33 +03:00
|
|
|
let featureObject = this.get(serviceProperty);
|
|
|
|
|
|
|
|
// set the new key value for either the labs property or the accessibility property
|
|
|
|
set(featureObject, key, value);
|
2016-05-05 17:03:09 +03:00
|
|
|
|
2021-10-12 17:33:03 +03:00
|
|
|
if (options.requires && value === true) {
|
|
|
|
options.requires.forEach((flag) => {
|
|
|
|
set(featureObject, flag, true);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-03-03 19:14:33 +03:00
|
|
|
// update the 'labs' or 'accessibility' key of the model
|
|
|
|
model.set(serviceProperty, JSON.stringify(featureObject));
|
2016-05-05 17:03:09 +03:00
|
|
|
|
2017-03-03 19:14:33 +03:00
|
|
|
return model.save().then(() => {
|
2016-05-05 17:03:09 +03:00
|
|
|
// return the labs key value that we get from the server
|
2017-03-03 19:14:33 +03:00
|
|
|
this.notifyPropertyChange(serviceProperty);
|
|
|
|
return this.get(`${serviceProperty}.${key}`);
|
2016-06-30 17:45:02 +03:00
|
|
|
}).catch((error) => {
|
2017-03-03 19:14:33 +03:00
|
|
|
model.rollbackAttributes();
|
|
|
|
this.notifyPropertyChange(serviceProperty);
|
2016-05-05 17:03:09 +03:00
|
|
|
|
|
|
|
// we'll always have an errors object unless we hit a
|
|
|
|
// validation error
|
2016-06-30 17:45:02 +03:00
|
|
|
if (!error) {
|
2018-01-18 18:36:01 +03:00
|
|
|
throw new EmberError(`Validation of the feature service ${options.user ? 'user' : 'settings'} model failed when updating ${serviceProperty}.`);
|
2016-05-05 17:03:09 +03:00
|
|
|
}
|
|
|
|
|
2019-03-06 16:53:54 +03:00
|
|
|
this.notifications.showAPIError(error);
|
2016-05-05 17:03:09 +03:00
|
|
|
|
2017-03-03 19:14:33 +03:00
|
|
|
return this.get(`${serviceProperty}.${key}`);
|
2016-01-19 17:25:36 +03:00
|
|
|
});
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|
2018-01-11 17:16:42 +03:00
|
|
|
|
|
|
|
_setAdminTheme(enabled) {
|
2018-03-09 12:34:43 +03:00
|
|
|
let nightShift = enabled;
|
|
|
|
|
|
|
|
if (typeof nightShift === 'undefined') {
|
2019-03-06 16:53:54 +03:00
|
|
|
nightShift = enabled || this.nightShift;
|
2018-03-09 12:34:43 +03:00
|
|
|
}
|
2018-01-11 17:16:42 +03:00
|
|
|
|
2019-03-06 16:53:54 +03:00
|
|
|
return this.lazyLoader.loadStyle('dark', 'assets/ghost-dark.css', true).then(() => {
|
2018-01-11 17:16:42 +03:00
|
|
|
$('link[title=dark]').prop('disabled', !nightShift);
|
2019-06-18 14:54:37 +03:00
|
|
|
}).catch(() => {
|
|
|
|
//TODO: Also disable toggle from settings and Labs hover
|
|
|
|
$('link[title=dark]').prop('disabled', true);
|
2018-01-11 17:16:42 +03:00
|
|
|
});
|
2016-01-19 17:25:36 +03:00
|
|
|
}
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|