Compare commits
	
		
			2 Commits
		
	
	
		
			custom-col
			...
			new-tree-i
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 55e9cafbef | ||
|   | 8cd91061f7 | 
| @@ -301,7 +301,7 @@ | ||||
|  | ||||
| <script> | ||||
|     import Inspector from '../inspector/Inspector.vue'; | ||||
|     import MctTree from './mct-tree.vue'; | ||||
|     import MctTree from './mct-tree-prototype.vue'; | ||||
|     import ObjectView from '../components/ObjectView.vue'; | ||||
|     import MctTemplate from '../legacy/mct-template.vue'; | ||||
|     import CreateButton from './CreateButton.vue'; | ||||
|   | ||||
							
								
								
									
										374
									
								
								src/ui/layout/mct-tree-prototype.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								src/ui/layout/mct-tree-prototype.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,374 @@ | ||||
| <template> | ||||
|     <div class="c-tree-and-search"> | ||||
|         <div class="c-tree-and-search__search"> | ||||
|             <search class="c-search" ref="shell-search" | ||||
|                 :value="searchValue" | ||||
|                 @input="searchTree" | ||||
|                 @clear="searchTree"> | ||||
|             </search> | ||||
|         </div> | ||||
|  | ||||
|         <!-- loading --> | ||||
|         <div class="c-tree-and-search__loading loading" | ||||
|             v-if="isLoading"></div> | ||||
|         <!-- end loading --> | ||||
|  | ||||
|         <!-- main tree --> | ||||
|         <template v-if="parentNode && parentNode.id !== 'ROOT'"> | ||||
|             <tree-item | ||||
|                 :key="parentNode.id" | ||||
|                 :node="parentNode" | ||||
|                 :isExpanded="true" | ||||
|                 @notExpanded="navigateToParent"> | ||||
|             </tree-item> | ||||
|  | ||||
|             <div style="min-width: 100%; height: 2px; background: rgb(201,201,201);"></div> | ||||
|         </template> | ||||
|  | ||||
|         <ul class="c-tree-and-search__tree c-tree" | ||||
|             v-if="!isLoading" | ||||
|             v-show="!searchValue" | ||||
|             @scroll="scrollPage"> | ||||
|  | ||||
|             <tree-item  | ||||
|                 v-for="treeItem in pagedChildren" | ||||
|                 :key="treeItem.id" | ||||
|                 :node="treeItem" | ||||
|                 @expanded="setParentAndLoadChildren"> | ||||
|             </tree-item> | ||||
|         </ul> | ||||
|         <!-- end main tree --> | ||||
|  | ||||
|         <!-- search tree --> | ||||
|         <ul class="c-tree-and-search__tree c-tree" | ||||
|             v-if="searchValue"> | ||||
|             <tree-item v-for="treeItem in filteredTreeItems" | ||||
|                     :key="treeItem.id" | ||||
|                     :node="treeItem"> | ||||
|             </tree-item> | ||||
|         </ul> | ||||
|         <!-- end search tree --> | ||||
|  | ||||
|         <div class="c-tree-and-search__no-results"  | ||||
|             v-if="(allTreeItems.length === 0) || (searchValue && filteredTreeItems.length === 0)"> | ||||
|             No results found | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <style lang="scss"> | ||||
|     @import "~styles/sass-base"; | ||||
|  | ||||
|     .c-tree-and-search { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         padding-right: $interiorMarginSm; | ||||
|         overflow: auto; | ||||
|  | ||||
|         > * + * { margin-top: $interiorMargin; } | ||||
|  | ||||
|         &__search { | ||||
|             flex: 0 0 auto; | ||||
|         } | ||||
|  | ||||
|         &__loading { | ||||
|             flex: 1 1 auto; | ||||
|         } | ||||
|  | ||||
|         &__no-results { | ||||
|             font-style: italic; | ||||
|             opacity: 0.6; | ||||
|         } | ||||
|  | ||||
|         &__tree { | ||||
|             flex: 1 1 auto; | ||||
|             height: 0; // Chrome 73 overflow bug fix | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .c-tree { | ||||
|         @include userSelectNone(); | ||||
|         overflow-x: hidden; | ||||
|         overflow-y: auto; | ||||
|         padding-right: $interiorMargin; | ||||
|  | ||||
|         li { | ||||
|             position: relative; | ||||
|             &.c-tree__item-h { display: block; } | ||||
|         } | ||||
|  | ||||
|         .c-tree { | ||||
|             margin-left: 15px; | ||||
|         } | ||||
|  | ||||
|         &__item { | ||||
|             $aPad: $interiorMarginSm; | ||||
|             border-radius: $controlCr; | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             cursor: pointer; | ||||
|             line-height: 110%; | ||||
|             padding: $interiorMargin - $aPad; | ||||
|             transition: background 150ms ease; | ||||
|  | ||||
|             > * + * { | ||||
|                 margin-left: $interiorMarginSm; | ||||
|             } | ||||
|  | ||||
|             &:hover { | ||||
|                 background: $colorItemTreeHoverBg; | ||||
|                 .c-tree__item__type-icon:before { | ||||
|                     color: $colorItemTreeIconHover; | ||||
|                 } | ||||
|  | ||||
|                 .c-tree__item__name { | ||||
|                     color: $colorItemTreeHoverFg; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &.is-navigated-object, | ||||
|             &.is-selected { | ||||
|                 background: $colorItemTreeSelectedBg; | ||||
|                 .c-tree__item__type-icon:before { | ||||
|                     color: $colorItemTreeIconHover; | ||||
|                 } | ||||
|  | ||||
|                 .c-tree__item__name { | ||||
|                     color: $colorItemTreeSelectedFg; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &.is-being-edited { | ||||
|                 background: $colorItemTreeEditingBg; | ||||
|                 .c-tree__item__type-icon:before { | ||||
|                     color: $colorItemTreeEditingIcon; | ||||
|                 } | ||||
|  | ||||
|                 .c-tree__item__name { | ||||
|                     color: $colorItemTreeEditingFg; | ||||
|                     font-style: italic; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Object labels in trees | ||||
|             &__label { | ||||
|                 // <a> tag that holds type icon and name. | ||||
|                 // Draggable element. | ||||
|                 /*border-radius: $controlCr; | ||||
|                 display: flex; | ||||
|                 align-items: center; | ||||
|                 flex: 1 1 auto; | ||||
|                 overflow: hidden; | ||||
|                 padding: $aPad; | ||||
|                 white-space: nowrap;*/ | ||||
|             } | ||||
|  | ||||
|             &__name { | ||||
|                // @include ellipsize(); | ||||
|                // display: inline; | ||||
|                 color: $colorItemTreeFg; | ||||
|               //  width: 100%; | ||||
|             } | ||||
|  | ||||
|             &__type-icon { | ||||
|                 // Type icon. Must be an HTML entity to allow inclusion of alias indicator. | ||||
|                // display: block; | ||||
|              //   flex: 0 0 auto; | ||||
|               //  font-size: 1.3em; | ||||
|               //  margin-right: $interiorMarginSm; | ||||
|                 color: $colorItemTreeIcon; | ||||
|               //  width: $treeTypeIconW; | ||||
|             } | ||||
|  | ||||
|             &.is-alias { | ||||
|                 // Object is an alias to an original. | ||||
|                 [class*='__type-icon'] { | ||||
|                     @include isAlias(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             body.mobile & { | ||||
|                 @include button($bg: $colorMobilePaneLeftTreeItemBg, $fg: $colorMobilePaneLeftTreeItemFg); | ||||
|                 height: $mobileTreeItemH; | ||||
|                 margin-bottom: $interiorMarginSm; | ||||
|                 [class*="view-control"] { | ||||
|                     width: ceil($mobileTreeItemH * 0.5); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
|     import treeItem from './tree-item-prototype.vue' | ||||
|     import search from '../components/search.vue'; | ||||
|  | ||||
|     const PAGE_THRESHOLD = 50; | ||||
|  | ||||
|     export default { | ||||
|         inject: ['openmct'], | ||||
|         name: 'mct-tree', | ||||
|         components: { | ||||
|             search, | ||||
|             treeItem | ||||
|         }, | ||||
|         data() { | ||||
|             return { | ||||
|                 searchValue: '', | ||||
|                 allTreeItems: [], | ||||
|                 filteredTreeItems: [], | ||||
|                 isLoading: false, | ||||
|                 currentObjectPath: [], | ||||
|                 parentNode: undefined, | ||||
|                 page: 1 | ||||
|             } | ||||
|         }, | ||||
|         computed: { | ||||
|             pagedChildren() { | ||||
|                 if (this.allTreeItems.length > PAGE_THRESHOLD) { | ||||
|                     let maxIndex = this.page * PAGE_THRESHOLD, | ||||
|                         minIndex = maxIndex - PAGE_THRESHOLD; | ||||
|  | ||||
|                     return this.allTreeItems.slice(minIndex, maxIndex); | ||||
|                 } else { | ||||
|                     return this.allTreeItems; | ||||
|                 } | ||||
|             }, | ||||
|             lastPage() { | ||||
|                 return Math.floor(this.allTreeItems.length / PAGE_THRESHOLD); | ||||
|             } | ||||
|         }, | ||||
|         methods: { | ||||
|             getRootChildren() { | ||||
|                 this.openmct.objects.get('ROOT') | ||||
|                     .then(root => { | ||||
|                         let rootNode = this.buildTreeItems(root); | ||||
|                         this.getAllChildren(rootNode); | ||||
|                     }) | ||||
|             }, | ||||
|             getAllChildren(node) { | ||||
|                 this.isLoading = true; | ||||
|  | ||||
|                 if (this.composition) { | ||||
|                     this.composition.off('add', this.addChild); | ||||
|                     this.composition.off('remove', this.removeChild); | ||||
|                     delete this.composition; | ||||
|                 } | ||||
|  | ||||
|                 this.parentNode = node; | ||||
|                 this.currentObjectPath = this.parentNode.objectPath; | ||||
|                 this.allTreeItems = []; | ||||
|  | ||||
|                 this.composition = this.openmct.composition.get(node.object); | ||||
|                 this.composition.on('add', this.addChild); | ||||
|                 this.composition.on('remove', this.removeChild); | ||||
|                 this.composition.load().then(() => { | ||||
|                     this.isLoading = false; | ||||
|                 }); | ||||
|             }, | ||||
|             buildTreeItems(domainObject) { | ||||
|                 return { | ||||
|                     id: this.openmct.objects.makeKeyString(domainObject.identifier), | ||||
|                     object: domainObject, | ||||
|                     objectPath: [domainObject].concat(this.currentObjectPath), | ||||
|                     navigateToParent: '/browse' | ||||
|                 }; | ||||
|             }, | ||||
|             getFilteredChildren() { | ||||
|                 this.searchService.query(this.searchValue).then(children => { | ||||
|                     this.filteredTreeItems = children.hits.map(child => { | ||||
|                          | ||||
|                         let context = child.object.getCapability('context'), | ||||
|                             object = child.object.useCapability('adapter'), | ||||
|                             objectPath = [], | ||||
|                             navigateToParent; | ||||
|  | ||||
|                         if (context) { | ||||
|                             objectPath = context.getPath().slice(1) | ||||
|                                 .map(oldObject => oldObject.useCapability('adapter')) | ||||
|                                 .reverse(); | ||||
|                             navigateToParent = '/browse/' + objectPath.slice(1) | ||||
|                                 .map((parent) => this.openmct.objects.makeKeyString(parent.identifier)) | ||||
|                                 .join('/'); | ||||
|                         } | ||||
|  | ||||
|                         return { | ||||
|                             id: this.openmct.objects.makeKeyString(object.identifier), | ||||
|                             object, | ||||
|                             objectPath, | ||||
|                             navigateToParent | ||||
|                         } | ||||
|                     }); | ||||
|                 }); | ||||
|             }, | ||||
|             searchTree(value) { | ||||
|                 this.searchValue = value; | ||||
|                  | ||||
|                 if (this.searchValue !== '') { | ||||
|                     this.getFilteredChildren(); | ||||
|                 } | ||||
|             }, | ||||
|             buildPathString(parentPath) { | ||||
|                 return [parentPath, this.parentNode.id].join('/'); | ||||
|             }, | ||||
|             addChild (child) { | ||||
|                 this.allTreeItems.push(this.buildTreeItems(child)); | ||||
|             }, | ||||
|             removeChild(identifier) { | ||||
|                 let removeId = this.openmct.objects.makeKeyString(identifier); | ||||
|                 this.allChildren = this.children | ||||
|                     .filter(c => c.id !== removeId); | ||||
|             }, | ||||
|             navigateToParent(node) { | ||||
|                 let parentDomainObject = node.objectPath[1], | ||||
|                     parentNode = { | ||||
|                     id: this.openmct.objects.makeKeyString(parentDomainObject.identifier), | ||||
|                     object: parentDomainObject, | ||||
|                     objectPath: node.objectPath.slice(1), | ||||
|                     navigateToParent: '/browse' | ||||
|                 } | ||||
|  | ||||
|                 this.getAllChildren(parentNode); | ||||
|             }, | ||||
|             setParentAndLoadChildren(node){ | ||||
|                 this.getAllChildren(node); | ||||
|             }, | ||||
|             nextPage() { | ||||
|                 if (this.page < this.lastPage) { | ||||
|                     this.page += 1; | ||||
|                 } | ||||
|             }, | ||||
|             previousPage() { | ||||
|                 if (this.page >= 1) { | ||||
|                     this.page -= 1; | ||||
|                 } | ||||
|             }, | ||||
|             scrollPage(event) { | ||||
|                 let offsetHeight = event.target.offsetHeight, | ||||
|                     scrollHeight = event.target.scrollHeight, | ||||
|                     scrollTop = event.target.scrollTop, | ||||
|                     changePage = true; | ||||
|  | ||||
|                 if (scrollTop + offsetHeight === scrollHeight) { | ||||
|                     this.scrollLoading = window.setTimeout(() => { | ||||
|                         if (this.page < this.lastPage) { | ||||
|                             this.nextPage(); | ||||
|                             event.target.scrollTop = 1; | ||||
|                         } | ||||
|                     }, 500); | ||||
|                 } else if (scrollTop === 0) { | ||||
|                      this.scrollLoading = window.setTimeout(() => { | ||||
|                         if (this.page > 1) { | ||||
|                             this.previousPage(); | ||||
|                             event.target.scrollTop = offsetHeight - 1; | ||||
|                         } | ||||
|                     }, 500); | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         mounted() { | ||||
|             this.searchService = this.openmct.$injector.get('searchService'); | ||||
|             this.getRootChildren(); | ||||
|         } | ||||
|     } | ||||
| </script> | ||||
							
								
								
									
										94
									
								
								src/ui/layout/tree-item-prototype.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/ui/layout/tree-item-prototype.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| <template> | ||||
|     <li class="c-tree__item-h"> | ||||
|         <div class="c-tree__item" | ||||
|             :class="{ 'is-alias': isAlias, 'is-navigated-object': isNavigated }"> | ||||
|             <view-control class="c-tree__item__view-control" | ||||
|                           :enabled="hasChildren" | ||||
|                           v-model="expanded"> | ||||
|             </view-control> | ||||
|             <object-label :domainObject="node.object" | ||||
|                           :objectPath="node.objectPath" | ||||
|                           :navigateToPath="navigateToPath"> | ||||
|             </object-label> | ||||
|         </div> | ||||
|     </li> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|     import viewControl from '../components/viewControl.vue'; | ||||
|     import ObjectLabel from '../components/ObjectLabel.vue'; | ||||
|  | ||||
|     export default { | ||||
|         name: 'tree-item', | ||||
|         inject: ['openmct'], | ||||
|         props: { | ||||
|             node: Object, | ||||
|             isExpanded: { | ||||
|                 default: false, | ||||
|                 type: Boolean | ||||
|             } | ||||
|         }, | ||||
|         data() { | ||||
|             this.navigateToPath = this.buildPathString(this.node.navigateToParent) | ||||
|             return { | ||||
|                 hasChildren: false, | ||||
|                 isLoading: false, | ||||
|                 loaded: false, | ||||
|                 isNavigated: this.navigateToPath === this.openmct.router.currentLocation.path, | ||||
|                 children: [], | ||||
|                 expanded: this.isExpanded | ||||
|             } | ||||
|         }, | ||||
|         computed: { | ||||
|             isAlias() { | ||||
|                 let parent = this.node.objectPath[1]; | ||||
|                 if (!parent) { | ||||
|                     return false; | ||||
|                 } | ||||
|                 let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier); | ||||
|                 return parentKeyString !== this.node.object.location; | ||||
|             } | ||||
|         }, | ||||
|         watch: { | ||||
|             expanded(isExpanded) { | ||||
|                 if (isExpanded) { | ||||
|                     this.$emit('expanded', this.node); | ||||
|                 } else { | ||||
|                     this.$emit('notExpanded', this.node); | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         mounted() { | ||||
|             this.domainObject = this.node.object; | ||||
|             let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => { | ||||
|                 this.domainObject = newObject; | ||||
|             }); | ||||
|  | ||||
|             this.$once('hook:destroyed', removeListener); | ||||
|             if (this.openmct.composition.get(this.node.object)) { | ||||
|                 this.hasChildren = true; | ||||
|             } | ||||
|  | ||||
|             this.openmct.router.on('change:path', this.highlightIfNavigated); | ||||
|         }, | ||||
|         destroyed() { | ||||
|             this.openmct.router.off('change:path', this.highlightIfNavigated); | ||||
|         }, | ||||
|         methods: { | ||||
|             buildPathString(parentPath) { | ||||
|                 return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/'); | ||||
|             }, | ||||
|             highlightIfNavigated(newPath, oldPath){ | ||||
|                 if (newPath === this.navigateToPath) { | ||||
|                     this.isNavigated = true; | ||||
|                 } else if (oldPath === this.navigateToPath) { | ||||
|                     this.isNavigated = false; | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         components: { | ||||
|             viewControl, | ||||
|             ObjectLabel | ||||
|         } | ||||
|     } | ||||
| </script> | ||||
		Reference in New Issue
	
	Block a user