Compare commits
	
		
			8 Commits
		
	
	
		
			performanc
			...
			tree-pagin
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9015028f81 | ||
|   | 38d78990da | ||
|   | e0d2c85740 | ||
|   | 29ab9bdf02 | ||
|   | 0b433ccb50 | ||
|   | e2ecd106f6 | ||
|   | 7debe89f8b | ||
|   | a396f50acd | 
| @@ -29,6 +29,7 @@ define([ | ||||
|     "./res/templates/search.html", | ||||
|     "./res/templates/search-menu.html", | ||||
|     "raw-loader!./src/services/GenericSearchWorker.js", | ||||
|     "raw-loader!./src/services/BareBonesSearchWorker.js", | ||||
|     'legacyRegistry' | ||||
| ], function ( | ||||
|     SearchController, | ||||
| @@ -39,6 +40,7 @@ define([ | ||||
|     searchTemplate, | ||||
|     searchMenuTemplate, | ||||
|     searchWorkerText, | ||||
|     BareBonesSearchWorkerText, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|  | ||||
| @@ -115,6 +117,10 @@ define([ | ||||
|                 } | ||||
|             ], | ||||
|             "workers": [ | ||||
|                 { | ||||
|                     "key": "bareBonesSearchWorker", | ||||
|                     "scriptText": BareBonesSearchWorkerText | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "genericSearchWorker", | ||||
|                     "scriptText": searchWorkerText | ||||
|   | ||||
							
								
								
									
										80
									
								
								platform/search/src/services/BareBonesSearchWorker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								platform/search/src/services/BareBonesSearchWorker.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2018, 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /*global self*/ | ||||
|  | ||||
| /** | ||||
|  * Module defining GenericSearchWorker. Created by shale on 07/21/2015. | ||||
|  */ | ||||
| (function () { | ||||
|  | ||||
|     // An array of objects composed of domain object IDs and models | ||||
|     // {id: domainObject's ID, model: domainObject's model} | ||||
|     var indexedItems = []; | ||||
|  | ||||
|     function indexItem(id, model) { | ||||
|         indexedItems.push({ | ||||
|             id: id, | ||||
|             name: model.name.toLowerCase() | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets search results from the indexedItems based on provided search | ||||
|      *   input. Returns matching results from indexedItems | ||||
|      * | ||||
|      * @param data An object which contains: | ||||
|      *           * input: The original string which we are searching with | ||||
|      *           * maxResults: The maximum number of search results desired | ||||
|      *           * queryId: an id identifying this query, will be returned. | ||||
|      */ | ||||
|     function search(data) { | ||||
|         // This results dictionary will have domain object ID keys which | ||||
|         // point to the value the domain object's score. | ||||
|         var results, | ||||
|             input = data.input.trim().toLowerCase(), | ||||
|             message = { | ||||
|                 request: 'search', | ||||
|                 results: {}, | ||||
|                 total: 0, | ||||
|                 queryId: data.queryId | ||||
|             }; | ||||
|  | ||||
|         results = indexedItems.filter((indexedItem) => { | ||||
|             return indexedItem.name.includes(input); | ||||
|         }); | ||||
|  | ||||
|         message.total = results.length; | ||||
|         message.results = results | ||||
|             .slice(0, data.maxResults); | ||||
|  | ||||
|         return message; | ||||
|     } | ||||
|  | ||||
|     self.onmessage = function (event) { | ||||
|         if (event.data.request === 'index') { | ||||
|             indexItem(event.data.id, event.data.model); | ||||
|         } else if (event.data.request === 'search') { | ||||
|             self.postMessage(search(event.data)); | ||||
|         } | ||||
|     }; | ||||
| }()); | ||||
| @@ -58,6 +58,8 @@ define([ | ||||
|  | ||||
|         this.pendingQueries = {}; | ||||
|  | ||||
|         this.useBareBones = true; | ||||
|  | ||||
|         this.worker = this.startWorker(workerService); | ||||
|         this.indexOnMutation(topic); | ||||
|  | ||||
| @@ -101,8 +103,14 @@ define([ | ||||
|      * @returns worker the created search worker. | ||||
|      */ | ||||
|     GenericSearchProvider.prototype.startWorker = function (workerService) { | ||||
|         var worker = workerService.run('genericSearchWorker'), | ||||
|             provider = this; | ||||
|         var provider = this, | ||||
|             worker; | ||||
|  | ||||
|         if (this.useBareBones) { | ||||
|             worker = workerService.run('bareBonesSearchWorker'); | ||||
|         } else { | ||||
|             worker = workerService.run('genericSearchWorker'); | ||||
|         } | ||||
|  | ||||
|         worker.addEventListener('message', function (messageEvent) { | ||||
|             provider.onWorkerMessage(messageEvent); | ||||
| @@ -242,18 +250,34 @@ define([ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         var pendingQuery = this.pendingQueries[event.data.queryId], | ||||
|         var pendingQuery, | ||||
|             modelResults; | ||||
|  | ||||
|         if (this.useBareBones) { | ||||
|             pendingQuery = this.pendingQueries[event.data.queryId]; | ||||
|             modelResults = { | ||||
|                 total: event.data.total | ||||
|             }; | ||||
|  | ||||
|         modelResults.hits = event.data.results.map(function (hit) { | ||||
|             return { | ||||
|                 id: hit.item.id, | ||||
|                 model: hit.item.model, | ||||
|                 score: hit.matchCount | ||||
|             modelResults.hits = event.data.results.map(function (hit) { | ||||
|                 return { | ||||
|                     id: hit.id | ||||
|                 }; | ||||
|             }); | ||||
|         } else { | ||||
|             pendingQuery = this.pendingQueries[event.data.queryId]; | ||||
|             modelResults = { | ||||
|                 total: event.data.total | ||||
|             }; | ||||
|         }); | ||||
|  | ||||
|             modelResults.hits = event.data.results.map(function (hit) { | ||||
|                 return { | ||||
|                     id: hit.item.id, | ||||
|                     model: hit.item.model, | ||||
|                     score: hit.matchCount | ||||
|                 }; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         pendingQuery.resolve(modelResults); | ||||
|         delete this.pendingQueries[event.data.queryId]; | ||||
|   | ||||
| @@ -144,6 +144,8 @@ | ||||
|         message.results = results | ||||
|             .slice(0, data.maxResults); | ||||
|  | ||||
|         console.log(message); | ||||
|  | ||||
|         return message; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -18,10 +18,47 @@ | ||||
|                     <span class="c-tree__item__label">Loading...</span> | ||||
|                 </div> | ||||
|             </li> | ||||
|             <tree-item v-for="child in children" | ||||
|                        :key="child.id" | ||||
|                        :node="child"> | ||||
|             </tree-item> | ||||
|  | ||||
|             <template v-if="children.length"> | ||||
|  | ||||
|                 <template v-if="children.length > page_threshold"> | ||||
|                     <li v-show="!showSearchComponent" | ||||
|                         @click="toggleSearchComponent" | ||||
|                         class="c-tree__item-h" | ||||
|                         style="font-size: 0.5em;"> | ||||
|                         <div class="c-tree__item icon-magnify"> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                      | ||||
|                     <li v-show="showSearchComponent" | ||||
|                         class="c-tree__item-h" | ||||
|                         style="font-size: 0.7em"> | ||||
|                         <div class="c-tree__item"> | ||||
|                             <a class="c-tree__item__label c-object-label"> | ||||
|                                 <search  | ||||
|                                     :value="searchValue" | ||||
|                                     @input="searchChildren" | ||||
|                                     @clear="searchChildren" | ||||
|                                     style="min-width: 80%;"> | ||||
|                                 </search> | ||||
|                                 <div style="padding: 2px; margin-left: 10%;" | ||||
|                                     class="icon-x" | ||||
|                                     @click="toggleSearchComponent"> | ||||
|                                 </div> | ||||
|                             </a> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                 </template> | ||||
|                  | ||||
|                 <div :style="style" | ||||
|                      @scroll="scrollPage" | ||||
|                      ref="scrollParent"> | ||||
|                     <tree-item v-for="child in filteredAndPagedChildren" | ||||
|                             :key="child.id" | ||||
|                             :node="child"> | ||||
|                     </tree-item> | ||||
|                 </div> | ||||
|             </template> | ||||
|         </ul> | ||||
|     </li> | ||||
| </template> | ||||
| @@ -29,6 +66,9 @@ | ||||
| <script> | ||||
|     import viewControl from '../components/viewControl.vue'; | ||||
|     import ObjectLabel from '../components/ObjectLabel.vue'; | ||||
|     import Search from '../components/search.vue'; | ||||
|  | ||||
|     const PAGE_THRESHOLD = 50; | ||||
|  | ||||
|     export default { | ||||
|         name: 'tree-item', | ||||
| @@ -44,7 +84,13 @@ | ||||
|                 loaded: false, | ||||
|                 isNavigated: this.navigateToPath === this.openmct.router.currentLocation.path, | ||||
|                 children: [], | ||||
|                 expanded: false | ||||
|                 expanded: false, | ||||
|                 page: 1, | ||||
|                 page_threshold: PAGE_THRESHOLD, | ||||
|                 searchValue: '', | ||||
|                 filteredChildren: [], | ||||
|                 scrollTop: 0, | ||||
|                 showSearchComponent: false | ||||
|             } | ||||
|         }, | ||||
|         computed: { | ||||
| @@ -55,6 +101,44 @@ | ||||
|                 } | ||||
|                 let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier); | ||||
|                 return parentKeyString !== this.node.object.location; | ||||
|             }, | ||||
|             filteredAndPagedChildren() { | ||||
|                 if (this.searchValue) { | ||||
|                     this.filteredChildren = this.children.filter((child) => { | ||||
|                         let searchLowCase = this.searchValue.toLowerCase(), | ||||
|                             nameLowerCase = child.object.name.toLowerCase(); | ||||
|  | ||||
|                         return nameLowerCase.includes(searchLowCase); | ||||
|                     }) | ||||
|                 } else { | ||||
|                     this.filteredChildren = this.children; | ||||
|                 } | ||||
|  | ||||
|                 if (this.filteredChildren.length > this.page_threshold) { | ||||
|                     let maxIndex = this.page * this.page_threshold, | ||||
|                         minIndex = maxIndex - this.page_threshold; | ||||
|  | ||||
|                     return this.filteredChildren.slice(minIndex, maxIndex); | ||||
|                 } else { | ||||
|                     return this.filteredChildren; | ||||
|                 } | ||||
|             }, | ||||
|             lastPage() { | ||||
|                 return Math.floor(this.filteredChildren.length / this.page_threshold); | ||||
|             }, | ||||
|             style() { | ||||
|                 let numChildren = this.filteredChildren.length; | ||||
|  | ||||
|                 if (!this.$refs.scrollParent || numChildren === 0) { | ||||
|                     return {}; | ||||
|                 } | ||||
|                  | ||||
|                 if ((numChildren * 20) > this.$refs.scrollParent.offsetHeight) { | ||||
|                     return { | ||||
|                         "overflow-y": 'scroll', | ||||
|                         "max-height": (this.page_threshold * 10) + 'px' | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         mounted() { | ||||
| @@ -97,6 +181,11 @@ | ||||
|                     this.composition.load().then(this.finishLoading); | ||||
|                     this.isLoading = true; | ||||
|                 } | ||||
|  | ||||
|                 if (!isExpanded) { | ||||
|                     this.page = 1; | ||||
|                     this.showSearchComponent = false; | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         methods: { | ||||
| @@ -126,11 +215,53 @@ | ||||
|                 } else if (oldPath === this.navigateToPath) { | ||||
|                     this.isNavigated = false; | ||||
|                 } | ||||
|             }, | ||||
|             nextPage() { | ||||
|                 if (this.page < this.lastPage) { | ||||
|                     this.page += 1; | ||||
|                 } | ||||
|             }, | ||||
|             previousPage() { | ||||
|                 if (this.page >= 1) { | ||||
|                     this.page -= 1; | ||||
|                 } | ||||
|             }, | ||||
|             searchChildren(input) { | ||||
|                 this.searchValue = input; | ||||
|                 this.page = 1; | ||||
|             }, | ||||
|             scrollPage(event) { | ||||
|                 let offsetHeight = event.target.offsetHeight, | ||||
|                     scrollTop = event.target.scrollTop, | ||||
|                     changePage = true; | ||||
|  | ||||
|                 window.clearTimeout(this.scrollLoading); | ||||
|  | ||||
|                 if (scrollTop > this.scrollTop && scrollTop > offsetHeight) { | ||||
|                     this.scrollLoading = window.setTimeout(() => { | ||||
|                         if (this.page < this.lastPage) { | ||||
|                             this.nextPage(); | ||||
|                             event.target.scrollTop = 1; | ||||
|                         } | ||||
|                     }, 250); | ||||
|                 } else if (this.scrollTop <= this.scrollTop && scrollTop <= 0) { | ||||
|                      this.scrollLoading = window.setTimeout(() => { | ||||
|                         if (this.page > 1) { | ||||
|                             this.previousPage(); | ||||
|                             event.target.scrollTop = offsetHeight - 1; | ||||
|                         } | ||||
|                     }, 250); | ||||
|                 } | ||||
|                 this.scrollTop = scrollTop; | ||||
|             }, | ||||
|             toggleSearchComponent() { | ||||
|                 this.showSearchComponent = !this.showSearchComponent; | ||||
|             } | ||||
|         }, | ||||
|         components: { | ||||
|             viewControl, | ||||
|             ObjectLabel | ||||
|             ObjectLabel, | ||||
|             Search | ||||
|         } | ||||
|     } | ||||
| </script> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user