Import domains from url query params on load
							parent
							
								
									f2c0878cda
								
							
						
					
					
						commit
						2273662feb
					
				|  | @ -26,7 +26,7 @@ limitations under the License. | |||
|             </template> | ||||
|         </Header> | ||||
| 
 | ||||
|         <div class="main container"> | ||||
|         <div class="main container" :style="{ display: ready ? undefined : 'none' }"> | ||||
|             <h2>Per-website config</h2> | ||||
| 
 | ||||
|             <div class="tabs"> | ||||
|  | @ -46,7 +46,7 @@ limitations under the License. | |||
|             <template v-for="data in activeDomains"> | ||||
|                 <Domain :key="data[1]" | ||||
|                         :data="data[0]" | ||||
|                         :style="{ display: data[1] === active ? 'block' : 'none' }" | ||||
|                         :style="{ display: data[1] === active ? undefined : 'none' }" | ||||
|                 ></Domain> | ||||
|             </template> | ||||
| 
 | ||||
|  | @ -66,6 +66,8 @@ limitations under the License. | |||
|     import Footer from 'do-vue/src/templates/footer'; | ||||
|     import isChanged from '../util/is_changed'; | ||||
|     import exportData from '../util/export_data'; | ||||
|     import importData from '../util/import_data'; | ||||
|     import isObject from '../util/is_object'; | ||||
|     import i18n from '../i18n'; | ||||
|     import Domain from './domain'; | ||||
|     import Global from './global'; | ||||
|  | @ -81,11 +83,10 @@ limitations under the License. | |||
|         data() { | ||||
|             return { | ||||
|                 i18n, | ||||
|                 domains: [ | ||||
|                     clone(Domain.delegated), | ||||
|                 ], | ||||
|                 domains: [], | ||||
|                 global: Global.delegated, | ||||
|                 active: 0, | ||||
|                 ready: false, | ||||
|             }; | ||||
|         }, | ||||
|         computed: { | ||||
|  | @ -96,11 +97,26 @@ limitations under the License. | |||
|                 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: { | ||||
|             changes(index) { | ||||
|                 const data = this.$data.domains[index]; | ||||
|                 const changes = Object.entries(data).reduce((prev, current) => { | ||||
|                     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; | ||||
|                     return prev; | ||||
|                 }, 0); | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ limitations under the License. | |||
|                        v-for="tab in tabs" | ||||
|                        :key="tab.key" | ||||
|                        :data="$props.data[tab.key]" | ||||
|                        :style="{ display: active === tab.key ? 'block' : 'none' }" | ||||
|                        :style="{ display: active === tab.key ? undefined : 'none' }" | ||||
|                        class="container" | ||||
|             ></component> | ||||
| 
 | ||||
|  | @ -56,6 +56,7 @@ limitations under the License. | |||
| 
 | ||||
|     const tabs = Object.values(Sections); | ||||
|     const delegated = { | ||||
|         hasUserInteraction: false, | ||||
|         presets: Presets.delegated, | ||||
|         ...tabs.reduce((prev, tab) => { | ||||
|             prev[tab.key] = tab.delegated; | ||||
|  | @ -65,10 +66,10 @@ limitations under the License. | |||
| 
 | ||||
|     export default { | ||||
|         name: 'Domain', | ||||
|         delegated, | ||||
|         delegated,          // Data the parent will present here | ||||
|         components: { | ||||
|             Presets, | ||||
|         },          // Data the parent will present here | ||||
|         }, | ||||
|         props: { | ||||
|             data: Object,   // Data delegated back to us from parent | ||||
|         }, | ||||
|  | @ -76,7 +77,6 @@ limitations under the License. | |||
|             return { | ||||
|                 active: tabs[0].key, | ||||
|                 tabs, | ||||
|                 hasUserInteraction: false, | ||||
|             }; | ||||
|         }, | ||||
|         computed: { | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
|     <div class="container"> | ||||
|         <div class="header-group"> | ||||
|             <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"> | ||||
|                     <i class="fas fa-angle-up"></i> | ||||
|                 </a> | ||||
|  | @ -12,8 +12,8 @@ | |||
|             </template> | ||||
|         </div> | ||||
| 
 | ||||
|         <template v-if="!$parent.$data.hasUserInteraction || expanded"> | ||||
|             <div v-if="$parent.$data.hasUserInteraction" class="message is-warning"> | ||||
|         <template v-if="!$parent.$props.data.hasUserInteraction || expanded"> | ||||
|             <div v-if="$parent.$props.data.hasUserInteraction" class="message is-warning"> | ||||
|                 <div class="message-body"> | ||||
|                     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. | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ limitations under the License. | |||
|                    v-for="tab in tabs" | ||||
|                    :key="tab.key" | ||||
|                    :data="$props.data[tab.key]" | ||||
|                    :style="{ display: active === tab.key ? 'block' : 'none' }" | ||||
|                    :style="{ display: active === tab.key ? undefined : 'none' }" | ||||
|                    class="container" | ||||
|         ></component> | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,10 +10,11 @@ export default (defaults, cat, isInteraction = true) => { | |||
|                 // Save user interaction if value changed
 | ||||
|                 if (isInteraction | ||||
|                     && this.$parent | ||||
|                     && 'hasUserInteraction' in this.$parent.$data | ||||
|                     && !this.$parent.$data.hasUserInteraction | ||||
|                     && 'data' in this.$parent.$props | ||||
|                     && 'hasUserInteraction' in this.$parent.$props.data | ||||
|                     && !this.$parent.$props.data.hasUserInteraction | ||||
|                     && 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].computed = value; | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ const categoriesExport = (categories) => { | |||
| 
 | ||||
|     // Work through each category
 | ||||
|     for (const category in categories) { | ||||
|         // Ignore presets
 | ||||
|         if (category === 'presets') continue; | ||||
|         const categoryData = {}; | ||||
| 
 | ||||
|         // 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
	
	 MattIPv4
						MattIPv4