Import domains from url query params on load
This commit is contained in:
parent
f2c0878cda
commit
2273662feb
|
@ -26,7 +26,7 @@ limitations under the License.
|
||||||
</template>
|
</template>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
<div class="main container">
|
<div class="main container" :style="{ display: ready ? undefined : 'none' }">
|
||||||
<h2>Per-website config</h2>
|
<h2>Per-website config</h2>
|
||||||
|
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
|
@ -46,7 +46,7 @@ limitations under the License.
|
||||||
<template v-for="data in activeDomains">
|
<template v-for="data in activeDomains">
|
||||||
<Domain :key="data[1]"
|
<Domain :key="data[1]"
|
||||||
:data="data[0]"
|
:data="data[0]"
|
||||||
:style="{ display: data[1] === active ? 'block' : 'none' }"
|
:style="{ display: data[1] === active ? undefined : 'none' }"
|
||||||
></Domain>
|
></Domain>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ limitations under the License.
|
||||||
import Footer from 'do-vue/src/templates/footer';
|
import Footer from 'do-vue/src/templates/footer';
|
||||||
import isChanged from '../util/is_changed';
|
import isChanged from '../util/is_changed';
|
||||||
import exportData from '../util/export_data';
|
import exportData from '../util/export_data';
|
||||||
|
import importData from '../util/import_data';
|
||||||
|
import isObject from '../util/is_object';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import Domain from './domain';
|
import Domain from './domain';
|
||||||
import Global from './global';
|
import Global from './global';
|
||||||
|
@ -81,11 +83,10 @@ limitations under the License.
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
i18n,
|
i18n,
|
||||||
domains: [
|
domains: [],
|
||||||
clone(Domain.delegated),
|
|
||||||
],
|
|
||||||
global: Global.delegated,
|
global: Global.delegated,
|
||||||
active: 0,
|
active: 0,
|
||||||
|
ready: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -96,11 +97,26 @@ limitations under the License.
|
||||||
return JSON.stringify(exportData(this.activeDomains, this.$data.global), null, 2);
|
return JSON.stringify(exportData(this.activeDomains, this.$data.global), null, 2);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
// If there is no query param, add one default domain and we're ready
|
||||||
|
if (!window.location.search.length) {
|
||||||
|
this.$data.domains.push(clone(Domain.delegated));
|
||||||
|
this.$data.ready = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import any data from the URL query params
|
||||||
|
importData(window.location.search, this.$data.domains, this.$data.global, this.$nextTick);
|
||||||
|
|
||||||
|
// After two ticks (one tick to set watched data), we are ready
|
||||||
|
this.$nextTick(() => this.$nextTick(() => this.$data.ready = true));
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changes(index) {
|
changes(index) {
|
||||||
const data = this.$data.domains[index];
|
const data = this.$data.domains[index];
|
||||||
const changes = Object.entries(data).reduce((prev, current) => {
|
const changes = Object.entries(data).reduce((prev, current) => {
|
||||||
if (current[0] === 'presets') return prev; // Ignore changes from presets
|
if (current[0] === 'presets') return prev; // Ignore changes from presets
|
||||||
|
if (!isObject(current[1])) return prev; // Ignore non-objects (things that aren't tabs)
|
||||||
prev += Object.keys(current[1]).filter(key => isChanged(current[1][key], current[0], key)).length;
|
prev += Object.keys(current[1]).filter(key => isChanged(current[1][key], current[0], key)).length;
|
||||||
return prev;
|
return prev;
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
|
@ -33,7 +33,7 @@ limitations under the License.
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
:data="$props.data[tab.key]"
|
:data="$props.data[tab.key]"
|
||||||
:style="{ display: active === tab.key ? 'block' : 'none' }"
|
:style="{ display: active === tab.key ? undefined : 'none' }"
|
||||||
class="container"
|
class="container"
|
||||||
></component>
|
></component>
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ limitations under the License.
|
||||||
|
|
||||||
const tabs = Object.values(Sections);
|
const tabs = Object.values(Sections);
|
||||||
const delegated = {
|
const delegated = {
|
||||||
|
hasUserInteraction: false,
|
||||||
presets: Presets.delegated,
|
presets: Presets.delegated,
|
||||||
...tabs.reduce((prev, tab) => {
|
...tabs.reduce((prev, tab) => {
|
||||||
prev[tab.key] = tab.delegated;
|
prev[tab.key] = tab.delegated;
|
||||||
|
@ -65,10 +66,10 @@ limitations under the License.
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Domain',
|
name: 'Domain',
|
||||||
delegated,
|
delegated, // Data the parent will present here
|
||||||
components: {
|
components: {
|
||||||
Presets,
|
Presets,
|
||||||
}, // Data the parent will present here
|
},
|
||||||
props: {
|
props: {
|
||||||
data: Object, // Data delegated back to us from parent
|
data: Object, // Data delegated back to us from parent
|
||||||
},
|
},
|
||||||
|
@ -76,7 +77,6 @@ limitations under the License.
|
||||||
return {
|
return {
|
||||||
active: tabs[0].key,
|
active: tabs[0].key,
|
||||||
tabs,
|
tabs,
|
||||||
hasUserInteraction: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="header-group">
|
<div class="header-group">
|
||||||
<h3>Presets</h3>
|
<h3>Presets</h3>
|
||||||
<template v-if="$parent.$data.hasUserInteraction">
|
<template v-if="$parent.$props.data.hasUserInteraction">
|
||||||
<a v-if="expanded" class="button is-tiny" @click="expanded = false">
|
<a v-if="expanded" class="button is-tiny" @click="expanded = false">
|
||||||
<i class="fas fa-angle-up"></i>
|
<i class="fas fa-angle-up"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-if="!$parent.$data.hasUserInteraction || expanded">
|
<template v-if="!$parent.$props.data.hasUserInteraction || expanded">
|
||||||
<div v-if="$parent.$data.hasUserInteraction" class="message is-warning">
|
<div v-if="$parent.$props.data.hasUserInteraction" class="message is-warning">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
It looks like you've customised the configuration for this domain.
|
It looks like you've customised the configuration for this domain.
|
||||||
Choosing a new preset may reset or change some of the settings that you've customised.
|
Choosing a new preset may reset or change some of the settings that you've customised.
|
||||||
|
|
|
@ -28,7 +28,7 @@ limitations under the License.
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
:data="$props.data[tab.key]"
|
:data="$props.data[tab.key]"
|
||||||
:style="{ display: active === tab.key ? 'block' : 'none' }"
|
:style="{ display: active === tab.key ? undefined : 'none' }"
|
||||||
class="container"
|
class="container"
|
||||||
></component>
|
></component>
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,11 @@ export default (defaults, cat, isInteraction = true) => {
|
||||||
// Save user interaction if value changed
|
// Save user interaction if value changed
|
||||||
if (isInteraction
|
if (isInteraction
|
||||||
&& this.$parent
|
&& this.$parent
|
||||||
&& 'hasUserInteraction' in this.$parent.$data
|
&& 'data' in this.$parent.$props
|
||||||
&& !this.$parent.$data.hasUserInteraction
|
&& 'hasUserInteraction' in this.$parent.$props.data
|
||||||
|
&& !this.$parent.$props.data.hasUserInteraction
|
||||||
&& this.$props.data[key].value !== value)
|
&& this.$props.data[key].value !== value)
|
||||||
this.$parent.$data.hasUserInteraction = true;
|
this.$parent.$props.data.hasUserInteraction = true;
|
||||||
|
|
||||||
this.$props.data[key].value = value;
|
this.$props.data[key].value = value;
|
||||||
this.$props.data[key].computed = value;
|
this.$props.data[key].computed = value;
|
||||||
|
|
|
@ -3,6 +3,8 @@ const categoriesExport = (categories) => {
|
||||||
|
|
||||||
// Work through each category
|
// Work through each category
|
||||||
for (const category in categories) {
|
for (const category in categories) {
|
||||||
|
// Ignore presets
|
||||||
|
if (category === 'presets') continue;
|
||||||
const categoryData = {};
|
const categoryData = {};
|
||||||
|
|
||||||
// Go over each property in the category
|
// Go over each property in the category
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
import qs from 'qs';
|
||||||
|
import clone from 'clone';
|
||||||
|
import Domain from '../templates/domain';
|
||||||
|
import isObject from './is_object';
|
||||||
|
|
||||||
|
export default (query, domains, global, nextTick) => {
|
||||||
|
const data = qs.parse(query, {
|
||||||
|
ignoreQueryPrefix: true,
|
||||||
|
allowDots: true,
|
||||||
|
decoder(value) {
|
||||||
|
// If it's a set of digits, parse it as a float
|
||||||
|
if (/^(\d+|\d*\.\d+)$/.test(value)) {
|
||||||
|
return parseFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it matches a keyword, convert it
|
||||||
|
let keywords = {
|
||||||
|
true: true,
|
||||||
|
false: false,
|
||||||
|
null: null,
|
||||||
|
undefined: undefined,
|
||||||
|
};
|
||||||
|
if (value in keywords) {
|
||||||
|
return keywords[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, leave it as is
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle domains
|
||||||
|
if ('domains' in data) {
|
||||||
|
// Check its an array or object
|
||||||
|
if (Array.isArray(data.domains) || isObject(data.domains)) {
|
||||||
|
// Ensure we're working with an array
|
||||||
|
const values = isObject(data.domains) ? Object.values(data.domains) : data.domains;
|
||||||
|
|
||||||
|
// Work through each potential domain
|
||||||
|
for (const domainData of values) {
|
||||||
|
// Check this is an object
|
||||||
|
if (!isObject(domainData)) continue;
|
||||||
|
|
||||||
|
// Create a new domain (assume it has had custom user settings)
|
||||||
|
const domainImported = clone(Domain.delegated);
|
||||||
|
domainImported.hasUserInteraction = true;
|
||||||
|
domains.push(domainImported);
|
||||||
|
|
||||||
|
// Apply the initial values on the next Vue tick, once the watchers are ready
|
||||||
|
nextTick(() => {
|
||||||
|
// Work through each potential category
|
||||||
|
for (const category in domainData) {
|
||||||
|
// Ignore presets
|
||||||
|
if (category === 'presets') continue;
|
||||||
|
|
||||||
|
// Check this is a real category
|
||||||
|
if (!(category in domainImported)) continue;
|
||||||
|
|
||||||
|
// Check this is an object
|
||||||
|
if (!isObject(domainData[category])) continue;
|
||||||
|
|
||||||
|
// Work through each potential setting in this category
|
||||||
|
for (const key in domainData[category]) {
|
||||||
|
// Check this is a real key
|
||||||
|
if (!(key in domainImported[category])) continue;
|
||||||
|
|
||||||
|
// Apply the value
|
||||||
|
domainImported[category][key].value = domainData[category][key];
|
||||||
|
domainImported[category][key].computed = domainData[category][key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle global settings
|
||||||
|
// TODO
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
export default obj => Object.prototype.toString.call(obj) === '[object Object]';
|
Loading…
Reference in New Issue