Compare commits
	
		
			26 Commits
		
	
	
		
			2.1.4-ERT
			...
			save-style
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d4269e2546 | ||
|   | c3cb47c670 | ||
|   | 42d519cf4a | ||
|   | 7c98d809c0 | ||
|   | 306b9db8ed | ||
|   | e05580b973 | ||
|   | d44ad83445 | ||
|   | 1397c45a96 | ||
|   | 15c0a1cf36 | ||
|   | 106ef8994a | ||
|   | 72e5618706 | ||
|   | 5e9c51a22c | ||
|   | 1270976a0e | ||
|   | ad9ac4ca1e | ||
|   | 0c2c21a015 | ||
|   | 92b8b811d5 | ||
|   | f5a0d6620b | ||
|   | dbf3f3c6d8 | ||
|   | cfa7717204 | ||
|   | 5127a40bd5 | ||
|   | 3eb2a64969 | ||
|   | 8f38a0da9a | ||
|   | 21f337c308 | ||
|   | bad0b380b9 | ||
|   | b83a38a00b | ||
|   | dd1f57b2bf | 
| @@ -21,9 +21,9 @@ | ||||
| *****************************************************************************/ | ||||
|  | ||||
| <template> | ||||
| <div class="c-style"> | ||||
| <div class="c-style has-local-controls"> | ||||
|     <span :class="[ | ||||
|               { 'is-style-invisible': styleItem.style.isStyleInvisible }, | ||||
|               { 'is-style-invisible': styleItem.style && styleItem.style.isStyleInvisible }, | ||||
|               { 'c-style-thumb--mixed': mixedStyles.indexOf('backgroundColor') > -1 } | ||||
|           ]" | ||||
|           :style="[styleItem.style.imageUrl ? { backgroundImage:'url(' + styleItem.style.imageUrl + ')'} : itemStyle ]" | ||||
| @@ -61,6 +61,13 @@ | ||||
|                                :options="isStyleInvisibleOption" | ||||
|                                @change="updateStyleValue" | ||||
|         /> | ||||
|  | ||||
|         <!-- Save Styles --> | ||||
|         <toolbar-button v-if="canSaveStyle()" | ||||
|                         class="c-style__toolbar-button--save c-local-controls--show-on-hover" | ||||
|                         :options="saveOptions" | ||||
|                         @click="saveItemStyle()" | ||||
|         /> | ||||
|     </span> | ||||
| </div> | ||||
| </template> | ||||
| @@ -81,11 +88,12 @@ export default { | ||||
|         ToolbarToggleButton | ||||
|     }, | ||||
|     inject: [ | ||||
|         'openmct' | ||||
|         'openmct', 'stylesManager' | ||||
|     ], | ||||
|     props: { | ||||
|         isEditing: { | ||||
|             type: Boolean | ||||
|             type: Boolean, | ||||
|             required: true | ||||
|         }, | ||||
|         mixedStyles: { | ||||
|             type: Array, | ||||
| @@ -182,7 +190,16 @@ export default { | ||||
|                     } | ||||
|                 ] | ||||
|             }; | ||||
|  | ||||
|         }, | ||||
|         saveOptions() { | ||||
|             return { | ||||
|                 icon: 'icon-save', | ||||
|                 title: 'Save style', | ||||
|                 // value: this.normalizeValueForSwatch(value), | ||||
|                 // property: 'color', | ||||
|                 isEditing: this.isEditing | ||||
|                 // nonSpecific: this.mixedStyles.indexOf('color') > -1 | ||||
|             }; | ||||
|         } | ||||
|     }, | ||||
|     methods: { | ||||
| @@ -216,6 +233,12 @@ export default { | ||||
|             } | ||||
|  | ||||
|             this.$emit('persist', this.styleItem, item.property); | ||||
|         }, | ||||
|         canSaveStyle() { | ||||
|             return this.isEditing && !this.mixedStyles.length; | ||||
|         }, | ||||
|         saveItemStyle() { | ||||
|             this.stylesManager.save(this.itemStyle); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|   | ||||
| @@ -125,7 +125,8 @@ export default { | ||||
|     }, | ||||
|     inject: [ | ||||
|         'openmct', | ||||
|         'selection' | ||||
|         'selection', | ||||
|         'stylesManager' | ||||
|     ], | ||||
|     data() { | ||||
|         return { | ||||
| @@ -149,6 +150,8 @@ export default { | ||||
|     }, | ||||
|     destroyed() { | ||||
|         this.removeListeners(); | ||||
|         this.openmct.editor.off('isEditing', this.setEditState); | ||||
|         this.stylesManager.off('styleSelected', this.updateSelectionStyle); | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.items = []; | ||||
| @@ -167,6 +170,7 @@ export default { | ||||
|         } | ||||
|  | ||||
|         this.openmct.editor.on('isEditing', this.setEditState); | ||||
|         this.stylesManager.on('styleSelected', this.updateSelectionStyle); | ||||
|     }, | ||||
|     methods: { | ||||
|         getObjectStyles() { | ||||
| @@ -637,6 +641,30 @@ export default { | ||||
|         }, | ||||
|         persist(domainObject, style) { | ||||
|             this.openmct.objects.mutate(domainObject, 'configuration.objectStyles', style); | ||||
|         }, | ||||
|         updateSelectionStyle(style) { | ||||
|             if (!this.allowEditing) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const foundStyle = this.findStyleByConditionId(this.selectedConditionId); | ||||
|  | ||||
|             if (foundStyle && !this.isStaticAndConditionalStyles) { | ||||
|                 Object.entries(style).forEach(([property, value]) => { | ||||
|                     if (foundStyle.style[property] !== undefined && foundStyle.style[property] !== value) { | ||||
|                         foundStyle.style[property] = value; | ||||
|                     } | ||||
|                 }); | ||||
|                 this.getAndPersistStyles(); | ||||
|             } else { | ||||
|                 this.removeConditionSet(); | ||||
|                 Object.entries(style).forEach(([property, value]) => { | ||||
|                     if (this.staticStyle.style[property] !== undefined && this.staticStyle.style[property] !== value) { | ||||
|                         this.staticStyle.style[property] = value; | ||||
|                         this.getAndPersistStyles(property); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|   | ||||
| @@ -87,6 +87,15 @@ | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &__selector { | ||||
|         &:hover { | ||||
|             $c: $colorBodyFg; | ||||
|             border-color: rgba($c, 0.2); | ||||
|             background: rgba($c, 0.2); | ||||
|             transition: $transIn; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .c-style { | ||||
|         padding: 2px; // Allow a bit of room for thumb box-shadow | ||||
|  | ||||
|   | ||||
| @@ -113,6 +113,10 @@ button { | ||||
|     } | ||||
| } | ||||
|  | ||||
| .c-icon-button--disabled { | ||||
|     @include cClickIconButtonLayout(); | ||||
| } | ||||
|  | ||||
| .c-icon-link { | ||||
|     &:before { | ||||
|         // Icon | ||||
| @@ -120,7 +124,8 @@ button { | ||||
|     } | ||||
| } | ||||
|  | ||||
| .c-icon-button { | ||||
| .c-icon-button, | ||||
| .c-icon-button--disabled { | ||||
|     &__label { | ||||
|         margin-left: $interiorMargin; | ||||
|     } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
|  | ||||
|     </div> | ||||
|     <div class="c-inspector__content"> | ||||
|         <multipane v-if="currentTabbedView.key === '__properties'" | ||||
|         <multipane v-show="currentTabbedView.key === '__properties'" | ||||
|                    type="vertical" | ||||
|         > | ||||
|             <pane class="c-inspector__properties"> | ||||
| @@ -32,9 +32,13 @@ | ||||
|                 <elements /> | ||||
|             </pane> | ||||
|         </multipane> | ||||
|         <template v-else> | ||||
|             <styles-inspector-view /> | ||||
|         </template> | ||||
|         <StylesInspectorView | ||||
|             v-show="currentTabbedView.key === '__styles'" | ||||
|         /> | ||||
|         <SavedStylesInspectorView | ||||
|             v-show="currentTabbedView.key === '__styles'" | ||||
|             :is-editing="isEditing" | ||||
|         /> | ||||
|     </div> | ||||
| </div> | ||||
| </template> | ||||
| @@ -48,12 +52,18 @@ import Properties from './Properties.vue'; | ||||
| import ObjectName from './ObjectName.vue'; | ||||
| import InspectorViews from './InspectorViews.vue'; | ||||
| import _ from "lodash"; | ||||
| import StylesInspectorView from "./StylesInspectorView.vue"; | ||||
| import stylesManager from '@/ui/inspector/StylesManager'; | ||||
| import StylesInspectorView from './StylesInspectorView.vue'; | ||||
| import SavedStylesInspectorView from './SavedStylesInspectorView.vue'; | ||||
|  | ||||
| export default { | ||||
|     provide: { | ||||
|         stylesManager: stylesManager | ||||
|     }, | ||||
|     inject: ['openmct'], | ||||
|     components: { | ||||
|         StylesInspectorView, | ||||
|         SavedStylesInspectorView, | ||||
|         multipane, | ||||
|         pane, | ||||
|         Elements, | ||||
| @@ -63,7 +73,10 @@ export default { | ||||
|         InspectorViews | ||||
|     }, | ||||
|     props: { | ||||
|         'isEditing': Boolean | ||||
|         isEditing: { | ||||
|             type: Boolean, | ||||
|             required: true | ||||
|         } | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|   | ||||
							
								
								
									
										208
									
								
								src/ui/inspector/SavedStyleSelector.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								src/ui/inspector/SavedStyleSelector.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| /***************************************************************************** | ||||
| * Open MCT, Copyright (c) 2014-2020, United States Government | ||||
| * as represented by the Administrator of the National Aeronautics and Space | ||||
| * Administration. All rights reserved. | ||||
| * | ||||
| * Open MCT is licensed under the Apache License, Version 2.0 (the | ||||
| * "License"); you may not use this file except in compliance with the License. | ||||
| * You may obtain a copy of the License at | ||||
| * http://www.apache.org/licenses/LICENSE-2.0. | ||||
| * | ||||
| * Unless required by applicable law or agreed to in writing, software | ||||
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| * License for the specific language governing permissions and limitations | ||||
| * under the License. | ||||
| * | ||||
| * Open MCT includes source code licensed under additional open source | ||||
| * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
| * this source code distribution or the Licensing information page available | ||||
| * at runtime from the About dialog for additional information. | ||||
| *****************************************************************************/ | ||||
|  | ||||
| <template> | ||||
| <div | ||||
|     class="c-saved-style" | ||||
|     @click="selectStyle()" | ||||
| > | ||||
|     <div class="c-style has-local-controls"> | ||||
|         <span | ||||
|             class="c-disclosure-triangle is-enabled" | ||||
|             :class="{ 'c-disclosure-triangle--expanded': expanded }" | ||||
|             @click.stop="toggleExpanded()" | ||||
|         ></span> | ||||
|         <span | ||||
|             class="c-style-thumb" | ||||
|             :style="thumbStyle" | ||||
|         > | ||||
|             <span | ||||
|                 class="c-style-thumb__text" | ||||
|                 :class="{ 'hide-nice': !hasProperty(savedStyle.color) }" | ||||
|             > | ||||
|                 ABC | ||||
|             </span> | ||||
|         </span> | ||||
|         <span class="c-toolbar"> | ||||
|             <div class="c-ctrl-wrapper"> | ||||
|                 <div | ||||
|                     class="c-icon-button--disabled c-icon-button--swatched icon-line-horz" | ||||
|                     title="Border color" | ||||
|                 > | ||||
|                     <div | ||||
|                         class="c-swatch" | ||||
|                         :style="{ | ||||
|                             background: savedStyle.border | ||||
|                         }" | ||||
|                     ></div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="c-ctrl-wrapper"> | ||||
|                 <div | ||||
|                     class="c-icon-button--disabled c-icon-button--swatched icon-paint-bucket" | ||||
|                     title="Background color" | ||||
|                 > | ||||
|                     <div | ||||
|                         class="c-swatch" | ||||
|                         :style="{ | ||||
|                             background: savedStyle.backgroundColor | ||||
|                         }" | ||||
|                     ></div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="c-ctrl-wrapper"> | ||||
|                 <div | ||||
|                     class="c-icon-button--disabled c-icon-button--swatched icon-font" | ||||
|                     title="Text color" | ||||
|                 > | ||||
|                     <div | ||||
|                         class="c-swatch" | ||||
|                         :style="{ | ||||
|                             background: savedStyle.color | ||||
|                         }" | ||||
|                     ></div> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <!-- delete saved style --> | ||||
|             <div | ||||
|                 v-if="canDeleteStyle" | ||||
|                 class="c-ctrl-wrapper c-local-controls--show-on-hover" | ||||
|             > | ||||
|                 <div | ||||
|                     class="c-icon-button icon-trash" | ||||
|                     title="Delete Style" | ||||
|                     @click.stop="deleteStyle()" | ||||
|                 > | ||||
|                 </div> | ||||
|             </div> | ||||
|         </span> | ||||
|     </div> | ||||
|  | ||||
|     <div v-if="expanded"> | ||||
|         {{ description }} | ||||
|     </div> | ||||
| </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|     name: 'SavedStyleSelector', | ||||
|     inject: [ | ||||
|         'openmct', | ||||
|         'stylesManager' | ||||
|     ], | ||||
|     props: { | ||||
|         isEditing: { | ||||
|             type: Boolean, | ||||
|             required: true | ||||
|         }, | ||||
|         savedStyle: { | ||||
|             type: Object, | ||||
|             required: true | ||||
|         } | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             expanded: false | ||||
|         }; | ||||
|     }, | ||||
|     computed: { | ||||
|         thumbStyle() { | ||||
|             return { | ||||
|                 border: `1px solid ${this.savedStyle.border}`, | ||||
|                 backgroundColor: this.savedStyle.backgroundColor, | ||||
|                 color: this.savedStyle.color | ||||
|             }; | ||||
|         }, | ||||
|         description() { | ||||
|             const fill = `Fill: ${this.savedStyle.backgroundColor || 'None'};`; | ||||
|             const border = `Border: ${this.savedStyle.border || 'None'};`; | ||||
|             const color = `Text Color: ${this.savedStyle.color || 'None'};`; | ||||
|             const fontSize = this.savedStyle.fontSize ? `Font Size: ${this.savedStyle.fontSize};` : ''; | ||||
|             const font = this.savedStyle.font ? `Font Family: ${this.savedStyle.font};` : ''; | ||||
|  | ||||
|             return ` | ||||
|                 ${fill} | ||||
|                 ${border} | ||||
|                 ${color} | ||||
|                 ${fontSize} | ||||
|                 ${font} | ||||
|             `; | ||||
|         }, | ||||
|         canDeleteStyle() { | ||||
|             return this.isEditing; | ||||
|         } | ||||
|     }, | ||||
|     methods: { | ||||
|         selectStyle() { | ||||
|             if (this.isEditing) { | ||||
|                 this.stylesManager.select(this.savedStyle); | ||||
|             } | ||||
|         }, | ||||
|         deleteStyle(style) { | ||||
|             this.showDeleteStyleDialog(style) | ||||
|                 .then(() => { | ||||
|                     this.stylesManager.delete(this.savedStyle); | ||||
|                 }) | ||||
|                 .catch(() => {}); | ||||
|         }, | ||||
|         showDeleteStyleDialog(style) { | ||||
|             const message = ` | ||||
|                 This will delete this saved style. | ||||
|                 This action will not effect styling that has already been applied. | ||||
|                 Do you want to continue? | ||||
|             `; | ||||
|  | ||||
|             return new Promise((resolve, reject) => { | ||||
|                 let dialog = this.openmct.overlays.dialog({ | ||||
|                     title: 'Delete Saved Style', | ||||
|                     iconClass: 'alert', | ||||
|                     message: message, | ||||
|                     buttons: [ | ||||
|                         { | ||||
|                             label: 'OK', | ||||
|                             callback: () => { | ||||
|                                 dialog.dismiss(); | ||||
|                                 resolve(); | ||||
|                             } | ||||
|                         }, | ||||
|                         { | ||||
|                             label: 'Cancel', | ||||
|                             callback: () => { | ||||
|                                 dialog.dismiss(); | ||||
|                                 reject(); | ||||
|                             } | ||||
|                         } | ||||
|                     ] | ||||
|                 }); | ||||
|             }); | ||||
|         }, | ||||
|         hasProperty(property) { | ||||
|             return property !== undefined; | ||||
|         }, | ||||
|         toggleExpanded() { | ||||
|             this.expanded = !this.expanded; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										72
									
								
								src/ui/inspector/SavedStylesInspectorView.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/ui/inspector/SavedStylesInspectorView.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| /***************************************************************************** | ||||
| * Open MCT, Copyright (c) 2014-2020, United States Government | ||||
| * as represented by the Administrator of the National Aeronautics and Space | ||||
| * Administration. All rights reserved. | ||||
| * | ||||
| * Open MCT is licensed under the Apache License, Version 2.0 (the | ||||
| * "License"); you may not use this file except in compliance with the License. | ||||
| * You may obtain a copy of the License at | ||||
| * http://www.apache.org/licenses/LICENSE-2.0. | ||||
| * | ||||
| * Unless required by applicable law or agreed to in writing, software | ||||
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| * License for the specific language governing permissions and limitations | ||||
| * under the License. | ||||
| * | ||||
| * Open MCT includes source code licensed under additional open source | ||||
| * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
| * this source code distribution or the Licensing information page available | ||||
| * at runtime from the About dialog for additional information. | ||||
| *****************************************************************************/ | ||||
|  | ||||
| <template> | ||||
| <div class="u-contents"></div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import SavedStylesView from './SavedStylesView.vue'; | ||||
| import Vue from 'vue'; | ||||
|  | ||||
| export default { | ||||
|     inject: ['openmct', 'stylesManager'], | ||||
|     data() { | ||||
|         return { | ||||
|             selection: [] | ||||
|         }; | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.openmct.selection.on('change', this.updateSelection); | ||||
|         this.updateSelection(this.openmct.selection.get()); | ||||
|     }, | ||||
|     destroyed() { | ||||
|         this.openmct.selection.off('change', this.updateSelection); | ||||
|     }, | ||||
|     methods: { | ||||
|         updateSelection(selection) { | ||||
|             if (selection.length > 0 && selection[0].length > 0) { | ||||
|                 if (this.component) { | ||||
|                     this.component.$destroy(); | ||||
|                     this.component = undefined; | ||||
|                     this.$el.innerHTML = ''; | ||||
|                 } | ||||
|  | ||||
|                 let viewContainer = document.createElement('div'); | ||||
|                 this.$el.append(viewContainer); | ||||
|                 this.component = new Vue({ | ||||
|                     el: viewContainer, | ||||
|                     components: { | ||||
|                         SavedStylesView | ||||
|                     }, | ||||
|                     provide: { | ||||
|                         openmct: this.openmct, | ||||
|                         selection: selection, | ||||
|                         stylesManager: this.stylesManager | ||||
|                     }, | ||||
|                     template: '<saved-styles-view />' | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| </script> | ||||
							
								
								
									
										132
									
								
								src/ui/inspector/SavedStylesView.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/ui/inspector/SavedStylesView.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| /***************************************************************************** | ||||
| * Open MCT, Copyright (c) 2014-2020, United States Government | ||||
| * as represented by the Administrator of the National Aeronautics and Space | ||||
| * Administration. All rights reserved. | ||||
| * | ||||
| * Open MCT is licensed under the Apache License, Version 2.0 (the | ||||
| * "License"); you may not use this file except in compliance with the License. | ||||
| * You may obtain a copy of the License at | ||||
| * http://www.apache.org/licenses/LICENSE-2.0. | ||||
| * | ||||
| * Unless required by applicable law or agreed to in writing, software | ||||
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| * License for the specific language governing permissions and limitations | ||||
| * under the License. | ||||
| * | ||||
| * Open MCT includes source code licensed under additional open source | ||||
| * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
| * this source code distribution or the Licensing information page available | ||||
| * at runtime from the About dialog for additional information. | ||||
| *****************************************************************************/ | ||||
|  | ||||
| <template> | ||||
| <div class="c-inspector__saved-styles c-inspect-styles"> | ||||
|     <div class="c-inspect-styles__header"> | ||||
|         Saved Styles | ||||
|     </div> | ||||
|     <div class="c-inspect-styles__content"> | ||||
|         <div class="c-inspect-styles__saved-style"> | ||||
|             <div | ||||
|                 v-for="(savedStyle, index) in savedStyles" | ||||
|                 :key="index" | ||||
|                 class="c-inspect-styles__saved-style" | ||||
|             > | ||||
|                 <saved-style-selector | ||||
|                     class="c-inspect-styles__selector" | ||||
|                     :is-editing="isEditing" | ||||
|                     :saved-style="savedStyle" | ||||
|                 /> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import SavedStyleSelector from './SavedStyleSelector.vue'; | ||||
|  | ||||
| export default { | ||||
|     name: 'SavedStylesView', | ||||
|     components: { | ||||
|         SavedStyleSelector | ||||
|     }, | ||||
|     inject: [ | ||||
|         'openmct', | ||||
|         'selection', | ||||
|         'stylesManager' | ||||
|     ], | ||||
|     data() { | ||||
|         return { | ||||
|             isEditing: this.openmct.editor.isEditing(), | ||||
|             savedStyles: undefined | ||||
|         }; | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.openmct.editor.on('isEditing', this.setIsEditing); | ||||
|         this.stylesManager.on('stylesUpdated', this.setStyles); | ||||
|         this.stylesManager.on('limitReached', this.showLimitReachedDialog); | ||||
|         this.stylesManager.on('persistError', this.showPersistErrorDialog); | ||||
|  | ||||
|         this.loadStyles(); | ||||
|     }, | ||||
|     destroyed() { | ||||
|         this.openmct.editor.off('isEditing', this.setIsEditing); | ||||
|         this.stylesManager.off('stylesUpdated', this.setStyles); | ||||
|         this.stylesManager.off('limitReached', this.showLimitReachedDialog); | ||||
|         this.stylesManager.off('persistError', this.showPersistErrorDialog); | ||||
|     }, | ||||
|     methods: { | ||||
|         setIsEditing(isEditing) { | ||||
|             this.isEditing = isEditing; | ||||
|         }, | ||||
|         loadStyles() { | ||||
|             const styles = this.stylesManager.load(); | ||||
|  | ||||
|             this.setStyles(styles); | ||||
|         }, | ||||
|         setStyles(styles) { | ||||
|             this.savedStyles = styles; | ||||
|         }, | ||||
|         showLimitReachedDialog(limit) { | ||||
|             const message = ` | ||||
|                 You have reached the limit on the number of saved styles. | ||||
|                 Please delete one or more saved styles and try again. | ||||
|             `; | ||||
|  | ||||
|             let dialog = this.openmct.overlays.dialog({ | ||||
|                 title: 'Saved Styles Limit', | ||||
|                 iconClass: 'alert', | ||||
|                 message: message, | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         label: 'OK', | ||||
|                         callback: () => { | ||||
|                             dialog.dismiss(); | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             }); | ||||
|         }, | ||||
|         showPersistErrorDialog() { | ||||
|             const message = ` | ||||
|                 Problem encountered saving styles. | ||||
|                 Try again or delete one or more styles before trying again. | ||||
|             `; | ||||
|             let dialog = this.openmct.overlays.dialog({ | ||||
|                 title: 'Error Saving Style', | ||||
|                 iconClass: 'error', | ||||
|                 message: message, | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         label: 'OK', | ||||
|                         callback: () => { | ||||
|                             dialog.dismiss(); | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| </script> | ||||
| @@ -29,7 +29,7 @@ import StylesView from '../../plugins/condition/components/inspector/StylesView. | ||||
| import Vue from 'vue'; | ||||
|  | ||||
| export default { | ||||
|     inject: ['openmct'], | ||||
|     inject: ['openmct', 'stylesManager'], | ||||
|     data() { | ||||
|         return { | ||||
|             selection: [] | ||||
| @@ -56,7 +56,8 @@ export default { | ||||
|                 this.component = new Vue({ | ||||
|                     provide: { | ||||
|                         openmct: this.openmct, | ||||
|                         selection: selection | ||||
|                         selection: selection, | ||||
|                         stylesManager: this.stylesManager | ||||
|                     }, | ||||
|                     el: viewContainer, | ||||
|                     components: { | ||||
|   | ||||
							
								
								
									
										111
									
								
								src/ui/inspector/StylesManager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/ui/inspector/StylesManager.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| import EventEmitter from 'EventEmitter'; | ||||
|  | ||||
| const LOCAL_STORAGE_KEY = 'mct-saved-styles'; | ||||
| const LIMIT = 20; | ||||
| const STYLE_PROPERTIES = [ | ||||
|     'backgroundColor', 'border', 'color' | ||||
| ]; | ||||
|  | ||||
| /** | ||||
|  * @typedef {Object} Style | ||||
|  * @property {*} property | ||||
|  */ | ||||
| class StylesManager extends EventEmitter { | ||||
|     load() { | ||||
|         let styles = window.localStorage.getItem(LOCAL_STORAGE_KEY); | ||||
|         styles = styles ? JSON.parse(styles) : []; | ||||
|  | ||||
|         return styles; | ||||
|     } | ||||
|  | ||||
|     save(style) { | ||||
|         const normalizedStyle = this.normalizeStyle(style); | ||||
|         const styles = this.load(); | ||||
|  | ||||
|         if (!this.isSaveLimitReached(styles)) { | ||||
|             styles.unshift(normalizedStyle); | ||||
|             const persistSucceeded = this.persist(styles); | ||||
|  | ||||
|             if (persistSucceeded) { | ||||
|                 this.emit('stylesUpdated', styles); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     normalizeStyle(style) { | ||||
|         const normalizedStyle = style; | ||||
|  | ||||
|         // strip border styling down to border color only | ||||
|         style.border = style.border.substring(style.border.lastIndexOf('#')); | ||||
|  | ||||
|         return normalizedStyle; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     isSaveLimitReached(styles) { | ||||
|         if (styles.length >= LIMIT) { | ||||
|             this.emit('limitReached'); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     isExistingStyle(style, styles) { | ||||
|         return styles.some(existingStyle => this.isEqual(style, existingStyle)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     persist(styles) { | ||||
|         try { | ||||
|             window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(styles)); | ||||
|  | ||||
|             return true; | ||||
|         } catch { | ||||
|             this.emit('persistError'); | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     isEqual(style1, style2) { | ||||
|         const keys = Object.keys(Object.assign({}, style1, style2)); | ||||
|         const different = keys.some(key => (!style1[key] && style2[key]) | ||||
|             || (style1[key] && !style2[key]) | ||||
|             || (style1[key] !== style2[key]) | ||||
|         ); | ||||
|  | ||||
|         return !different; | ||||
|     } | ||||
|  | ||||
|     select(style) { | ||||
|         this.emit('styleSelected', style); | ||||
|     } | ||||
|  | ||||
|     delete(style) { | ||||
|         const styles = this.load(); | ||||
|         const remainingStyles = styles.filter(keep => !this.isEqual(keep, style)); | ||||
|  | ||||
|         const persistSuccess = this.persist(remainingStyles); | ||||
|         if (persistSuccess) { | ||||
|             this.emit('stylesUpdated', remainingStyles); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| const stylesManager = new StylesManager(); | ||||
| // breaks on adding listener later | ||||
| // Object.freeze(stylesManager); | ||||
|  | ||||
| export default stylesManager; | ||||
| @@ -162,6 +162,11 @@ | ||||
|     } | ||||
| } | ||||
|  | ||||
| /********************************************* INSPECTOR PROPERTIES TAB */ | ||||
| .c-saved-style { | ||||
|     cursor: default; | ||||
| } | ||||
|  | ||||
| /********************************************* LEGACY SUPPORT */ | ||||
| .c-inspector { | ||||
|     // FilterField.vue | ||||
|   | ||||
		Reference in New Issue
	
	Block a user