Compare commits
	
		
			6 Commits
		
	
	
		
			couch-batc
			...
			notebook-s
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 0a820aa869 | ||
|   | 7c92b6d206 | ||
|   | 395a1caeec | ||
|   | 339b315642 | ||
|   | 601d59d6bd | ||
|   | c6e2d5a363 | 
| @@ -78,7 +78,7 @@ | ||||
|             ] | ||||
|         })); | ||||
|         openmct.install(openmct.plugins.SummaryWidget()); | ||||
|         openmct.install(openmct.plugins.Notebook()); | ||||
|         openmct.install(openmct.plugins.NotebookSVC()); | ||||
|         openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay'])); | ||||
|         openmct.install(openmct.plugins.ObjectMigration()); | ||||
|         openmct.install(openmct.plugins.ClearData(['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'])); | ||||
|   | ||||
							
								
								
									
										31
									
								
								src/plugins/notebook-svc/components/embed.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/plugins/notebook-svc/components/embed.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| <template> | ||||
|         <div class="c-ne__embed"> | ||||
|         <div class="c-ne__embed__snap-thumb" | ||||
|             v-if="embed.snapshot"> | ||||
|             <img v-bind:src="embed.snapshot.src"> | ||||
|         </div> | ||||
|         <div class="c-ne__embed__info"> | ||||
|             <div class="c-ne__embed__name"> | ||||
|                 <a class="c-ne__embed__link" | ||||
|                     :href="objectLink" | ||||
|                     :class="embed.cssClass"> | ||||
|                     {{embed.name}} | ||||
|                 </a> | ||||
|                 <a class="c-ne__embed__context-available icon-arrow-down"></a> | ||||
|             </div> | ||||
|             <div class="c-ne__embed__time" v-if="embed.snapshot"> | ||||
|                     {{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}} | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import objectLinkMixin from '../../../ui/mixins/object-link'; | ||||
|  | ||||
| export default { | ||||
|     inject: ['openmct', 'formatTime'], | ||||
|     props: ['embed'], | ||||
|     mixins: [objectLinkMixin] | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										63
									
								
								src/plugins/notebook-svc/components/entry.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/plugins/notebook-svc/components/entry.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| <template> | ||||
|         <li class="c-notebook__entry c-ne has-local-controls" | ||||
|             @dragover.prevent | ||||
|             @drop.prevent="onTreeItemDrop"> | ||||
|             <div class="c-ne__time-and-content"> | ||||
|                 <div class="c-ne__time"> | ||||
|                     <span>{{formatTime(entry.createdOn, 'YYYY-MM-DD')}}</span> | ||||
|                     <span>{{formatTime(entry.createdOn, 'HH:mm:ss')}}</span> | ||||
|                 </div> | ||||
|                 <div class="c-ne__content"> | ||||
|                     <div class="c-ne__text c-input-inline" | ||||
|                         contenteditable="true" | ||||
|                         ref="contenteditable" | ||||
|                         @blur="updateEntry" | ||||
|                         v-html="entry.text"> | ||||
|                     </div> | ||||
|                     <div class="c-ne__embeds"> | ||||
|                         <notebook-embed | ||||
|                             v-for="embed in entry.embeds" | ||||
|                             :key="embed.id" | ||||
|                             :embed="embed" | ||||
|                             :objectPath="embed.objectPath"> | ||||
|                         </notebook-embed> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <div class="c-ne__local-controls--hidden"> | ||||
|                 <button class="c-click-icon c-click-icon--major icon-trash" | ||||
|                     title="Delete this entry" | ||||
|                     @click="deleteEntry"> | ||||
|                 </button> | ||||
|             </div> | ||||
|         </li> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import NotebookEmbed from './embed.vue'; | ||||
|  | ||||
| export default { | ||||
|     inject: ['formatTime'], | ||||
|     props: ['entry'], | ||||
|     components: { | ||||
|         NotebookEmbed | ||||
|     }, | ||||
|     methods: { | ||||
|         updateEntry(event) { | ||||
|             this.$emit('update-entry', this.entry.id, event.target.innerText); | ||||
|         }, | ||||
|         deleteEntry() { | ||||
|             this.$emit('delete-entry', this.entry.id); | ||||
|         }, | ||||
|         onTreeItemDrop(event) { | ||||
|             this.$emit('drop-embed', this.entry.id, event); | ||||
|         } | ||||
|     }, | ||||
|     mounted() { | ||||
|         if (!this.entry.text && !this.entry.embeds.length) { | ||||
|             this.$refs.contenteditable.focus(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										198
									
								
								src/plugins/notebook-svc/components/notebook.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								src/plugins/notebook-svc/components/notebook.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,198 @@ | ||||
| <template> | ||||
|     <div class="c-notebook" | ||||
|         @dragover.stop | ||||
|         @drop.stop> | ||||
|         <div class="c-notebook__head"> | ||||
|             <search class="c-notebook__search" | ||||
|                     :value="searchValue" | ||||
|                     @input="searchEntries" | ||||
|                     @clear="searchEntries"> | ||||
|             </search> | ||||
|  | ||||
|             <div class="c-notebook__controls "> | ||||
|                 <select class="c-notebook__controls__time" v-model="timeFrame"> | ||||
|                     <option value="0" :selected="timeFrame==='0'">Show all</option> | ||||
|                     <option value="1" :selected="timeFrame==='1'">Last hour</option> | ||||
|                     <option value="8" :selected="timeFrame==='8'">Last 8 hours</option> | ||||
|                     <option value="24" :selected="timeFrame==='24'">Last 24 hours</option> | ||||
|                 </select> | ||||
|                 <select class="c-notebook__controls__time" v-model="sortOrder"> | ||||
|                     <option value="newest" :selected="sortOrder === 'newest'">Newest first</option> | ||||
|                     <option value="oldest" :selected="sortOrder === 'oldest'">Oldest first</option> | ||||
|                 </select> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="c-notebook__drag-area icon-plus" | ||||
|             @click="newEntry"> | ||||
|             <span class="c-notebook__drag-area__label">To start a new entry, click here or drag and drop any object</span> | ||||
|         </div> | ||||
|         <div class="c-notebook__entries"> | ||||
|             <ul> | ||||
|                 <entry | ||||
|                     v-for="entry in entries" | ||||
|                     :key="entry.id" | ||||
|                     :entry="entry" | ||||
|                     @update-entry="persistEntry" | ||||
|                     @delete-entry="deleteEntry" | ||||
|                     @drop-embed="addEmbed"> | ||||
|                 </entry> | ||||
|             </ul> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <style lang="scss"> | ||||
|  | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| import Search from '../../../ui/components/search.vue'; | ||||
| import Entry from './entry.vue'; | ||||
| import Moment from 'moment'; | ||||
| import searchVue from '../../../ui/components/search.vue'; | ||||
|  | ||||
| function formatTime(unixTime, format) { | ||||
|     return Moment(unixTime).format(format) | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     inject: ['openmct', 'providedDomainObject'], | ||||
|     components: { | ||||
|         Search, | ||||
|         Entry | ||||
|     }, | ||||
|     provide: { | ||||
|         formatTime | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             domainObject: this.providedDomainObject, | ||||
|             timeFrame: '0', | ||||
|             searchValue: '', | ||||
|             sortOrder: this.providedDomainObject.configuration.sortOrder | ||||
|         } | ||||
|     }, | ||||
|     methods: { | ||||
|         searchEntries(value) { | ||||
|             this.searchValue = value; | ||||
|         }, | ||||
|         updateDomainObject(domainObject) { | ||||
|             this.domainObject = domainObject; | ||||
|         }, | ||||
|         newEntry() { | ||||
|             this.searchValue = ''; | ||||
|  | ||||
|             let date = Date.now(), | ||||
|                 entry = {'id': 'entry-' + date, 'createdOn': date, 'embeds':[]}, | ||||
|                 entries = this.domainObject.entries, | ||||
|                 lastEntry = entries[entries.length - 1]; | ||||
|              | ||||
|             if (lastEntry && !lastEntry.text && !lastEntry.embeds.length) { | ||||
|                 let lastEntryComponent = this.$children.find(entryComponent => { | ||||
|                     if (entryComponent.entry) { | ||||
|                         return entryComponent.entry.id === lastEntry.id; | ||||
|                     } | ||||
|                 }); | ||||
|                  | ||||
|                 lastEntryComponent.$refs.contenteditable.focus(); | ||||
|             } else { | ||||
|                 entries.push(entry); | ||||
|  | ||||
|                 this.openmct.objects.mutate(this.domainObject, 'entries', entries); | ||||
|             } | ||||
|         }, | ||||
|         findEntry(entryId) { | ||||
|             return this.domainObject.entries.findIndex(entry => { | ||||
|                 return entry.id === entryId; | ||||
|             }) | ||||
|         }, | ||||
|         persistEntry(entryId, text) { | ||||
|             let entryPos = this.findEntry(entryId); | ||||
|  | ||||
|             this.openmct.objects.mutate(this.domainObject, `entries[${entryPos}].text`, text); | ||||
|         }, | ||||
|         deleteEntry(entryId) { | ||||
|             let entryPos = this.findEntry(entryId), | ||||
|                 entries = this.domainObject.entries; | ||||
|              | ||||
|             if (entryPos !== -1) { | ||||
|                 let dialog = this.openmct.overlays.dialog({ | ||||
|                     iconClass: 'alert', | ||||
|                     message: 'This action will permanently delete this entry. Do you wish to continue?', | ||||
|                     buttons: [ | ||||
|                         { | ||||
|                             label: "Ok", | ||||
|                             emphasis: true, | ||||
|                             callback: () => { | ||||
|                                 entries.splice(entryPos, 1); | ||||
|                                 this.openmct.objects.mutate(this.domainObject, 'entries', entries); | ||||
|                                 dialog.dismiss(); | ||||
|                             } | ||||
|                         }, | ||||
|                         { | ||||
|                             label: "Cancel", | ||||
|                             callback: () => { | ||||
|                                 dialog.dismiss(); | ||||
|                             } | ||||
|                         } | ||||
|                     ] | ||||
|                 }); | ||||
|             } | ||||
|         }, | ||||
|         applySearch(entries) { | ||||
|             return entries.filter((entry) => { | ||||
|                 if (entry.text.includes(this.searchValue)) { | ||||
|                     return entry; | ||||
|                 } | ||||
|             }); | ||||
|         }, | ||||
|         addEmbed(entryId, event) { | ||||
|             var data = event.dataTransfer.getData('openmct/domain-object-path'); | ||||
|  | ||||
|             if (data) { | ||||
|                 var objectPath = JSON.parse(data), | ||||
|                     domainObject = objectPath[0], | ||||
|                     domainObjectKey = domainObject.identifier.key, | ||||
|                     domainObjectType = this.openmct.types.get(domainObject.type), | ||||
|                     cssClass = domainObjectType && domainObjectType.definition ?  | ||||
|                         domainObjectType.definition.cssClass : 'icon-object-unknown', | ||||
|                     entryPos = this.findEntry(entryId), | ||||
|                     currentEntryEmbeds = this.domainObject.entries[entryPos].embeds, | ||||
|                     newEmbed = { | ||||
|                         id: '' + Date.now(), | ||||
|                         domainObject: domainObject, | ||||
|                         objectPath: objectPath, | ||||
|                         type: domainObjectKey, | ||||
|                         cssClass: cssClass, | ||||
|                         name: domainObject.name, | ||||
|                         snapshot: '' | ||||
|                     }; | ||||
|      | ||||
|                 currentEntryEmbeds.push(newEmbed); | ||||
|                 this.openmct.objects.mutate(this.domainObject, 'entries[' + entryPos + '].embeds', currentEntryEmbeds); | ||||
|             } | ||||
|         }, | ||||
|         onDrop() { | ||||
|             console.log('droped'); | ||||
|         } | ||||
|     }, | ||||
|     computed: { | ||||
|         entries() { | ||||
|             let entries = [...this.domainObject.entries]; | ||||
|              | ||||
|             if (this.searchValue !== '') { | ||||
|                 entries = this.applySearch(entries); | ||||
|             } | ||||
|  | ||||
|             if (this.sortOrder === 'newest') { | ||||
|                 return entries.reverse(); | ||||
|             } else { | ||||
|                 return entries; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     mounted() { | ||||
|         this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject); | ||||
|     } | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										67
									
								
								src/plugins/notebook-svc/notebook-view-provider.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/plugins/notebook-svc/notebook-view-provider.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| define([ | ||||
|     'vue', | ||||
|     './components/notebook.vue' | ||||
| ], function ( | ||||
|     Vue, | ||||
|     Notebook | ||||
| ) { | ||||
|     function NotebookViewProvider(openmct) { | ||||
|         return { | ||||
|             key: 'notebook', | ||||
|             name: 'Notebook', | ||||
|             cssClass: 'icon-notebook', | ||||
|             canView: function (domainObject) { | ||||
|                 return domainObject.type === 'notebook'; | ||||
|             }, | ||||
|             view: function (domainObject) { | ||||
|                 let component; | ||||
|  | ||||
|                 return { | ||||
|                     show: function (element) { | ||||
|                         component =  new Vue({ | ||||
|                             components: { | ||||
|                                 Notebook: Notebook.default | ||||
|                             }, | ||||
|                             provide: { | ||||
|                                 openmct, | ||||
|                                 providedDomainObject: domainObject | ||||
|                             }, | ||||
|                             el: element, | ||||
|                             template: '<notebook></notebook>' | ||||
|                         }); | ||||
|                     }, | ||||
|                     destroy: function (element) { | ||||
|                         component.$destroy(); | ||||
|                         component = undefined; | ||||
|                     } | ||||
|                 }; | ||||
|             }, | ||||
|             priority: function () { | ||||
|                 return 1; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|     return NotebookViewProvider; | ||||
| }); | ||||
							
								
								
									
										47
									
								
								src/plugins/notebook-svc/plugin.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/plugins/notebook-svc/plugin.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| define([ | ||||
|     './notebook-view-provider' | ||||
| ], function ( | ||||
|     NotebookViewProvider | ||||
| ) { | ||||
|     return function plugin() { | ||||
|  | ||||
|         return function install(openmct) { | ||||
|             openmct.objectViews.addProvider(new NotebookViewProvider(openmct)); | ||||
|  | ||||
|             openmct.types.addType('notebook', { | ||||
|                 name: "Notebook SVC", | ||||
|                 creatable: true, | ||||
|                 description: "Create and save timestamped notes with embedded object snapshots.", | ||||
|                 cssClass: 'icon-notebook', | ||||
|                 initialize: function (domainObject) { | ||||
|                     domainObject.configuration = { | ||||
|                         sortOrder: 'oldest' | ||||
|                     }; | ||||
|                     domainObject.entries = []; | ||||
|                 } | ||||
|             }); | ||||
|         }; | ||||
|     }; | ||||
| }); | ||||
| @@ -35,7 +35,7 @@ define([ | ||||
|  | ||||
|             installed = true; | ||||
|  | ||||
|             openmct.legacyRegistry.register('notebook', { | ||||
|             openmct.legacyRegistry.register('notebook-old', { | ||||
|                 name: 'Notebook Plugin', | ||||
|                 extensions: { | ||||
|                     types: [ | ||||
| @@ -73,10 +73,10 @@ define([ | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             openmct.legacyRegistry.enable('notebook'); | ||||
|             openmct.legacyRegistry.enable('notebook-old'); | ||||
|  | ||||
|             openmct.objectViews.addProvider({ | ||||
|                 key: 'notebook-vue', | ||||
|                 key: 'notebook-old', | ||||
|                 name: 'Notebook View', | ||||
|                 cssClass: 'icon-notebook', | ||||
|                 canView: function (domainObject) { | ||||
|   | ||||
| @@ -41,6 +41,7 @@ define([ | ||||
|     './flexibleLayout/plugin', | ||||
|     './tabs/plugin', | ||||
|     './LADTable/plugin', | ||||
|     './notebook-svc/plugin', | ||||
|     './filters/plugin', | ||||
|     './objectMigration/plugin', | ||||
|     './goToOriginalAction/plugin', | ||||
| @@ -66,6 +67,7 @@ define([ | ||||
|     FlexibleLayout, | ||||
|     Tabs, | ||||
|     LADTable, | ||||
|     NotebookSVC, | ||||
|     Filters, | ||||
|     ObjectMigration, | ||||
|     GoToOriginalAction, | ||||
| @@ -159,12 +161,13 @@ define([ | ||||
|     plugins.SummaryWidget = SummaryWidget; | ||||
|     plugins.TelemetryMean = TelemetryMean; | ||||
|     plugins.URLIndicator = URLIndicatorPlugin; | ||||
|     plugins.Notebook = Notebook; | ||||
|     // plugins.Notebook = Notebook; | ||||
|     plugins.DisplayLayout = DisplayLayoutPlugin.default; | ||||
|     plugins.FolderView = FolderView; | ||||
|     plugins.Tabs = Tabs; | ||||
|     plugins.FlexibleLayout = FlexibleLayout; | ||||
|     plugins.LADTable = LADTable; | ||||
|     plugins.NotebookSVC = NotebookSVC; | ||||
|     plugins.Filters = Filters; | ||||
|     plugins.ObjectMigration = ObjectMigration.default; | ||||
|     plugins.GoToOriginalAction = GoToOriginalAction.default; | ||||
|   | ||||
| @@ -111,7 +111,7 @@ export default { | ||||
|                 event.dataTransfer.setData("openmct/composable-domain-object", JSON.stringify(this.domainObject)); | ||||
|             } | ||||
|             // serialize domain object anyway, because some views can drag-and-drop objects without composition  | ||||
|             // (eg. notabook.) | ||||
|             // (eg. notebook.) | ||||
|             event.dataTransfer.setData("openmct/domain-object-path", serializedPath); | ||||
|             event.dataTransfer.setData(`openmct/domain-object/${keyString}`, this.domainObject); | ||||
|         } | ||||
|   | ||||
| @@ -90,7 +90,7 @@ class NotebookSnapshot { | ||||
|         }; | ||||
|  | ||||
|         function validateLocation(newParentObj) { | ||||
|             return newParentObj.model.type === 'notebook'; | ||||
|             return newParentObj.model.type === 'notebook' || newParentObj.model.type === 'notebook-svc'; | ||||
|         } | ||||
|  | ||||
|         return overlayModel; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user