2022-01-21 22:25:47 +03:00
|
|
|
import Service, {inject as service} from '@ember/service';
|
2023-08-21 13:26:51 +03:00
|
|
|
import nql from '@tryghost/nql';
|
2021-10-18 18:39:54 +03:00
|
|
|
import {isEmpty} from '@ember/utils';
|
2021-09-27 16:01:09 +03:00
|
|
|
import {run} from '@ember/runloop';
|
2022-02-09 13:49:38 +03:00
|
|
|
import {task} from 'ember-concurrency';
|
2021-09-27 16:01:09 +03:00
|
|
|
import {tracked} from '@glimmer/tracking';
|
|
|
|
|
2023-09-13 10:38:31 +03:00
|
|
|
const HIDDEN_SETTING_VALUE = null;
|
|
|
|
|
2021-09-27 16:01:09 +03:00
|
|
|
export default class CustomThemeSettingsServices extends Service {
|
|
|
|
@service store;
|
|
|
|
|
|
|
|
@tracked settings = [];
|
2021-10-14 16:15:11 +03:00
|
|
|
@tracked settingGroups = [];
|
|
|
|
|
2021-10-22 12:46:12 +03:00
|
|
|
_hasLoaded = false;
|
|
|
|
|
2021-10-14 16:15:11 +03:00
|
|
|
KNOWN_GROUPS = [{
|
|
|
|
key: 'homepage',
|
|
|
|
name: 'Homepage',
|
|
|
|
icon: 'house',
|
|
|
|
previewType: 'homepage'
|
|
|
|
}, {
|
|
|
|
key: 'post',
|
|
|
|
name: 'Post',
|
|
|
|
icon: 'post',
|
|
|
|
previewType: 'post'
|
|
|
|
}];
|
2021-09-27 16:01:09 +03:00
|
|
|
|
2021-09-28 18:12:01 +03:00
|
|
|
get isDirty() {
|
|
|
|
const dirtySetting = this.settings.find(setting => setting.hasDirtyAttributes);
|
|
|
|
return !!dirtySetting;
|
|
|
|
}
|
|
|
|
|
2021-09-30 15:28:26 +03:00
|
|
|
get keyValueObject() {
|
|
|
|
const keyValue = {};
|
|
|
|
|
|
|
|
this.settings.forEach((setting) => {
|
2023-09-13 10:38:31 +03:00
|
|
|
keyValue[setting.key] = this._isSettingVisible(setting) ? setting.value : HIDDEN_SETTING_VALUE;
|
2021-09-30 15:28:26 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
return keyValue;
|
|
|
|
}
|
|
|
|
|
2021-09-27 16:01:09 +03:00
|
|
|
load() {
|
|
|
|
return this.loadTask.perform();
|
|
|
|
}
|
|
|
|
|
2021-10-22 12:46:12 +03:00
|
|
|
reload() {
|
|
|
|
this._hasLoaded = false;
|
|
|
|
|
|
|
|
return this.loadTask.perform();
|
|
|
|
}
|
|
|
|
|
2021-09-27 16:01:09 +03:00
|
|
|
@task
|
|
|
|
*loadTask() {
|
2021-10-22 12:46:12 +03:00
|
|
|
if (this.hasLoaded) {
|
|
|
|
return this.settings;
|
|
|
|
}
|
|
|
|
|
2021-09-27 16:01:09 +03:00
|
|
|
// unload stored settings and re-load from API so they always match active theme
|
|
|
|
// run is required here, see https://github.com/emberjs/data/issues/5447#issuecomment-845672812
|
|
|
|
run(() => this.store.unloadAll('custom-theme-setting'));
|
|
|
|
|
|
|
|
const settings = yield this.store.findAll('custom-theme-setting');
|
|
|
|
this.settings = settings;
|
2021-10-14 16:15:11 +03:00
|
|
|
this.settingGroups = this._buildSettingGroups(settings);
|
2021-09-27 16:01:09 +03:00
|
|
|
|
2023-09-13 10:38:31 +03:00
|
|
|
this.updateSettingsVisibility();
|
|
|
|
|
2021-10-22 12:46:12 +03:00
|
|
|
this._hasLoaded = true;
|
|
|
|
|
2021-09-27 16:01:09 +03:00
|
|
|
return this.settings;
|
|
|
|
}
|
|
|
|
|
|
|
|
save() {
|
|
|
|
return this.saveTask.perform();
|
|
|
|
}
|
|
|
|
|
|
|
|
@task
|
|
|
|
*saveTask() {
|
2021-10-18 18:39:54 +03:00
|
|
|
if (isEmpty(this.settings)) {
|
|
|
|
return this.settings;
|
|
|
|
}
|
|
|
|
|
2021-09-27 16:01:09 +03:00
|
|
|
// save all records in a single request to `/custom_theme_settings`
|
|
|
|
const listRecord = this.store.createRecord('custom-theme-setting-list', {customThemeSettings: this.settings});
|
|
|
|
yield listRecord.save();
|
|
|
|
|
2021-09-30 18:29:41 +03:00
|
|
|
// don't keep references to lists and their children around
|
2021-09-27 16:01:09 +03:00
|
|
|
this.store.unloadRecord(listRecord);
|
|
|
|
|
|
|
|
return this.settings;
|
|
|
|
}
|
|
|
|
|
|
|
|
rollback() {
|
2021-10-19 18:22:16 +03:00
|
|
|
this.settings.forEach(setting => setting.rollbackAttributes());
|
2021-10-14 16:15:11 +03:00
|
|
|
}
|
|
|
|
|
2023-09-13 10:38:31 +03:00
|
|
|
updateSettingsVisibility() {
|
|
|
|
this.settings.forEach((setting) => {
|
|
|
|
setting.visible = this._isSettingVisible(setting);
|
2023-09-27 10:18:21 +03:00
|
|
|
|
|
|
|
// Updating the setting visibility will cause the setting to be marked as dirty so
|
|
|
|
// we need to compute whether the setting is actually dirty and set the flag manually
|
|
|
|
const changedProperties = Object.keys(setting.changedAttributes()).filter(key => key !== 'visible');
|
|
|
|
|
|
|
|
setting.hasDirtyAttributes = false;
|
|
|
|
|
|
|
|
if (changedProperties.length > 0) {
|
|
|
|
setting.hasDirtyAttributes = true;
|
|
|
|
}
|
2023-09-13 10:38:31 +03:00
|
|
|
});
|
2023-08-21 13:26:51 +03:00
|
|
|
}
|
|
|
|
|
2021-10-14 16:15:11 +03:00
|
|
|
_buildSettingGroups(settings) {
|
|
|
|
if (!settings || !settings.length) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
const groupKeys = this.KNOWN_GROUPS.map(g => g.key);
|
|
|
|
const groups = [];
|
|
|
|
|
|
|
|
const siteWideSettings = settings.filter(setting => !groupKeys.includes(setting.group));
|
|
|
|
if (siteWideSettings.length) {
|
|
|
|
groups.push({
|
|
|
|
key: 'site-wide',
|
|
|
|
name: 'Site-wide',
|
|
|
|
icon: 'view-site',
|
|
|
|
settings: siteWideSettings
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.KNOWN_GROUPS.forEach((knownGroup) => {
|
2023-09-13 10:38:31 +03:00
|
|
|
const groupSettings = settings.filter(setting => setting.group === knownGroup.key);
|
2021-10-14 16:15:11 +03:00
|
|
|
|
|
|
|
if (groupSettings.length) {
|
2021-10-14 18:58:05 +03:00
|
|
|
groups.push(Object.assign({}, knownGroup, {settings: groupSettings}));
|
2021-10-14 16:15:11 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return groups;
|
2021-09-27 16:01:09 +03:00
|
|
|
}
|
2023-09-13 10:38:31 +03:00
|
|
|
|
|
|
|
_isSettingVisible(setting) {
|
|
|
|
if (!setting.visibility) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const settingsMap = this.settings.reduce((map, {key, value}) => ({...map, [key]: value}), {});
|
|
|
|
|
|
|
|
return nql(setting.visibility).queryJSON(settingsMap);
|
|
|
|
}
|
2021-09-27 16:01:09 +03:00
|
|
|
}
|