Ghost/ghost/admin/app/services/feature.js
Kevin Ansfield c3b49b45cf 🎨 synchronous settings service
no issue
- adds `settings` service that acts as a proxy to the singular settings model with methods to fetch and reload, also prevents accidentally loading only some settings types which has caused problems in the past
- updates app boot, signin, and signup processes to fetch settings ensuring that any part of the app can grab settings synchronously if needed
- removes `timeZone` service, it's no longer needed as we can grab `settings.activeTimezone` directly
- replaces all store queries for the settings model with appropriate `settings` methods
- refactors `apps/*` routes/controllers, they had become a little convoluted with the way they were dealing with settings and the new service helped to clean that up
2017-03-20 07:43:49 -05:00

109 lines
3.1 KiB
JavaScript

import Ember from 'ember';
import Service from 'ember-service';
import computed from 'ember-computed';
import injectService from 'ember-service/inject';
import set from 'ember-metal/set';
import RSVP from 'rsvp';
// ember-cli-shims doesn't export Error
const {Error: EmberError} = Ember;
export function feature(name, user = false) {
let watchedProps = user ? [`accessibility.${name}`] : [`config.${name}`, `labs.${name}`];
return computed.apply(Ember, watchedProps.concat({
get() {
if (user) {
return this.get(`accessibility.${name}`);
}
if (this.get(`config.${name}`)) {
return this.get(`config.${name}`);
}
return this.get(`labs.${name}`) || false;
},
set(key, value) {
this.update(key, value, user);
return value;
}
}));
}
export default Service.extend({
store: injectService(),
config: injectService(),
session: injectService(),
settings: injectService(),
notifications: injectService(),
publicAPI: feature('publicAPI'),
subscribers: feature('subscribers'),
nightShift: feature('nightShift', true),
_user: null,
labs: computed('settings.labs', function () {
let labs = this.get('settings.labs');
try {
return JSON.parse(labs) || {};
} catch (e) {
return {};
}
}),
accessibility: computed('_user.accessibility', function () {
let accessibility = this.get('_user.accessibility');
try {
return JSON.parse(accessibility) || {};
} catch (e) {
return {};
}
}),
fetch() {
return RSVP.hash({
settings: this.get('settings').fetch(),
user: this.get('session.user')
}).then(({user}) => {
this.set('_user', user);
return true;
});
},
update(key, value, user = false) {
let serviceProperty = user ? 'accessibility' : 'labs';
let model = this.get(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);
// 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 ${user ? 'user' : 'settings'} model failed when updating ${serviceProperty}.`);
}
this.get('notifications').showAPIError(error);
return this.get(`${serviceProperty}.${key}`);
});
}
});