Move presets into their own panel
							parent
							
								
									e7e9cbcfa2
								
							
						
					
					
						commit
						795edd2255
					
				|  | @ -82,6 +82,38 @@ $highlight: #f2c94c; | |||
|     margin-top: 0; | ||||
|     padding: 1.5rem 0 2rem; | ||||
| 
 | ||||
|     &.presets { | ||||
|       text-align: left; | ||||
| 
 | ||||
|       .header-group, | ||||
|       .buttons-group { | ||||
|         display: flex; | ||||
|         flex-direction: row; | ||||
|         justify-content: space-between; | ||||
|       } | ||||
| 
 | ||||
|       .header-group { | ||||
|         h3 { | ||||
|           margin: 0; | ||||
|         } | ||||
| 
 | ||||
|         .button { | ||||
|           &.is-tiny { | ||||
|             font-size: 20px; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       .message, | ||||
|       .buttons-group { | ||||
|         margin: 1rem 0 0; | ||||
|       } | ||||
| 
 | ||||
|       .buttons-group { | ||||
|         align-items: center; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .container { | ||||
|       padding: 0 1.5rem; | ||||
|     } | ||||
|  | @ -91,28 +123,21 @@ $highlight: #f2c94c; | |||
|         padding: 0 1rem; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .buttons-group { | ||||
|     align-items: center; | ||||
|     display: flex; | ||||
|     flex-direction: row; | ||||
|     justify-content: space-between; | ||||
|   } | ||||
|     .navigation-buttons { | ||||
|       align-items: center; | ||||
|       display: flex; | ||||
|       flex-direction: row; | ||||
|       justify-content: flex-end; | ||||
|       margin: 1.5rem 1.5rem 0; | ||||
| 
 | ||||
|   .navigation-buttons { | ||||
|     align-items: center; | ||||
|     display: flex; | ||||
|     flex-direction: row; | ||||
|     justify-content: flex-end; | ||||
|     margin: 1.5rem 1.5rem 0; | ||||
|       .button { | ||||
|         margin-left: .5rem; | ||||
| 
 | ||||
|     .button { | ||||
|       margin-left: .5rem; | ||||
| 
 | ||||
|       i + span, | ||||
|       span + i { | ||||
|         margin: 0 0 0 .5rem; | ||||
|         i + span, | ||||
|         span + i { | ||||
|           margin: 0 0 0 .5rem; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -15,47 +15,60 @@ limitations under the License. | |||
| --> | ||||
| 
 | ||||
| <template> | ||||
|     <div class="panel"> | ||||
|         <div class="tabs"> | ||||
|             <ul> | ||||
|                 <li v-for="tab in tabs" :class="tabClass(tab.key)"> | ||||
|                     <a @click="active = tab.key">{{ tab.display }}{{ changes(tab.key) }}</a> | ||||
|                 </li> | ||||
|             </ul> | ||||
|     <div> | ||||
|         <div class="panel presets"> | ||||
|             <Presets :data="$props.data.presets"></Presets> | ||||
|         </div> | ||||
| 
 | ||||
|         <component :is="tab" | ||||
|                    v-for="tab in tabs" | ||||
|                    :key="tab.key" | ||||
|                    :data="$props.data[tab.key]" | ||||
|                    :style="{ display: active === tab.key ? 'block' : 'none' }" | ||||
|                    class="container" | ||||
|         ></component> | ||||
|         <div class="panel"> | ||||
|             <div class="tabs"> | ||||
|                 <ul> | ||||
|                     <li v-for="tab in tabs" :class="tabClass(tab.key)"> | ||||
|                         <a @click="active = tab.key">{{ tab.display }}{{ changes(tab.key) }}</a> | ||||
|                     </li> | ||||
|                 </ul> | ||||
|             </div> | ||||
| 
 | ||||
|         <div class="navigation-buttons"> | ||||
|             <a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab"> | ||||
|                 <i class="fas fa-long-arrow-alt-left"></i> <span>Back</span> | ||||
|             </a> | ||||
|             <a v-if="nextTab !== false" class="button is-primary is-mini" @click="active = nextTab"> | ||||
|                 <span>Next</span> <i class="fas fa-long-arrow-alt-right"></i> | ||||
|             </a> | ||||
|             <component :is="tab" | ||||
|                        v-for="tab in tabs" | ||||
|                        :key="tab.key" | ||||
|                        :data="$props.data[tab.key]" | ||||
|                        :style="{ display: active === tab.key ? 'block' : 'none' }" | ||||
|                        class="container" | ||||
|             ></component> | ||||
| 
 | ||||
|             <div class="navigation-buttons"> | ||||
|                 <a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab"> | ||||
|                     <i class="fas fa-long-arrow-alt-left"></i> <span>Back</span> | ||||
|                 </a> | ||||
|                 <a v-if="nextTab !== false" class="button is-primary is-mini" @click="active = nextTab"> | ||||
|                     <span>Next</span> <i class="fas fa-long-arrow-alt-right"></i> | ||||
|                 </a> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
|     import isChanged from '../util/is_changed'; | ||||
|     import Presets from './domain_sections/presets'; | ||||
|     import * as Sections from './domain_sections'; | ||||
| 
 | ||||
|     const tabs = Object.values(Sections); | ||||
|     const delegated = tabs.reduce((prev, tab) => { | ||||
|         prev[tab.key] = tab.delegated; | ||||
|         return prev; | ||||
|     }, {}); | ||||
|     const delegated = { | ||||
|         presets: Presets.delegated, | ||||
|         ...tabs.reduce((prev, tab) => { | ||||
|             prev[tab.key] = tab.delegated; | ||||
|             return prev; | ||||
|         }, {}), | ||||
|     }; | ||||
| 
 | ||||
|     export default { | ||||
|         name: 'Domain', | ||||
|         delegated,          // Data the parent will present here | ||||
|         delegated, | ||||
|         components: { | ||||
|             Presets, | ||||
|         },          // Data the parent will present here | ||||
|         props: { | ||||
|             data: Object,   // Data delegated back to us from parent | ||||
|         }, | ||||
|  | @ -63,6 +76,7 @@ limitations under the License. | |||
|             return { | ||||
|                 active: tabs[0].key, | ||||
|                 tabs, | ||||
|                 hasUserInteraction: false, | ||||
|             }; | ||||
|         }, | ||||
|         computed: { | ||||
|  | @ -81,7 +95,6 @@ limitations under the License. | |||
|         }, | ||||
|         methods: { | ||||
|             changesCount(tab) { | ||||
|                 if (tab === 'presets') return 0; // Ignore changes from presets | ||||
|                 return Object.keys(this.$props.data[tab]) | ||||
|                     .filter(key => isChanged(this.$props.data[tab][key], tab, key)).length; | ||||
|             }, | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| export { default as Presets } from './presets'; | ||||
| export { default as Server } from './server'; | ||||
| export { default as HTTPS } from './https'; | ||||
| export { default as PHP } from './php'; | ||||
|  |  | |||
|  | @ -1,13 +1,34 @@ | |||
| <template> | ||||
|     <div> | ||||
|         <div class="buttons-group"> | ||||
|             <a v-for="(preset, key) in $props.data" | ||||
|                :class="`button${preset.computed ? ' is-primary' : ''}`" | ||||
|                @click="setPreset(key)" | ||||
|             > | ||||
|                 {{ preset.display }} | ||||
|             </a> | ||||
|     <div class="container"> | ||||
|         <div class="header-group"> | ||||
|             <h3>Presets</h3> | ||||
|             <template v-if="$parent.$data.hasUserInteraction"> | ||||
|                 <a v-if="expanded" class="button is-tiny" @click="expanded = false"> | ||||
|                     <i class="fas fa-angle-up"></i> | ||||
|                 </a> | ||||
|                 <a v-else class="button is-tiny" @click="expanded = true"> | ||||
|                     <i class="fas fa-angle-down"></i> | ||||
|                 </a> | ||||
|             </template> | ||||
|         </div> | ||||
| 
 | ||||
|         <template v-if="!$parent.$data.hasUserInteraction || expanded"> | ||||
|             <div v-if="$parent.$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. | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="buttons-group"> | ||||
|                 <a v-for="(preset, key) in $props.data" | ||||
|                    :class="`button${preset.computed ? ' is-primary' : ''}`" | ||||
|                    @click="setPreset(key)" | ||||
|                 > | ||||
|                     {{ preset.display }} | ||||
|                 </a> | ||||
|             </div> | ||||
|         </template> | ||||
|     </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -114,19 +135,20 @@ | |||
|     }; | ||||
| 
 | ||||
|     export default { | ||||
|         name: 'DomainPresets',                      // Component name | ||||
|         display: 'Presets',                         // Display name for tab | ||||
|         key: 'presets',                             // Key for data in parent | ||||
|         delegated: delegatedFromDefaults(defaults), // Data the parent will present here | ||||
|         name: 'DomainPresets',                                      // Component name | ||||
|         display: 'Presets',                                         // Display name for tab | ||||
|         key: 'presets',                                             // Key for data in parent | ||||
|         delegated: delegatedFromDefaults(defaults),                 // Data the parent will present here | ||||
|         props: { | ||||
|             data: Object,                           // Data delegated back to us from parent | ||||
|             data: Object,                                           // Data delegated back to us from parent | ||||
|         }, | ||||
|         data () { | ||||
|             return { | ||||
|                 i18n, | ||||
|                 expanded: false, | ||||
|             }; | ||||
|         }, | ||||
|         computed: computedFromDefaults(defaults),   // Getters & setters for the delegated data | ||||
|         computed: computedFromDefaults(defaults, 'presets', false), // Getters & setters for the delegated data | ||||
|         watch: { | ||||
|             // When any data changes, check if it still matches a preset | ||||
|             '$parent.$props.data': { | ||||
|  |  | |||
|  | @ -1,12 +1,20 @@ | |||
| import isChanged from './is_changed'; | ||||
| 
 | ||||
| export default (defaults, cat) => { | ||||
| export default (defaults, cat, isInteraction = true) => { | ||||
|     return Object.keys(defaults).reduce((prev, key) => { | ||||
|         prev[key] = { | ||||
|             get() { | ||||
|                 return this.$props.data[key].value; | ||||
|             }, | ||||
|             set (value) { | ||||
|                 // Save user interaction if value changed
 | ||||
|                 if (isInteraction | ||||
|                     && this.$parent | ||||
|                     && 'hasUserInteraction' in this.$parent.$data | ||||
|                     && !this.$parent.$data.hasUserInteraction | ||||
|                     && this.$props.data[key].value !== value) | ||||
|                         this.$parent.$data.hasUserInteraction = true; | ||||
| 
 | ||||
|                 this.$props.data[key].value = value; | ||||
|                 this.$props.data[key].computed = value; | ||||
|             }, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 MattIPv4
						MattIPv4