Use settings structs
This commit is contained in:
parent
3574d6a5ba
commit
3437c36b87
|
@ -12,7 +12,7 @@ import Globals from './globals';
|
|||
import { FileUtils, ClientLogger as Logger } from 'common';
|
||||
import path from 'path';
|
||||
import { Events } from 'modules';
|
||||
import { ErrorEvent } from 'structs';
|
||||
import { SettingsSet, ErrorEvent } from 'structs';
|
||||
import { Modals } from 'ui';
|
||||
|
||||
/**
|
||||
|
@ -54,6 +54,10 @@ export default class {
|
|||
const directories = await FileUtils.listDirectory(this.contentPath);
|
||||
|
||||
for (let dir of directories) {
|
||||
try {
|
||||
await FileUtils.directoryExists(path.join(this.contentPath, dir));
|
||||
} catch (err) { continue; }
|
||||
|
||||
try {
|
||||
await this.preloadContent(dir);
|
||||
} catch (err) {
|
||||
|
@ -98,6 +102,10 @@ export default class {
|
|||
// If content is already loaded this should resolve.
|
||||
if (this.getContentByDirName(dir)) continue;
|
||||
|
||||
try {
|
||||
await FileUtils.directoryExists(path.join(this.contentPath, dir));
|
||||
} catch (err) { continue; }
|
||||
|
||||
try {
|
||||
// Load if not
|
||||
await this.preloadContent(dir);
|
||||
|
@ -168,37 +176,34 @@ export default class {
|
|||
const readConfig = await this.readConfig(contentPath);
|
||||
const mainPath = path.join(contentPath, readConfig.main);
|
||||
|
||||
readConfig.defaultConfig = readConfig.defaultConfig || [];
|
||||
|
||||
const userConfig = {
|
||||
enabled: false,
|
||||
config: readConfig.defaultConfig
|
||||
config: new SettingsSet({
|
||||
settings: readConfig.defaultConfig,
|
||||
schemes: readConfig.configSchemes
|
||||
})
|
||||
};
|
||||
|
||||
for (let category of userConfig.config.settings) {
|
||||
for (let setting of category.settings) {
|
||||
setting.setContentPath(contentPath);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const readUserConfig = await this.readUserConfig(contentPath);
|
||||
userConfig.enabled = readUserConfig.enabled || false;
|
||||
for (let category of userConfig.config) {
|
||||
const newCategory = readUserConfig.config.find(c => c.category === category.category);
|
||||
|
||||
for (let setting of category.settings) {
|
||||
setting.path = contentPath;
|
||||
|
||||
if (!newCategory) continue;
|
||||
const newSetting = newCategory.settings.find(s => s.id === setting.id);
|
||||
if (!newSetting) continue;
|
||||
|
||||
setting.value = newSetting.value;
|
||||
}
|
||||
}
|
||||
userConfig.config.merge({ settings: readUserConfig.config });
|
||||
userConfig.config.setSaved();
|
||||
userConfig.css = readUserConfig.css || null;
|
||||
} catch (err) { /*We don't care if this fails it either means that user config doesn't exist or there's something wrong with it so we revert to default config*/
|
||||
|
||||
console.info(`Failed reading config for ${this.contentType} ${readConfig.info.name} in ${dirName}`);
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
const configs = {
|
||||
defaultConfig: readConfig.defaultConfig,
|
||||
schemes: readConfig.configSchemes,
|
||||
schemes: userConfig.schemes,
|
||||
userConfig
|
||||
};
|
||||
|
||||
|
|
|
@ -42,6 +42,10 @@ export default class Plugin {
|
|||
this.hasSettings = this.config && this.config.length > 0;
|
||||
this.start = this.start.bind(this);
|
||||
this.stop = this.stop.bind(this);
|
||||
|
||||
this.settings.on('setting-updated', event => this.events.emit('setting-updated', event));
|
||||
this.settings.on('settings-updated', event => this.events.emit('settings-updated', event));
|
||||
this.settings.on('settings-updated', event => this.saveConfiguration());
|
||||
}
|
||||
|
||||
get type() { return 'plugin' }
|
||||
|
@ -61,7 +65,8 @@ export default class Plugin {
|
|||
get pluginPath() { return this.paths.contentPath }
|
||||
get dirName() { return this.paths.dirName }
|
||||
get enabled() { return this.userConfig.enabled }
|
||||
get config() { return this.userConfig.config || [] }
|
||||
get settings() { return this.userConfig.config }
|
||||
get config() { return this.settings.settings }
|
||||
get pluginConfig() { return this.config }
|
||||
get exports() { return this._exports ? this._exports : (this._exports = this.getExports()) }
|
||||
get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new PluginEvents(this)) }
|
||||
|
@ -81,45 +86,22 @@ export default class Plugin {
|
|||
}
|
||||
|
||||
async saveSettings(newSettings) {
|
||||
const updatedSettings = [];
|
||||
const updatedSettings = this.settings.merge(newSettings);
|
||||
|
||||
for (let newCategory of newSettings) {
|
||||
const category = this.config.find(c => c.category === newCategory.category);
|
||||
for (let newSetting of newCategory.settings) {
|
||||
const setting = category.settings.find(s => s.id === newSetting.id);
|
||||
if (Utils.compare(setting.value, newSetting.value)) continue;
|
||||
|
||||
const old_value = setting.value;
|
||||
setting.value = newSetting.value;
|
||||
updatedSettings.push({ category_id: category.category, setting_id: setting.id, value: setting.value, old_value });
|
||||
this.settingUpdated(category.category, setting.id, setting.value, old_value);
|
||||
}
|
||||
}
|
||||
|
||||
this.saveConfiguration();
|
||||
return this.settingsUpdated(updatedSettings);
|
||||
}
|
||||
|
||||
settingUpdated(category_id, setting_id, value, old_value) {
|
||||
const event = new SettingUpdatedEvent({ category_id, setting_id, value, old_value });
|
||||
this.events.emit('setting-updated', event);
|
||||
this.events.emit(`setting-updated_{$category_id}_${setting_id}`, event);
|
||||
}
|
||||
|
||||
settingsUpdated(updatedSettings) {
|
||||
const event = new SettingsUpdatedEvent({ settings: updatedSettings.map(s => new SettingUpdatedEvent(s)) });
|
||||
this.events.emit('settings-updated', event);
|
||||
await this.saveConfiguration();
|
||||
return updatedSettings;
|
||||
}
|
||||
|
||||
async saveConfiguration() {
|
||||
window.testConfig = new ContentConfig(this.config);
|
||||
try {
|
||||
const config = new ContentConfig(this.config).strip();
|
||||
await FileUtils.writeFile(`${this.pluginPath}/user.config.json`, JSON.stringify({
|
||||
enabled: this.enabled,
|
||||
config
|
||||
config: this.settings.strip().settings
|
||||
}));
|
||||
|
||||
this.settings.setSaved();
|
||||
} catch (err) {
|
||||
console.error(`Plugin ${this.id} configuration failed to save`, err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import Globals from './globals';
|
|||
import CssEditor from './csseditor';
|
||||
import Events from './events';
|
||||
import { Utils, FileUtils, ClientLogger as Logger } from 'common';
|
||||
import { SettingUpdatedEvent } from 'structs';
|
||||
import { SettingsSet, SettingUpdatedEvent } from 'structs';
|
||||
import path from 'path';
|
||||
|
||||
export default class {
|
||||
|
@ -25,24 +25,22 @@ export default class {
|
|||
const user_config = await FileUtils.readJsonFromFile(settingsPath);
|
||||
const { settings, scss, css_editor_bounds } = user_config;
|
||||
|
||||
this.settings = defaultSettings;
|
||||
|
||||
for (let newSet of settings) {
|
||||
let set = this.settings.find(s => s.id === newSet.id);
|
||||
if (!set) continue;
|
||||
|
||||
for (let newCategory of newSet.settings) {
|
||||
let category = set.settings.find(c => c.category === newCategory.category);
|
||||
if (!category) continue;
|
||||
|
||||
for (let newSetting of newCategory.settings) {
|
||||
let setting = category.settings.find(s => s.id === newSetting.id);
|
||||
if (!setting) continue;
|
||||
|
||||
setting.value = newSetting.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.settings = defaultSettings.map(set => {
|
||||
const newSet = new SettingsSet(set);
|
||||
newSet.merge(settings.find(s => s.id === newSet.id));
|
||||
newSet.setSaved();
|
||||
newSet.on('setting-updated', event => {
|
||||
const { category, setting, value, old_value } = event;
|
||||
Logger.log('Settings', `${newSet.id}/${category.id}/${setting.id} was changed from ${old_value} to ${value}`);
|
||||
Events.emit('setting-updated', event);
|
||||
Events.emit(`setting-updated-${newSet.id}_${category.id}_${setting.id}`, event);
|
||||
});
|
||||
newSet.on('settings-updated', async (event) => {
|
||||
await this.saveSettings();
|
||||
Events.emit('settings-updated', event);
|
||||
});
|
||||
return newSet;
|
||||
});
|
||||
|
||||
CssEditor.updateScss(scss, true);
|
||||
CssEditor.editor_bounds = css_editor_bounds || {};
|
||||
|
@ -59,22 +57,7 @@ export default class {
|
|||
|
||||
const settingsPath = path.resolve(this.dataPath, 'user.settings.json');
|
||||
await FileUtils.writeJsonToFile(settingsPath, {
|
||||
settings: this.getSettings.map(set => {
|
||||
return {
|
||||
id: set.id,
|
||||
settings: set.settings.map(category => {
|
||||
return {
|
||||
category: category.category,
|
||||
settings: category.settings.map(setting => {
|
||||
return {
|
||||
id: setting.id,
|
||||
value: setting.value
|
||||
};
|
||||
})
|
||||
};
|
||||
})
|
||||
};
|
||||
}),
|
||||
settings: this.getSettings.map(set => set.strip()),
|
||||
scss: CssEditor.scss,
|
||||
css_editor_bounds: {
|
||||
width: CssEditor.editor_bounds.width,
|
||||
|
@ -83,10 +66,14 @@ export default class {
|
|||
y: CssEditor.editor_bounds.y
|
||||
}
|
||||
});
|
||||
|
||||
for (let set of this.getSettings) {
|
||||
set.setSaved();
|
||||
}
|
||||
} catch (err) {
|
||||
// There was an error loading settings
|
||||
// This probably means that the user doesn't have any settings yet
|
||||
// There was an error saving settings
|
||||
Logger.err('Settings', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,76 +81,37 @@ export default class {
|
|||
return this.getSettings.find(s => s.id === set_id);
|
||||
}
|
||||
|
||||
static get core() { return this.getSet('core') }
|
||||
static get ui() { return this.getSet('ui') }
|
||||
static get emotes() { return this.getSet('emotes') }
|
||||
static get security() { return this.getSet('security') }
|
||||
|
||||
static getCategory(set_id, category_id) {
|
||||
const set = this.getSet(set_id);
|
||||
if (!set) return;
|
||||
|
||||
return set.settings.find(c => c.category === category_id);
|
||||
return set ? set.getCategory(category_id) : undefined;
|
||||
}
|
||||
|
||||
static getSetting(set_id, category_id, setting_id) {
|
||||
const category = this.getCategory(set_id, category_id);
|
||||
if (!category) return;
|
||||
|
||||
return category.settings.find(s => s.id === setting_id);
|
||||
const set = this.getSet(set_id);
|
||||
return set ? set.getSetting(category_id, setting_id) : undefined;
|
||||
}
|
||||
|
||||
static get(set_id, category_id, setting_id) {
|
||||
const setting = this.getSetting(set_id, category_id, setting_id);
|
||||
return setting ? setting.value : undefined;
|
||||
const set = this.getSet(set_id);
|
||||
return set ? set.get(category_id, setting_id) : undefined;
|
||||
}
|
||||
|
||||
static mergeSettings(set_id, newSettings, settingsUpdated) {
|
||||
static async mergeSettings(set_id, newSettings) {
|
||||
const set = this.getSet(set_id);
|
||||
if (!set) return;
|
||||
const updatedSettings = [];
|
||||
|
||||
for (let newCategory of newSettings) {
|
||||
let category = set.settings.find(c => c.category === newCategory.category);
|
||||
|
||||
for (let newSetting of newCategory.settings) {
|
||||
let setting = category.settings.find(s => s.id === newSetting.id);
|
||||
if (Utils.compare(setting.value, newSetting.value)) continue;
|
||||
|
||||
let old_value = setting.value;
|
||||
setting.value = newSetting.value;
|
||||
updatedSettings.push({ set_id: set.id, category_id: category.category, setting_id: setting.id, value: setting.value, old_value });
|
||||
this.settingUpdated(set.id, category.category, setting.id, setting.value, old_value);
|
||||
}
|
||||
}
|
||||
|
||||
this.saveSettings();
|
||||
return settingsUpdated ? settingsUpdated(updatedSettings) : updatedSettings;
|
||||
return await set.merge(newSettings);
|
||||
}
|
||||
|
||||
static setSetting(set_id, category_id, setting_id, value) {
|
||||
for (let set of this.getSettings) {
|
||||
if (set.id !== set_id) continue;
|
||||
|
||||
for (let category of set.settings) {
|
||||
if (category.category !== category_id) continue;
|
||||
|
||||
for (let setting of category.settings) {
|
||||
if (setting.id !== setting_id) continue;
|
||||
if (Utils.compare(setting.value, value)) return true;
|
||||
|
||||
let old_value = setting.value;
|
||||
setting.value = value;
|
||||
this.settingUpdated(set_id, category_id, setting_id, value, old_value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static settingUpdated(set_id, category_id, setting_id, value, old_value) {
|
||||
Logger.log('Settings', `${set_id}/${category_id}/${setting_id} was changed from ${old_value} to ${value}`);
|
||||
|
||||
const event = new SettingUpdatedEvent({ set_id, category_id, setting_id, value, old_value });
|
||||
Events.emit('setting-updated', event);
|
||||
Events.emit(`setting-updated-${set_id}_{$category_id}_${setting_id}`, event);
|
||||
const setting = this.getSetting(set_id, category_id, setting_id);
|
||||
if (!setting) throw {message: `Tried to set ${set_id}/${category_id}/${setting_id}, which doesn't exist`};
|
||||
setting.value = value;
|
||||
}
|
||||
|
||||
static get getSettings() {
|
||||
|
|
|
@ -42,6 +42,10 @@ export default class Theme {
|
|||
this.saveSettings = this.saveSettings.bind(this);
|
||||
this.enable = this.enable.bind(this);
|
||||
this.disable = this.disable.bind(this);
|
||||
|
||||
this.settings.on('setting-updated', event => this.events.emit('setting-updated', event));
|
||||
this.settings.on('settings-updated', event => this.events.emit('settings-updated', event));
|
||||
this.settings.on('settings-updated', event => this.saveConfiguration());
|
||||
}
|
||||
|
||||
get configs() { return this.__themeInternals.configs }
|
||||
|
@ -61,7 +65,8 @@ export default class Theme {
|
|||
get themePath() { return this.paths.contentPath }
|
||||
get dirName() { return this.paths.dirName }
|
||||
get enabled() { return this.userConfig.enabled }
|
||||
get config() { return this.userConfig.config || [] }
|
||||
get settings() { return this.userConfig.config }
|
||||
get config() { return this.settings.settings }
|
||||
get themeConfig() { return this.config }
|
||||
get css() { return this.userConfig.css }
|
||||
get events() { return this.EventEmitter ? this.EventEmitter : (this.EventEmitter = new ThemeEvents(this)) }
|
||||
|
@ -71,47 +76,24 @@ export default class Theme {
|
|||
}
|
||||
|
||||
async saveSettings(newSettings) {
|
||||
const updatedSettings = [];
|
||||
|
||||
for (let newCategory of newSettings) {
|
||||
const category = this.config.find(c => c.category === newCategory.category);
|
||||
for (let newSetting of newCategory.settings) {
|
||||
const setting = category.settings.find(s => s.id === newSetting.id);
|
||||
if (Utils.compare(setting.value, newSetting.value)) continue;
|
||||
|
||||
const old_value = setting.value;
|
||||
setting.value = newSetting.value;
|
||||
updatedSettings.push({ category_id: category.category, setting_id: setting.id, value: setting.value, old_value });
|
||||
this.settingUpdated(category.category, setting.id, setting.value, old_value);
|
||||
}
|
||||
}
|
||||
const updatedSettings = this.settings.merge(newSettings);
|
||||
|
||||
// As the theme's configuration has changed it needs recompiling
|
||||
// When the compiled CSS has been save it will also save the configuration
|
||||
// When the compiled CSS has been saved it will also save the configuration
|
||||
await this.recompile();
|
||||
|
||||
return this.settingsUpdated(updatedSettings);
|
||||
}
|
||||
|
||||
settingUpdated(category_id, setting_id, value, old_value) {
|
||||
const event = new SettingUpdatedEvent({ category_id, setting_id, value, old_value });
|
||||
this.events.emit('setting-updated', event);
|
||||
this.events.emit(`setting-updated_{$category_id}_${setting_id}`, event);
|
||||
}
|
||||
|
||||
settingsUpdated(updatedSettings) {
|
||||
const event = new SettingsUpdatedEvent({ settings: updatedSettings.map(s => new SettingUpdatedEvent(s)) });
|
||||
this.events.emit('settings-updated', event);
|
||||
}
|
||||
|
||||
async saveConfiguration() {
|
||||
try {
|
||||
const config = new ContentConfig(this.config).strip();
|
||||
await FileUtils.writeFile(`${this.themePath}/user.config.json`, JSON.stringify({
|
||||
enabled: this.enabled,
|
||||
config,
|
||||
config: this.settings.strip().settings,
|
||||
css: this.css
|
||||
}));
|
||||
|
||||
this.settings.setSaved();
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
|
|
@ -101,67 +101,9 @@ export default class ThemeManager extends ContentManager {
|
|||
static async parseSetting(setting) {
|
||||
const { type, id, value } = setting;
|
||||
const name = id.replace(/[^a-zA-Z0-9-]/g, '-').replace(/--/g, '-');
|
||||
const scss = await setting.toSCSS();
|
||||
|
||||
if (type === 'colour' || type === 'color') {
|
||||
return [name, value];
|
||||
}
|
||||
|
||||
if (type === 'array') {
|
||||
const items = JSON.parse(JSON.stringify(value)) || [];
|
||||
const settings_json = JSON.stringify(setting.settings);
|
||||
|
||||
for (let item of items) {
|
||||
const settings = JSON.parse(settings_json);
|
||||
|
||||
for (let category of settings) {
|
||||
const newCategory = item.settings.find(c => c.category === category.category);
|
||||
for (let setting of category.settings) {
|
||||
const newSetting = newCategory.settings.find(s => s.id === setting.id);
|
||||
setting.value = setting.old_value = newSetting.value;
|
||||
setting.changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
item.settings = settings;
|
||||
}
|
||||
|
||||
console.log('items', items);
|
||||
|
||||
// Final comma ensures the variable is a list
|
||||
const maps = [];
|
||||
for (let item of items)
|
||||
maps.push(await this.getConfigAsSCSSMap(item.settings));
|
||||
return [name, maps.length ? maps.join(', ') + ',' : '()'];
|
||||
}
|
||||
|
||||
if (type === 'file' && Array.isArray(value)) {
|
||||
if (!value || !value.length) return [name, '()'];
|
||||
|
||||
const files = [];
|
||||
for (let filepath of value) {
|
||||
const buffer = await FileUtils.readFileBuffer(path.resolve(setting.path, filepath));
|
||||
const type = await FileUtils.getFileType(buffer);
|
||||
files.push(`(data: ${this.toSCSSString(buffer.toString('base64'))}, type: ${this.toSCSSString(type.mime)}, url: ${this.toSCSSString(await FileUtils.toDataURI(buffer, type.mime))})`);
|
||||
}
|
||||
|
||||
return [name, files.length ? files.join(', ') : '()'];
|
||||
}
|
||||
|
||||
if (type === 'slider') {
|
||||
return [name, value * setting.multi || 1];
|
||||
}
|
||||
|
||||
if (type === 'dropdown' || type === 'radio') {
|
||||
return [name, setting.options.find(opt => opt.id === value).value];
|
||||
}
|
||||
|
||||
if (typeof value === 'boolean' || typeof value === 'number') {
|
||||
return [name, value];
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return [name, this.toSCSSString(value)];
|
||||
}
|
||||
if (scss) return [name, scss];
|
||||
}
|
||||
|
||||
static toSCSSString(value) {
|
||||
|
|
|
@ -13,15 +13,27 @@ import Event from './event';
|
|||
export default class SettingUpdatedEvent extends Event {
|
||||
|
||||
get set() {
|
||||
return this.args.set_id;
|
||||
return this.args.set;
|
||||
}
|
||||
|
||||
get set_id() {
|
||||
return this.args.set.id;
|
||||
}
|
||||
|
||||
get category() {
|
||||
return this.args.category_id;
|
||||
return this.args.category;
|
||||
}
|
||||
|
||||
get category_id() {
|
||||
return this.args.category.id;
|
||||
}
|
||||
|
||||
get setting() {
|
||||
return this.args.setting_id;
|
||||
return this.args.setting;
|
||||
}
|
||||
|
||||
get setting_id() {
|
||||
return this.args.setting.id;
|
||||
}
|
||||
|
||||
get value() {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bd-flex bd-flex-col bd-pluginsView">
|
||||
<div class="bd-flex bd-flex-col bd-pluginsview">
|
||||
<div v-if="local" class="bd-flex bd-flex-grow bd-flex-col bd-plugins-container bd-local-plugins">
|
||||
<PluginCard v-for="plugin in localPlugins" :plugin="plugin" :key="plugin.id" :togglePlugin="() => togglePlugin(plugin)" :reloadPlugin="() => reloadPlugin(plugin)" :deletePlugin="e => deletePlugin(plugin, e.shiftKey)" :showSettings="() => showSettings(plugin)" />
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<div class="bd-settings-schemes" v-if="schemes && schemes.length">
|
||||
<div class="bd-settings-schemes-container">
|
||||
<template v-for="scheme in schemes">
|
||||
<div class="bd-settings-scheme" :class="{'bd-active': checkSchemeActive(scheme)}" @click="() => setActiveScheme(scheme)">
|
||||
<div class="bd-settings-scheme" :class="{'bd-active': scheme.isActive(settings)}" @click="() => scheme.applyTo(settings)">
|
||||
<div class="bd-settings-scheme-icon" :style="{'background-image': `url("${scheme.icon_url}")`}"></div>
|
||||
<div class="bd-settings-scheme-name" v-if="scheme.name">{{ scheme.name }}</div>
|
||||
<div class="bd-settings-scheme-hint" v-if="scheme.hint">{{ scheme.hint }}</div>
|
||||
|
@ -23,7 +23,7 @@
|
|||
</div>
|
||||
|
||||
<div class="bd-settings-categories">
|
||||
<template v-for="category in settings">
|
||||
<template v-for="category in settings.categories">
|
||||
<div class="bd-settings-category">
|
||||
<div v-if="category.category === 'default' || !category.type">
|
||||
<Setting v-for="setting in category.settings" :key="setting.id" :setting="setting" :change="v => settingChange(category, setting, v)" />
|
||||
|
@ -53,47 +53,15 @@
|
|||
import Drawer from '../common/Drawer.vue';
|
||||
|
||||
export default {
|
||||
props: ['settings', 'schemes', 'change'],
|
||||
props: ['settings', 'schemes'],
|
||||
components: {
|
||||
Setting,
|
||||
Drawer
|
||||
},
|
||||
methods: {
|
||||
checkSchemeActive(scheme) {
|
||||
for (let schemeCategory of scheme.settings) {
|
||||
const category = this.settings.find(c => c.category === schemeCategory.category);
|
||||
if (!category) return false;
|
||||
|
||||
for (let schemeSetting of schemeCategory.settings) {
|
||||
const setting = category.settings.find(s => s.id === schemeSetting.id);
|
||||
if (!setting || !Utils.compare(setting.value, schemeSetting.value)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
setActiveScheme(scheme) {
|
||||
for (let schemeCategory of scheme.settings) {
|
||||
const category = this.settings.find(c => c.category === schemeCategory.category);
|
||||
if (!category) {
|
||||
console.err(`Category ${schemeCategory.category} does not exist`);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let schemeSetting of schemeCategory.settings) {
|
||||
const setting = category.settings.find(s => s.id === schemeSetting.id);
|
||||
if (!setting) {
|
||||
console.err(`Setting ${schemeCategory.category}/${schemeSetting.id} does not exist`);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.change(category.category, setting.id, schemeSetting.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
settingChange(category, setting, value) {
|
||||
if (setting.disabled) return;
|
||||
this.change(category.category, setting.id, value);
|
||||
setting.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bd-flex bd-flex-col bd-themesView">
|
||||
<div class="bd-flex bd-flex-col bd-themesview">
|
||||
<div v-if="local" class="bd-flex bd-flex-grow bd-flex-col bd-themes-container bd-local-themes">
|
||||
<ThemeCard v-for="theme in localThemes" :theme="theme" :key="theme.id" :toggleTheme="() => toggleTheme(theme)" :reloadTheme="e => reloadTheme(theme, e.shiftKey)" :showSettings="() => showSettings(theme)" :deleteTheme="e => deleteTheme(theme, e.shiftKey)" />
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<template>
|
||||
<div class="bd-settings-modal" :class="{'bd-edited': changed}">
|
||||
<Modal :headerText="modal.headertext" :close="modal.close" :class="{'bd-modal-out': modal.closing}">
|
||||
<SettingsPanel :settings="configCache" :schemes="modal.schemes" :change="settingChange" slot="body" class="bd-settings-modal-body" />
|
||||
<SettingsPanel :settings="settings" :schemes="modal.schemes" slot="body" class="bd-settings-modal-body" />
|
||||
<div slot="footer" class="bd-footer-alert" :class="{'bd-active': changed, 'bd-warn': warnclose}" :style="{pointerEvents: changed ? 'all' : 'none'}">
|
||||
<div class="bd-footer-alert-text">Unsaved changes</div>
|
||||
<div class="bd-button bd-reset-button bd-tp" :class="{'bd-disabled': saving}" @click="resetSettings">Reset</div>
|
||||
|
@ -34,9 +34,8 @@
|
|||
props: ['modal'],
|
||||
data() {
|
||||
return {
|
||||
changed: false,
|
||||
warnclose: false,
|
||||
configCache: [],
|
||||
settings: null,
|
||||
closing: false,
|
||||
saving: false
|
||||
}
|
||||
|
@ -45,41 +44,32 @@
|
|||
Modal,
|
||||
SettingsPanel
|
||||
},
|
||||
computed: {
|
||||
changed() {
|
||||
return this.settings.categories.find(category => category.changed);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkForChanges() {
|
||||
let changed = false;
|
||||
for (let category of this.configCache) {
|
||||
const cat = this.modal.settings.find(c => c.category === category.category);
|
||||
for (let setting of category.settings) {
|
||||
if (!Utils.compare(cat.settings.find(s => s.id === setting.id).value, setting.value)) {
|
||||
changed = true;
|
||||
Vue.set(setting, 'changed', true);
|
||||
} else {
|
||||
Vue.set(setting, 'changed', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
},
|
||||
settingChange(category_id, setting_id, value) {
|
||||
const category = this.configCache.find(c => c.category === category_id);
|
||||
if (!category) return;
|
||||
|
||||
const setting = category.settings.find(s => s.id === setting_id);
|
||||
if (!setting) return;
|
||||
|
||||
setting.value = value;
|
||||
|
||||
this.changed = this.checkForChanges();
|
||||
this.$forceUpdate();
|
||||
},
|
||||
// settingChange(category_id, setting_id, value) {
|
||||
// console.log(`Setting ${category_id}/${setting_id} to ${value}`, this.configCache);
|
||||
//
|
||||
// const category = this.configCache.find(c => c.category === category_id);
|
||||
// if (!category) return;
|
||||
//
|
||||
// const setting = category.settings.find(s => s.id === setting_id);
|
||||
// if (!setting) return;
|
||||
//
|
||||
// setting.value = value;
|
||||
//
|
||||
// // this.changed = this.checkForChanges();
|
||||
// this.$forceUpdate();
|
||||
// },
|
||||
async saveSettings() {
|
||||
if (this.saving) return;
|
||||
this.saving = true;
|
||||
try {
|
||||
await this.modal.saveSettings(this.configCache);
|
||||
this.configCache = JSON.parse(JSON.stringify(this.modal.settings));
|
||||
this.changed = false;
|
||||
if (this.modal.saveSettings) await this.modal.saveSettings(this.settings);
|
||||
// this.cloneSettings();
|
||||
} catch (err) {
|
||||
// TODO Display error that settings failed to save
|
||||
console.log(err);
|
||||
|
@ -88,9 +78,14 @@
|
|||
},
|
||||
resetSettings() {
|
||||
if (this.saving) return;
|
||||
this.configCache = JSON.parse(JSON.stringify(this.modal.settings));
|
||||
this.changed = false;
|
||||
// this.configCache = JSON.parse(JSON.stringify(this.modal.settings));
|
||||
// this.changed = false;
|
||||
this.cloneSettings();
|
||||
this.$forceUpdate();
|
||||
},
|
||||
cloneSettings() {
|
||||
console.log('Cloning settings');
|
||||
this.settings = this.modal.dont_clone ? this.modal.settings : this.modal.settings.clone();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -100,11 +95,19 @@
|
|||
setTimeout(() => this.warnclose = false, 400);
|
||||
throw {message: 'Settings have been changed'};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.modal.settings.on('settings-updated', this.cloneSettings);
|
||||
},
|
||||
destroyed() {
|
||||
this.modal.settings.off('settings-updated', this.cloneSettings);
|
||||
},
|
||||
beforeMount() {
|
||||
this.configCache = JSON.parse(JSON.stringify(this.modal.settings));
|
||||
this.changed = this.checkForChanges();
|
||||
// this.configCache = JSON.parse(JSON.stringify(this.modal.settings));
|
||||
// this.changed = this.checkForChanges();
|
||||
console.log(this);
|
||||
this.cloneSettings();
|
||||
// this.settings = this.modal.dont_clone ? this.modal.settings : this.modal.settings.clone();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
<div class="bd-form-settingsarray" :class="{'bd-form-settingsarray-inline': setting.inline}">
|
||||
<div class="bd-title">
|
||||
<h3>{{ setting.text }}</h3>
|
||||
<button class="bd-button bd-button-primary" :class="{'bd-disabled': setting.disabled || setting.max && items.length >= setting.max}" @click="() => addItem(!setting.inline)">Add</button>
|
||||
<button class="bd-button bd-button-primary" :class="{'bd-disabled': setting.disabled || setting.max && setting.items.length >= setting.max}" @click="() => addItem(!setting.inline)">Add</button>
|
||||
</div>
|
||||
<div class="bd-hint">{{ setting.hint }}</div>
|
||||
<div class="bd-settingsarray-items">
|
||||
<div class="bd-settingsarray-item" v-for="(item, index) in items">
|
||||
<div class="bd-settingsarray-item" v-for="(item, index) in setting.items">
|
||||
<div class="bd-settingsarray-item-marker">{{ index + 1 }}</div>
|
||||
|
||||
<SettingsPanel class="bd-settingsarray-item-contents" v-if="setting.inline" :settings="item.settings" :change="(c, s, v) => changeInItem(item, c, s, v)" />
|
||||
|
@ -28,7 +28,7 @@
|
|||
|
||||
<div class="bd-settingsarray-item-controls">
|
||||
<span class="bd-settingsarray-open" v-if="typeof setting.allow_external !== 'undefined' ? setting.allow_external || !setting.inline : true" @click="() => showModal(item, index)"><MiOpenInNew v-if="setting.inline" /><MiSettings v-else /></span>
|
||||
<span class="bd-settingsarray-remove" :class="{'bd-disabled': setting.disabled || setting.min && items.length <= setting.min}" @click="() => removeItem(item)"><MiMinus /></span>
|
||||
<span class="bd-settingsarray-remove" :class="{'bd-disabled': setting.disabled || setting.min && setting.items.length <= setting.min}" @click="() => removeItem(item)"><MiMinus /></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -47,29 +47,26 @@
|
|||
components: {
|
||||
MiSettings, MiOpenInNew, MiMinus
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
items: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
setting(value) {
|
||||
// this.setting was changed
|
||||
this.reloadSettings();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addItem(openModal) {
|
||||
if (this.setting.disabled || this.setting.max && this.items.length >= this.setting.max) return;
|
||||
const item = { settings: this.getItemSettings({}) };
|
||||
if (openModal) this.showModal(item, this.items.length);
|
||||
this.items.push(item);
|
||||
this.update();
|
||||
if (this.setting.disabled || this.setting.max && this.setting.items.length >= this.setting.max) return;
|
||||
// const item = { settings: this.getItemSettings({}) };
|
||||
const item = this.setting.addItem();
|
||||
if (openModal) this.showModal(item, this.setting.items.length);
|
||||
// this.update();
|
||||
// this.$forceUpdate();
|
||||
},
|
||||
removeItem(item) {
|
||||
if (this.setting.disabled || this.setting.min && this.items.length <= this.setting.min) return;
|
||||
this.items = this.items.filter(i => i !== item);
|
||||
this.update();
|
||||
if (this.setting.disabled || this.setting.min && this.setting.items.length <= this.setting.min) return;
|
||||
// this.setting.items = this.setting.items.filter(i => i !== item);
|
||||
this.setting.removeItem(item);
|
||||
// this.update();
|
||||
this.$forceUpdate();
|
||||
},
|
||||
changeInItem(item, category_id, setting_id, value) {
|
||||
console.log('Setting', item, category_id, setting_id, 'to', value);
|
||||
|
@ -82,50 +79,15 @@
|
|||
|
||||
setting.value = value;
|
||||
setting.changed = !Utils.compare(setting.value, setting.old_value);
|
||||
this.update();
|
||||
},
|
||||
update() {
|
||||
this.change(this.items.map(item => ({
|
||||
settings: item.settings ? item.settings.map(category => ({
|
||||
category: category.category,
|
||||
settings: category.settings.map(setting => ({
|
||||
id: setting.id,
|
||||
value: setting.value
|
||||
}))
|
||||
})) : []
|
||||
})));
|
||||
// this.update();
|
||||
},
|
||||
showModal(item, index) {
|
||||
Modals.settings(this.setting.headertext ? this.setting.headertext.replace(/%n/, index + 1) : this.setting.text + ` #${index + 1}`, item.settings, this.setting.schemes, () => this.update());
|
||||
},
|
||||
getItemSettings(item) {
|
||||
const settings = JSON.parse(JSON.stringify(this.setting.settings));
|
||||
const newSettings = item.settings || [];
|
||||
|
||||
for (let newCategory of newSettings) {
|
||||
const category = settings.find(c => c.category === newCategory.category);
|
||||
if (!category) continue;
|
||||
for (let newSetting of newCategory.settings) {
|
||||
const setting = category.settings.find(s => s.id === newSetting.id);
|
||||
if (!setting) continue;
|
||||
setting.value = setting.old_value = newSetting.value;
|
||||
setting.changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
},
|
||||
reloadSettings() {
|
||||
this.items = JSON.parse(JSON.stringify(this.setting.value)) || [];
|
||||
this.items = this.items.map(item => ({ settings: this.getItemSettings(item) }));
|
||||
Modals.settings(item, this.setting.headertext ? this.setting.headertext.replace(/%n/, index + 1) : this.setting.text + ` #${index + 1}`);
|
||||
}
|
||||
},
|
||||
beforeCreate() {
|
||||
// https://vuejs.org/v2/guide/components.html#Circular-References-Between-Components
|
||||
this.$options.components.SettingsPanel = SettingsPanel;
|
||||
},
|
||||
beforeMount() {
|
||||
this.reloadSettings();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<div class="bd-form-dropdown">
|
||||
<div class="bd-title">
|
||||
<h3 v-if="setting.text">{{setting.text}}</h3>
|
||||
<Dropdown v-if="!setting.fullwidth" :options="setting.options" :selected="setting.value" :disabled="setting.disabled" :change="change" />
|
||||
<Dropdown v-if="!setting.fullwidth" :options="setting.options" :selected="setting.args.value" :disabled="setting.disabled" :change="change" />
|
||||
</div>
|
||||
<div class="bd-hint">{{setting.hint}}</div>
|
||||
<Dropdown v-if="setting.fullwidth" :options="setting.options" :selected="setting.value" :disabled="setting.disabled" :change="change" />
|
||||
|
@ -25,6 +25,25 @@
|
|||
props: ['setting', 'change'],
|
||||
components: {
|
||||
Dropdown
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
selectOption(option) {
|
||||
this.active = false;
|
||||
this.change(option.id);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener("click", e => {
|
||||
let options = this.$refs.options;
|
||||
if (options && !options.contains(e.target) && options !== e.target) {
|
||||
this.active = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -123,27 +123,11 @@ export default class {
|
|||
}
|
||||
}
|
||||
|
||||
static settings(headertext, settings, schemes, settingsUpdated, settingUpdated, saveSettings) {
|
||||
static settings(settings, headertext, saveSettings) {
|
||||
return this.add({
|
||||
headertext, settings, schemes,
|
||||
headertext, settings, schemes: settings.schemes,
|
||||
saveSettings: saveSettings ? saveSettings : newSettings => {
|
||||
const updatedSettings = [];
|
||||
|
||||
for (let newCategory of newSettings) {
|
||||
let category = settings.find(c => c.category === newCategory.category);
|
||||
|
||||
for (let newSetting of newCategory.settings) {
|
||||
let setting = category.settings.find(s => s.id === newSetting.id);
|
||||
if (Utils.compare(setting.value, newSetting.value)) continue;
|
||||
|
||||
let old_value = setting.value;
|
||||
setting.value = newSetting.value;
|
||||
updatedSettings.push({ category_id: category.category, setting_id: setting.id, value: setting.value, old_value });
|
||||
if (settingUpdated) settingUpdated(category.category, setting.id, setting.value, old_value);
|
||||
}
|
||||
}
|
||||
|
||||
return settingsUpdated ? settingsUpdated(updatedSettings) : updatedSettings;
|
||||
return settings.merge(newSettings);
|
||||
}
|
||||
}, SettingsModal);
|
||||
}
|
||||
|
@ -151,11 +135,12 @@ export default class {
|
|||
static internalSettings(set_id) {
|
||||
const set = Settings.getSet(set_id);
|
||||
if (!set) return;
|
||||
return this.settings(set.headertext, set.settings, set.schemes, null, null, newSettings => Settings.mergeSettings(set.id, newSettings));
|
||||
// return this.settings(set, set.headertext, newSettings => Settings.mergeSettings(set.id, newSettings));
|
||||
return this.settings(set, set.headertext);
|
||||
}
|
||||
|
||||
static contentSettings(content) {
|
||||
return this.settings(content.name + ' Settings', content.config, content.configSchemes, null, null, content.saveSettings.bind(content));
|
||||
return this.settings(content.settings, content.name + ' Settings');
|
||||
}
|
||||
|
||||
static get stack() {
|
||||
|
|
Loading…
Reference in New Issue