mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-03 03:55:26 +03:00
060d791a63
no issue The `settings` service has been a source of confusion when writing with modern Ember patterns because it's use of the deprecated `ProxyMixin` forced all property access/setting to go via `.get()` and `.set()` whereas the rest of the system has mostly (there are a few other uses of ProxyObjects remaining) eliminated the use of the non-native get/set methods. - removed use of `ProxyMixin` in the `settings` service by grabbing the attributes off the setting model after fetching and using `Object.defineProperty()` to add native getters/setters that pass through to the model's getters/setters. Ember's autotracking automatically works across the native getters/setters so we can then use the service as if it was any other native object - updated all code to use `settings.{attrName}` directly for getting/setting instead of `.get()` and `.set()` - removed use of observer in the `customViews` service because it was being set up before the native properties had been added on the settings service meaning autotracking wasn't able to set up properly
96 lines
2.8 KiB
JavaScript
96 lines
2.8 KiB
JavaScript
import Service, {inject as service} from '@ember/service';
|
|
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
|
|
import {tracked} from '@glimmer/tracking';
|
|
|
|
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
|
|
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 = '';
|
|
|
|
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'})
|
|
.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;
|
|
|
|
settingsModel.eachAttribute((name) => {
|
|
if (!Object.prototype.hasOwnProperty.call(this, name)) {
|
|
Object.defineProperty(this, name, {
|
|
get() {
|
|
return this.settingsModel[name];
|
|
},
|
|
set(newValue) {
|
|
this.settingsModel[name] = newValue;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
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();
|
|
}
|
|
}
|