108 lines
3.4 KiB
JavaScript
108 lines
3.4 KiB
JavaScript
import Service, {inject as service} from '@ember/service';
|
|
import Setting from '../models/setting';
|
|
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
|
|
import classic from 'ember-classic-decorator';
|
|
import {computed, defineProperty, get} from '@ember/object';
|
|
import {tracked} from '@glimmer/tracking';
|
|
@classic
|
|
export default class SettingsService extends Service.extend(ValidationEngine) {
|
|
@service store;
|
|
|
|
// will be set to the single Settings model, it's a reference so any later
|
|
// changes to the settings object in the store will be reflected
|
|
@tracked settingsModel = null;
|
|
|
|
validationType = 'setting';
|
|
_loadingPromise = null;
|
|
|
|
// this is an odd case where we only want to react to changes that we get
|
|
// back from the API rather than local updates
|
|
@tracked settledIcon = '';
|
|
|
|
init() {
|
|
super.init(...arguments);
|
|
|
|
// TODO: update to use .getSchemaDefinitionService().attributesDefinitionFor({type: 'settings'});
|
|
// in later Ember versions
|
|
const attributes = get(Setting, 'attributes');
|
|
|
|
for (const [name] of attributes) {
|
|
if (!Object.prototype.hasOwnProperty.call(this, name)) {
|
|
// a standard defineProperty here was not autotracking correctly - retry in a later Ember version
|
|
defineProperty(this, name, computed(`settingsModel.${name}`, {
|
|
get() {
|
|
return this.settingsModel?.[name];
|
|
},
|
|
set(keyName, value) {
|
|
return this.settingsModel[name] = value;
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
|
|
get hasDirtyAttributes() {
|
|
return this.settingsModel?.hasDirtyAttributes || false;
|
|
}
|
|
|
|
get mailgunIsConfigured() {
|
|
return this.mailgunApiKey && this.mailgunDomain && this.mailgunBaseUrl;
|
|
}
|
|
|
|
// the settings API endpoint is a little weird as it's singular and we have
|
|
// to pass in all types - if we ever fetch settings without all types then
|
|
// save we have problems with the missing settings being removed or reset
|
|
_loadSettings() {
|
|
if (!this._loadingPromise) {
|
|
this._loadingPromise = this.store
|
|
.queryRecord('setting', {group: 'site,theme,private,members,portal,newsletter,email,amp,labs,slack,unsplash,views,firstpromoter,editor,comments,analytics,announcement,pintura,donations,recommendations'})
|
|
.then((settings) => {
|
|
this._loadingPromise = null;
|
|
return settings;
|
|
});
|
|
}
|
|
|
|
return this._loadingPromise;
|
|
}
|
|
|
|
async fetch() {
|
|
if (!this.settingsModel) {
|
|
return this.reload();
|
|
} else {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
async reload() {
|
|
const settingsModel = await this._loadSettings();
|
|
|
|
this.settingsModel = settingsModel;
|
|
this.settledIcon = settingsModel.icon;
|
|
|
|
return this;
|
|
}
|
|
|
|
async save() {
|
|
const {settingsModel} = this;
|
|
|
|
if (!settingsModel) {
|
|
return false;
|
|
}
|
|
|
|
await settingsModel.save();
|
|
await this.validate();
|
|
|
|
this.settledIcon = settingsModel.icon;
|
|
|
|
return this;
|
|
}
|
|
|
|
rollbackAttributes() {
|
|
return this.settingsModel?.rollbackAttributes();
|
|
}
|
|
|
|
changedAttributes() {
|
|
return this.settingsModel?.changedAttributes();
|
|
}
|
|
}
|