Add settings arrays

This commit is contained in:
Samuel Elliott 2018-02-19 18:19:52 +00:00
parent 847d88a628
commit fae6fc8511
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
7 changed files with 303 additions and 2 deletions

View File

@ -0,0 +1,77 @@
.bd-form-settingsarray {
.bd-button.bd-button-primary {
padding: 3px 8px;
border-radius: 3px;
font-size: 12px;
font-weight: 400;
}
.bd-settingsarray-items {
margin-top: 15px;
.bd-settingsarray-item {
display: flex;
margin-top: 10px;
.bd-settingsarray-item-marker {
flex: 0 0 auto;
min-width: 15px;
margin-right: 5px;
color: #aaa;
font-size: 15px;
}
.bd-settingsarray-item-contents {
flex: 1 1;
}
.bd-settings-panel {
.bd-settings-categories:last-child .bd-form-item:last-child .bd-form-divider {
margin-bottom: 0;
}
+ .bd-settingsarray-item-controls {
flex-basis: 0%;
}
}
.bd-settingsarray-item-hint {
color: #aaa;
font-size: 15px;
font-style: italic;
word-wrap: break-word;
max-width: 385px;
}
.bd-settingsarray-item-controls {
flex: 0 0 auto;
margin-left: 5px;
}
.bd-settingsarray-open,
.bd-settingsarray-remove {
margin-left: 5px;
svg {
width: 16px;
height: 16px;
cursor: pointer;
fill: #ccc;
&:hover {
fill: #fff;
}
}
}
&:last-child .bd-settings-categories:last-child .bd-form-item:last-child .bd-form-divider {
display: none;
}
}
}
&.bd-form-settingsarray-inline .bd-settingsarray-item {
margin-top: 10px;
}
}

View File

@ -5,3 +5,4 @@
@import './radios.scss';
@import './sliders.scss';
@import './switches.scss';
@import './arrays.scss';

View File

@ -5,7 +5,8 @@
.bd-form-radio,
.bd-form-numberinput,
.bd-form-slider,
.bd-setting-switch {
.bd-setting-switch,
.bd-form-settingsarray {
.bd-title {
display: flex;

View File

@ -0,0 +1,129 @@
/**
* BetterDiscord Setting File Component
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
* All rights reserved.
* https://betterdiscord.net
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
<template>
<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>
</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-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)" />
<div class="bd-settingsarray-item-contents" v-else>
<div class="bd-settingsarray-item-hint">
<span v-if="item.settings[0] && item.settings[0].settings[0]">{{ item.settings[0].settings[0].text }}: {{ item.settings[0].settings[0].value }}</span><span v-if="item.settings[0] && item.settings[0].settings[1]">, {{ item.settings[0].settings[1].text }}: {{ item.settings[0].settings[1].value }}</span><span v-if="item.settings[0] && item.settings[0].settings[2] || item.settings[1] && item.settings[1].settings[0]">, ...</span>
</div>
</div>
<div class="bd-settingsarray-item-controls">
<span class="bd-settingsarray-open" @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>
</div>
</div>
</div>
</div>
</template>
<script>
import { shell } from 'electron';
import { Utils, ClientIPC } from 'common';
import { MiSettings, MiOpenInNew, MiMinus } from '../../common';
import { Modals } from 'ui';
import SettingsPanel from '../SettingsPanel.vue';
export default {
props: ['setting', 'change'],
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();
},
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();
},
changeInItem(item, category_id, setting_id, value) {
console.log('Setting', item, category_id, setting_id, 'to', value);
const category = item.settings.find(c => c.category === category_id);
if (!category) return;
const setting = category.settings.find(s => s.id === setting_id);
if (!setting || Utils.compare(setting.value, value)) return;
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
}))
})) : []
})));
},
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);
for (let newSetting of newCategory.settings) {
const setting = category.settings.find(s => s.id === newSetting.id);
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) }));
}
},
beforeCreate() {
// https://vuejs.org/v2/guide/components.html#Circular-References-Between-Components
this.$options.components.SettingsPanel = SettingsPanel;
},
beforeMount() {
this.reloadSettings();
}
}
</script>

View File

@ -18,6 +18,7 @@
<MultilineTextSetting v-if="setting.type === 'text' && setting.multiline" :setting="setting" :change="change"/>
<SliderSetting v-if="setting.type === 'slider'" :setting="setting" :change="change"/>
<FileSetting v-if="setting.type === 'file'" :setting="setting" :change="change"/>
<ArraySetting v-if="setting.type === 'array'" :setting="setting" :change="change" />
<div class="bd-form-divider"></div>
</div>
</template>
@ -31,6 +32,7 @@
import MultilineTextSetting from './Multiline.vue';
import SliderSetting from './Slider.vue';
import FileSetting from './File.vue';
import ArraySetting from './Array.vue';
export default {
props: [
@ -45,7 +47,8 @@
StringSetting,
MultilineTextSetting,
SliderSetting,
FileSetting
FileSetting,
ArraySetting
},
computed: {
changed() {

View File

@ -17,6 +17,77 @@
"category_default_comment": "default category has no header and is always displayed first",
"category": "default",
"settings": [
{
"id": "array-1",
"type": "array",
"value": null,
"text": "Test settings array",
"hint": "Just a test. Inline should be left as false here in most cases. (Only set it to true if there's only one setting otherwise it takes up too much space. Or you could put it in a drawer.)",
"inline": false,
"min": 1,
"max": 5,
"settings": [
{
"category_default_comment": "default category has no header and is always displayed first",
"category": "default",
"settings": [
{
"id": "default-0",
"type": "bool",
"value": false,
"text": "Bool Test Setting 3",
"hint": "Bool Test Setting Hint 3"
},
{
"id": "default-1",
"type": "text",
"value": "defaultValue",
"text": "Text Test Setting",
"hint": "Text Test Setting Hint"
}
]
}
],
"schemes": [
{
"id": "scheme-1",
"name": "Test scheme",
"hint": "Can even use schemes here.",
"icon_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg",
"settings": [
{
"category": "default",
"settings": [
{
"id": "default-0",
"value": true
}
]
}
]
},
{
"id": "scheme-2",
"name": "Another test scheme",
"icon_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg",
"settings": [
{
"category": "default",
"settings": [
{
"id": "default-0",
"value": false
},
{
"id": "default-1",
"value": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Cow_female_black_white.jpg/220px-Cow_female_black_white.jpg"
}
]
}
]
}
]
},
{
"id": "default-0",
"type": "bool",

View File

@ -20,6 +20,25 @@
"hint": "A colour setting type would be nice here",
"scss_raw": true
},
{
"id": "additional-colours",
"type": "array",
"text": "Additional colours",
"inline": true,
"settings": [
{
"category": "default",
"settings": [
{
"id": "colour",
"type": "text",
"value": "#ff0000",
"scss_raw": true
}
]
}
]
},
{
"id": "spanOpacity",
"type": "slider",