Compare commits
	
		
			89 Commits
		
	
	
		
			joel/plot-
			...
			proposed-v
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 3b86e02ed3 | ||
|   | b4dc50295c | ||
|   | 382dde300a | ||
|   | 02aa08a3ef | ||
|   | c95d9c7956 | ||
|   | b1b8df4d87 | ||
|   | bd3c6665fb | ||
|   | 10e90519c0 | ||
|   | d341a8be97 | ||
|   | 8c439d8109 | ||
|   | 9c88b7ce1d | ||
|   | 2463e4d59f | ||
|   | d73c505bea | ||
|   | 831ecc59d9 | ||
|   | 1de26d3c5d | ||
|   | 11409ce509 | ||
|   | 93872ce074 | ||
|   | 8861644f2d | ||
|   | d4948f771b | ||
|   | 8295a0bed1 | ||
|   | 0656a298da | ||
|   | fe2ce91d50 | ||
|   | 14f30b2489 | ||
|   | 62d90a8114 | ||
|   | 87682607a5 | ||
|   | 7bf265b478 | ||
|   | 1d31fe8d02 | ||
|   | bfdbc71e40 | ||
|   | 1147f3aa47 | ||
|   | 719f9f45e8 | ||
|   | 95ef70a24c | ||
|   | d5aa998b4c | ||
|   | 7890fcae69 | ||
|   | 18843cee48 | ||
|   | 1879c122c7 | ||
|   | d7ddb96c4e | ||
|   | b55668426d | ||
|   | 5b656faa9d | ||
|   | 8d2c489fa9 | ||
|   | 4366b0870d | ||
|   | 47a543beb7 | ||
|   | 06f87c1472 | ||
|   | c9c41cdcc8 | ||
|   | 14a56ea17e | ||
|   | b2e7db71cc | ||
|   | d51e6bfd92 | ||
|   | d475d767d5 | ||
|   | a63e053399 | ||
|   | 370b515c23 | ||
|   | 4a50f325cb | ||
|   | dbe6a4efc1 | ||
|   | 13920d8802 | ||
|   | b6a8c514aa | ||
|   | e4a4704baa | ||
|   | be0029e59a | ||
|   | 9cb273ef0a | ||
|   | eec9b1cf4c | ||
|   | 1f96e84542 | ||
|   | c289a27305 | ||
|   | c944080790 | ||
|   | 96316de6e4 | ||
|   | 2240a87ddc | ||
|   | d891affe48 | ||
|   | 21a618d1ce | ||
|   | 5de7a96ccc | ||
|   | 09a833f524 | ||
|   | 580a4e52b5 | ||
|   | 9c4e17bfab | ||
|   | d3e5d95d6b | ||
|   | c70793ac2d | ||
|   | a6ef1d3423 | ||
|   | 4ca2f51d5e | ||
|   | 86ac80ddbd | ||
|   | 0525ba6b0b | ||
|   | a79e958ffc | ||
|   | 03cb0ccb57 | ||
|   | 7205faa6bb | ||
|   | 136f2ae785 | ||
|   | a07e2fb8e5 | ||
|   | 55b531bdeb | ||
|   | 7ece5897e8 | ||
|   | a29c7a6eab | ||
|   | c4fec1af6a | ||
|   | a6996df3df | ||
|   | 0c660238f2 | ||
|   | b73b824e55 | ||
|   | 1954d98628 | ||
|   | 7aa034ce23 | ||
|   | 385dc5d298 | 
							
								
								
									
										285
									
								
								API.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								API.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,285 @@ | ||||
| # Open MCT API | ||||
|  | ||||
| The Open MCT framework public api can be utilized by building the application | ||||
| (`gulp install`) and then copying the file from `dist/main.js` to your | ||||
| directory of choice. | ||||
|  | ||||
| Open MCT supports AMD, CommonJS, and loading via a script tag; it's easy to use | ||||
| in your project. The [`openmct`]{@link module:openmct} module is exported | ||||
| via AMD and CommonJS, and is also exposed as `openmct` in the global scope | ||||
| if loaded via a script tag. | ||||
|  | ||||
| ## Overview | ||||
|  | ||||
| Open MCT's goal is to allow you to browse, create, edit, and visualize all of | ||||
| the domain knowledge you need on a daily basis. | ||||
|  | ||||
| To do this, the main building block provided by Open MCT is the _domain object_. | ||||
| The temperature sensor on the starboard solar panel, | ||||
| an overlay plot comparing the results of all temperature sensor, | ||||
| the command dictionary for a spacecraft, | ||||
| the individual commands in that dictionary, your "my documents" folder: | ||||
| All of these things are domain objects. | ||||
|  | ||||
| Domain objects have Types, so a specific instrument temperature sensor is a | ||||
| "Telemetry Point," and turning on a drill for a certain duration of time is | ||||
| an "Activity".  Types allow you to form an ontology of knowledge and provide | ||||
| an abstraction for grouping, visualizing, and interpreting data. | ||||
|  | ||||
| And then we have Views. Views allow you to visualize domain objects. Views can | ||||
| apply to specific domain objects; they may also apply to certain types of | ||||
| domain objects, or they may apply to everything.  Views are simply a method | ||||
| of visualizing domain objects. | ||||
|  | ||||
| Regions allow you to specify what views are displayed for specific types of | ||||
| domain objects in response to different user actions. For instance, you may | ||||
| want to display a different view while editing, or you may want to update the | ||||
| toolbar display when objects are selected.  Regions allow you to map views to | ||||
| specific user actions. | ||||
|  | ||||
| Domain objects can be mutated and persisted, developers can create custom | ||||
| actions and apply them to domain objects, and many more things can be done. | ||||
| For more information, read on! | ||||
|  | ||||
| ## Running Open MCT | ||||
|  | ||||
| Once the [`openmct`](@link module:openmct) module has been loaded, you can | ||||
| simply invoke [`start`]{@link module:openmct.MCT#start} to run Open MCT: | ||||
|  | ||||
|  | ||||
| ``` | ||||
| openmct.start(); | ||||
| ``` | ||||
|  | ||||
| Generally, however, you will want to configure Open MCT by adding plugins | ||||
| before starting it. It is important to install plugins and configure Open MCT | ||||
| _before_ calling [`start`]{@link module:openmct.MCT#start}; Open MCT is not | ||||
| designed to be reconfigured once started. | ||||
|  | ||||
| ## Configuring Open MCT | ||||
|  | ||||
| The [`openmct`]{@link module:openmct} module (more specifically, the | ||||
| [`MCT`]{@link module:openmct.MCT} class, of which `openmct` is an instance) | ||||
| exposes a variety of methods to allow the application to be configured, | ||||
| extended, and customized before running. | ||||
|  | ||||
| Short examples follow; see the linked documentation for further details. | ||||
|  | ||||
| ### Adding Domain Object Types | ||||
|  | ||||
| Custom types may be registered via | ||||
| [`openmct.types`]{@link module:openmct.MCT#types}: | ||||
|  | ||||
| ``` | ||||
| openmct.types.addType('my-type', new openmct.Type({ | ||||
|     label: "My Type", | ||||
|     description: "This is a type that I added!" | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| ### Adding Views | ||||
|  | ||||
| Custom views may be registered based on the region in the application | ||||
| where they should appear: | ||||
|  | ||||
| * [`openmct.mainViews`]{@link module:openmct.MCT#mainViews} is a registry | ||||
|   of views of domain objects which should appear in the main viewing area. | ||||
| * [`openmct.inspectors`]{@link module:openmct.MCT#inspectors} is a registry | ||||
|   of views of domain objects and/or active selections, which should appear in | ||||
|   the Inspector. | ||||
| * [`openmct.toolbars`]{@link module:openmct.MCT#toolbars} is a registry | ||||
|   of views of domain objects and/or active selections, which should appear in | ||||
|   the toolbar area while editing. | ||||
| * [`openmct.indicators`]{@link module:openmct.MCT#inspectors} is a registry | ||||
|   of views which should appear in the status area of the application. | ||||
|  | ||||
| Example: | ||||
|  | ||||
| ``` | ||||
| openmct.mainViews.addProvider({ | ||||
|     canView: function (domainObject) { | ||||
|         return domainObject.type === 'my-type'; | ||||
|     }, | ||||
|     view: function (domainObject) { | ||||
|         return new MyView(domainObject); | ||||
|     } | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| ### Adding a Root-level Object | ||||
|  | ||||
| In many cases, you'd like a certain object (or a certain hierarchy of | ||||
| objects) to be accessible from the top level of the application (the | ||||
| tree on the left-hand side of Open MCT.) It is typical to expose a telemetry | ||||
| dictionary as a hierarchy of telemetry-providing domain objects in this | ||||
| fashion. | ||||
|  | ||||
| To do so, use the [`addRoot`]{@link module:openmct.ObjectAPI#addRoot} method | ||||
| of the [object API]{@link module:openmct.ObjectAPI}: | ||||
|  | ||||
| ``` | ||||
| openmct.objects.addRoot({ | ||||
|     identifier: { key: "my-key", namespace: "my-namespace" } | ||||
|     name: "My Root-level Object", | ||||
|     type: "my-type" | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| You can also remove this root-level object via its identifier: | ||||
|  | ||||
| ``` | ||||
| openmct.objects.removeRoot({ key: "my-key", namespace: "my-namespace" }); | ||||
| ``` | ||||
|  | ||||
| ### Adding Composition Providers | ||||
|  | ||||
| The "composition" of a domain object is the list of objects it contains, | ||||
| as shown (for example) in the tree for browsing. Open MCT provides a | ||||
| default solution for composition, but there may be cases where you want | ||||
| to provide the composition of a certain object (or type of object) dynamically. | ||||
| For instance, you may want to populate a hierarchy under a custom root-level | ||||
| object based on the contents of a telemetry dictionary. | ||||
| To do this, you can add a new CompositionProvider: | ||||
|  | ||||
| ``` | ||||
| openmct.composition.addProvider({ | ||||
|     appliesTo: function (domainObject) { | ||||
|         return domainObject.type === 'my-type'; | ||||
|     }, | ||||
|     load: function (domainObject) { | ||||
|         return Promise.resolve(myDomainObjects); | ||||
|     } | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| ### Adding Telemetry Providers | ||||
|  | ||||
| When connecting to a new telemetry source, you will want to register a new | ||||
| [telemetry provider]{@link module:openmct.TelemetryAPI~TelemetryProvider} | ||||
| with the [telemetry API]{@link module:openmct.TelemetryAPI#addProvider}: | ||||
|  | ||||
| ``` | ||||
| openmct.telemetry.addProvider({ | ||||
|     canProvideTelemetry: function (domainObject) { | ||||
|         return domainObject.type === 'my-type'; | ||||
|     }, | ||||
|     properties: function (domainObject) { | ||||
|         return [ | ||||
|             { key: 'value', name: "Temperature", units: "degC" }, | ||||
|             { key: 'time', name: "UTC" } | ||||
|         ]; | ||||
|     }, | ||||
|     request: function (domainObject, options) { | ||||
|         var telemetryId = domainObject.myTelemetryId; | ||||
|         return myAdapter.request(telemetryId, options.start, options.end); | ||||
|     }, | ||||
|     subscribe: function (domainObject, callback) { | ||||
|         var telemetryId = domainObject.myTelemetryId; | ||||
|         myAdapter.subscribe(telemetryId, callback); | ||||
|         return myAdapter.unsubscribe.bind(myAdapter, telemetryId, callback); | ||||
|     } | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| The implementations for `request` and `subscribe` can vary depending on the | ||||
| nature of the endpoint which will provide telemetry. In the example above, | ||||
| it is assumed that `myAdapter` contains the specific implementations | ||||
| (HTTP requests, WebSocket connections, etc.) associated with some telemetry | ||||
| source. | ||||
|  | ||||
| ## Using Open MCT | ||||
|  | ||||
| When implementing new features, it is useful and sometimes necessary to | ||||
| utilize functionality exposed by Open MCT. | ||||
|  | ||||
| ### Retrieving Composition | ||||
|  | ||||
| To limit which objects are loaded at any given time, the composition of | ||||
| a domain object must be requested asynchronously: | ||||
|  | ||||
| ``` | ||||
| openmct.composition(myObject).load().then(function (childObjects) { | ||||
|     childObjects.forEach(doSomething); | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| ### Support Common Gestures | ||||
|  | ||||
| Custom views may also want to support common gestures using the | ||||
| [gesture API]{@link module:openmct.GestureAPI}. For instance, to make | ||||
| a view (or part of a view) selectable: | ||||
|  | ||||
| ``` | ||||
| openmct.gestures.selectable(myHtmlElement, myDomainObject); | ||||
| ``` | ||||
|  | ||||
| ### Working with Domain Objects | ||||
|  | ||||
| The [object API]{@link module:openmct.ObjectAPI} provides useful methods | ||||
| for working with domain objects. | ||||
|  | ||||
| To make changes to a domain object, use the | ||||
| [`mutate`]{@link module:openmct.ObjectAPI#mutate} method: | ||||
|  | ||||
| ``` | ||||
| openmct.objects.mutate(myDomainObject, "name", "New name!"); | ||||
| ``` | ||||
|  | ||||
| Making modifications in this fashion allows other usages of the domain | ||||
| object to remain up to date using the | ||||
| [`observe`]{@link module:openmct.ObjectAPI#observe} method: | ||||
|  | ||||
| ``` | ||||
| openmct.objects.observe(myDomainObject, "name", function (newName) { | ||||
|     myLabel.textContent = newName; | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| ### Using Telemetry | ||||
|  | ||||
| Very often in Open MCT, you wish to work with telemetry data (for instance, | ||||
| to display it in a custom visualization.) | ||||
|  | ||||
|  | ||||
| ### Synchronizing with the Time Conductor | ||||
|  | ||||
| Views which wish to remain synchronized with the state of Open MCT's | ||||
| time conductor should utilize | ||||
| [`openmct.conductor`]{@link module:openmct.TimeConductor}: | ||||
|  | ||||
| ``` | ||||
| openmct.conductor.on('bounds', function (newBounds) { | ||||
|     requestTelemetry(newBounds.start, newBounds.end).then(displayTelemetry); | ||||
| }); | ||||
| ``` | ||||
|  | ||||
| ## Plugins | ||||
|  | ||||
| While you can register new features with Open MCT directly, it is generally | ||||
| more useful to package these as a plugin. A plugin is a function that takes | ||||
| [`openmct`]{@link module:openmct} as an argument, and performs configuration | ||||
| upon `openmct` when invoked. | ||||
|  | ||||
| ### Installing Plugins | ||||
|  | ||||
| To install plugins, use the [`install`]{@link module:openmct.MCT#install} | ||||
| method: | ||||
|  | ||||
| ``` | ||||
| openmct.install(myPlugin); | ||||
| ``` | ||||
|  | ||||
| The plugin will be invoked to configure Open MCT before it is started. | ||||
|  | ||||
| ### Writing Plugins | ||||
|  | ||||
| Plugins configure Open MCT, and should utilize the | ||||
| [`openmct`]{@link module:openmct} module to do so, as summarized above in | ||||
| "Configuring Open MCT" and "Using Open MCT" above. | ||||
|  | ||||
| ### Distributing Plugins | ||||
|  | ||||
| Hosting or downloading plugins is outside of the scope of this documentation. | ||||
| We recommend distributing plugins as UMD modules which export a single | ||||
| function. | ||||
|  | ||||
| @@ -18,6 +18,9 @@ | ||||
|     "node-uuid": "^1.4.7", | ||||
|     "comma-separated-values": "^3.6.4", | ||||
|     "FileSaver.js": "^0.0.2", | ||||
|     "zepto": "^1.1.6" | ||||
|     "zepto": "^1.1.6", | ||||
|     "eventemitter3": "^1.2.0", | ||||
|     "lodash": "3.10.1", | ||||
|     "almond": "~0.3.2" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										65
									
								
								composition-test.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								composition-test.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
|   <meta http-equiv="Content-type" content="text/html; charset=utf-8"> | ||||
|   <title>Implementing a composition provider</title> | ||||
|   <script src="dist/main.js"></script> | ||||
| </head> | ||||
| <body> | ||||
| <script> | ||||
|  | ||||
|     var widgetParts = ['foo', 'bar', 'baz', 'bing', 'frobnak'] | ||||
|  | ||||
|     function fabricateName() { | ||||
|         return [ | ||||
|             widgetParts[Math.floor(Math.random() * widgetParts.length)], | ||||
|             widgetParts[Math.floor(Math.random() * widgetParts.length)], | ||||
|             Math.floor(Math.random() * 1000) | ||||
|         ].join('_'); | ||||
|     } | ||||
|  | ||||
|     MCT.type('example.widget-factory', new MCT.Type({ | ||||
|         metadata: { | ||||
|             label: "Widget Factory", | ||||
|             glyph: "s", | ||||
|             description: "A factory for making widgets" | ||||
|         }, | ||||
|         initialize: function (object) { | ||||
|             object.widgetCount = 5; | ||||
|             object.composition = []; | ||||
|         }, | ||||
|         creatable: true, | ||||
|         form: [ | ||||
|             { | ||||
|                 name: "Widget Count", | ||||
|                 control: "textfield", | ||||
|                 key: "widgetCount", | ||||
|                 property: "widgetCount", | ||||
|                 required: true | ||||
|             } | ||||
|         ] | ||||
|     })); | ||||
|  | ||||
|     MCT.Composition.addProvider({ | ||||
|         appliesTo: function (domainObject) { | ||||
|             return domainObject.type === 'example.widget-factory'; | ||||
|         }, | ||||
|         load: function (domainObject) { | ||||
|             var widgets = []; | ||||
|             while (widgets.length < domainObject.widgetCount) { | ||||
|                 widgets.push({ | ||||
|                     name: fabricateName(), | ||||
|                     key: { | ||||
|                         namespace: 'widget-factory', | ||||
|                         identifier: '' + widgets.length | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|             return Promise.resolve(widgets); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     MCT.run(); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										144
									
								
								custom-view-react.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								custom-view-react.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
|   <meta http-equiv="Content-type" content="text/html; charset=utf-8"> | ||||
|   <title>Implementing a Custom Type and View </title> | ||||
|   <script src="dist/main.js"></script> | ||||
|   <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js"></script> | ||||
|       <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js"></script> | ||||
|       <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script> | ||||
| </head> | ||||
| <body> | ||||
| <script type="text/babel"> | ||||
|  | ||||
|     // First, we're going to create the Todo List type, so that users can create | ||||
|     // todo lists. | ||||
|  | ||||
|     MCT.type('example.todo', new MCT.Type({ | ||||
|         metadata: { | ||||
|             label: "To-Do List", | ||||
|             glyph: "2", | ||||
|             description: "A list of things that need to be done." | ||||
|         }, | ||||
|         initialize: function (object) { | ||||
|             object.tasks = [ | ||||
|                 { description: "This is a task." } | ||||
|             ]; | ||||
|         }, | ||||
|         creatable: true | ||||
|     })); | ||||
|  | ||||
|     /* | ||||
|     Refresh the page, and you should be able to create new Todo Lists. | ||||
|     unfortunately, when you navigate to a Todo list, you see a blank page. let's | ||||
|     fix that by adding a main view for that todo list. | ||||
|  | ||||
|     If you're wondering why this is commented out, well, it's because we'll | ||||
|     write a new version later. | ||||
|     */ | ||||
|  | ||||
|     var Task = React.createClass({ | ||||
|       render: function() { | ||||
|         return ( | ||||
|             <li> | ||||
|                 <input type="checkbox" | ||||
|                        checked={this.props.checked}/> | ||||
|                 <span>{this.props.description}</span> | ||||
|             </li> | ||||
|         ); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     var TaskList = React.createClass({ | ||||
|         render: function () { | ||||
|             var taskNodes = this.props.tasks.map(function(task) { | ||||
|                 return ( | ||||
|                     <Task checked={task.checked} | ||||
|                           description={task.description}/> | ||||
|                 ); | ||||
|             }); | ||||
|             return ( | ||||
|               <ul> | ||||
|                 {taskNodes} | ||||
|               </ul> | ||||
|             ); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     MCT.view(MCT.regions.main, { | ||||
|         canView: function (domainObject) { | ||||
|             return domainObject.type === 'example.todo'; | ||||
|         }, | ||||
|         view: function (domainObject) { | ||||
|             var mutableObject = MCT.Objects.getMutable(domainObject); | ||||
|  | ||||
|             return { | ||||
|                 show: function (container) { | ||||
|                     ReactDOM.render( | ||||
|                         <TaskList tasks={domainObject.tasks}/>, | ||||
|                         container | ||||
|                     ); | ||||
|                     mutableObject.on('tasks', function (tasks) { | ||||
|                         ReactDOM.render( | ||||
|                             <TaskList tasks={tasks}/>, | ||||
|                             container | ||||
|                         ); | ||||
|                     }); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     /* | ||||
|      Refresh the page and you should see a todo list with checkboxes!  Now let's | ||||
|      Allow you to add tasks by mutating the object.  We'll add a toolbar view to | ||||
|      do this. | ||||
|     */ | ||||
|  | ||||
|     var TaskToolbar = React.createClass({ | ||||
|         render: function () { | ||||
|             return ( | ||||
|                 <button onClick={this.props.addTask}>Add Task</button> | ||||
|             ); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     MCT.view(MCT.regions.toolbar, { | ||||
|         canView: function (domainObject) { | ||||
|             return domainObject.type === 'example.todo'; | ||||
|         }, | ||||
|         view: function (domainObject) { | ||||
|             var mutableObject = MCT.Objects.getMutable(domainObject); | ||||
|  | ||||
|             function addTask(event) { | ||||
|                 var description = prompt('Task description'); | ||||
|                 var tasks = mutableObject.get('tasks'); | ||||
|                 tasks.push({ | ||||
|                     description: description, | ||||
|                     complete: false | ||||
|                 }); | ||||
|                 mutableObject.set('tasks', tasks); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 show: function (container) { | ||||
|                     ReactDOM.render( | ||||
|                         <TaskToolbar addTask={addTask}/>, | ||||
|                         container | ||||
|                     ); | ||||
|                 }, | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     /* | ||||
|      Refresh the page, edit the todo list, and you'll have a button that allows | ||||
|      you to add tasks!  Unfortunately, new tasks don't show in the list.  Why? | ||||
|      Well, if your view should update on mutation, you need to set up the correct | ||||
|      listeners.  Let's update the TodoView we made earlier: | ||||
|     */ | ||||
|  | ||||
|     MCT.run(); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										160
									
								
								custom-view.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								custom-view.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
|   <meta http-equiv="Content-type" content="text/html; charset=utf-8"> | ||||
|   <title>Implementing a Custom Type and View </title> | ||||
|   <script src="dist/main.js"></script> | ||||
| </head> | ||||
| <body> | ||||
| <script> | ||||
|  | ||||
|     // First, we're going to create the Todo List type, so that users can create | ||||
|     // todo lists. | ||||
|  | ||||
|     MCT.type('example.todo', new MCT.Type({ | ||||
|         metadata: { | ||||
|             label: "To-Do List", | ||||
|             glyph: "2", | ||||
|             description: "A list of things that need to be done." | ||||
|         }, | ||||
|         initialize: function (object) { | ||||
|             object.tasks = [ | ||||
|                 { description: "This is a task." } | ||||
|             ]; | ||||
|         }, | ||||
|         creatable: true | ||||
|     })); | ||||
|  | ||||
|     /* | ||||
|     Refresh the page, and you should be able to create new Todo Lists. | ||||
|     unfortunately, when you navigate to a Todo list, you see a blank page. let's | ||||
|     fix that by adding a main view for that todo list. | ||||
|  | ||||
|     If you're wondering why this is commented out, well, it's because we'll | ||||
|     write a new version later. | ||||
|     */ | ||||
|  | ||||
|     // MCT.view(MCT.regions.main, { | ||||
|     //     canView: function (domainObject) { | ||||
|     //         return domainObject.type === 'example.todo'; | ||||
|     //     }, | ||||
|     //     view: function (domainObject) { | ||||
|     //         function renderTask(task) { | ||||
|     //             return [ | ||||
|     //                 '<li>', | ||||
|     //                 '<input type="checkbox"' + (task.complete ? ' checked="true"' : '') + '>', | ||||
|     //                 '<span>' + task.description + '</span>', | ||||
|     //                 '</li>' | ||||
|     //             ].join(''); | ||||
|     //         }; | ||||
|     // | ||||
|     //         function renderTaskList() { | ||||
|     //             return [ | ||||
|     //                 '<ul>', | ||||
|     //                 domainObject.tasks.map(renderTask).join(''), | ||||
|     //                 '</ul>' | ||||
|     //             ].join(''); | ||||
|     //         }; | ||||
|     // | ||||
|     //         return { | ||||
|     //             show: function (container) { | ||||
|     //                 container.innerHTML = renderTaskList(); | ||||
|     //             } | ||||
|     //         }; | ||||
|     //     } | ||||
|     // }); | ||||
|  | ||||
|     /* | ||||
|      Refresh the page and you should see a todo list with checkboxes!  Now let's | ||||
|      Allow you to add tasks by mutating the object.  We'll add a toolbar view to | ||||
|      do this. | ||||
|     */ | ||||
|  | ||||
|     MCT.view(MCT.regions.toolbar, { | ||||
|         canView: function (domainObject) { | ||||
|             return domainObject.type === 'example.todo'; | ||||
|         }, | ||||
|         view: function (domainObject) { | ||||
|             var mutableObject = MCT.Objects.getMutable(domainObject); | ||||
|  | ||||
|             function addTask(event) { | ||||
|                 var description = prompt('Task description'); | ||||
|                 var tasks = mutableObject.get('tasks'); | ||||
|                 tasks.push({ | ||||
|                     description: description, | ||||
|                     complete: false | ||||
|                 }); | ||||
|                 mutableObject.set('tasks', tasks); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 show: function (container) { | ||||
|                     container.addEventListener('click', addTask); | ||||
|                     container.innerHTML = '<button>Add Task</button>'; | ||||
|                 }, | ||||
|                 destroy: function (container) { | ||||
|                     container.removeEventListener('click', addTask); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     /* | ||||
|      Refresh the page, edit the todo list, and you'll have a button that allows | ||||
|      you to add tasks!  Unfortunately, new tasks don't show in the list.  Why? | ||||
|      Well, if your view should update on mutation, you need to set up the correct | ||||
|      listeners.  Let's update the TodoView we made earlier: | ||||
|     */ | ||||
|  | ||||
|     MCT.view(MCT.regions.main, { | ||||
|         canView: function(domainObject) { | ||||
|             return domainObject.type === 'example.todo' | ||||
|         }, | ||||
|         view: function (domainObject) { | ||||
|  | ||||
|             var mutableObject = MCT.Objects.getMutable(domainObject); | ||||
|  | ||||
|             function renderTask(task) { | ||||
|                 return [ | ||||
|                     '<li>', | ||||
|                     '<input type="checkbox"' + (task.complete ? ' checked="true"' : '') + '>', | ||||
|                     '<span>' + task.description + '</span>', | ||||
|                     '</li>' | ||||
|                 ].join(''); | ||||
|             } | ||||
|  | ||||
|             function renderTaskList(tasks) { | ||||
|                 return [ | ||||
|                     '<ul>', | ||||
|                     tasks.map(renderTask).join(''), | ||||
|                     '</ul>' | ||||
|                 ].join(''); | ||||
|             } | ||||
|  | ||||
|             function onCheckboxChange(event) { | ||||
|                 var checkbox = event.target; | ||||
|                 var taskEl = checkbox.parentNode; | ||||
|                 var taskList = taskEl.parentNode; | ||||
|                 var taskIndex = [].slice.apply(taskList.children).indexOf(taskEl); | ||||
|                 mutableObject.set('tasks[' + taskIndex + '].complete', checkbox.checked); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 show: function (container) { | ||||
|                     container.innerHTML = renderTaskList(domainObject.tasks); | ||||
|                     mutableObject.on('tasks', function (tasks) { | ||||
|                         container.innerHTML = renderTaskList(tasks); | ||||
|                     }); | ||||
|                     container.addEventListener('change', onCheckboxChange); | ||||
|                 }, | ||||
|                 destroy: function () { | ||||
|                     mutableObject.stopListening(); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     MCT.run(); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
| @@ -36,7 +36,7 @@ define([ | ||||
|     legacyRegistry | ||||
| ) { | ||||
|     "use strict"; | ||||
|     legacyRegistry.register("example/notifications", { | ||||
|     legacyRegistry.register("example/msl-adapter", { | ||||
|         "name" : "Mars Science Laboratory Data Adapter", | ||||
|         "extensions" : { | ||||
|         "types": [ | ||||
|   | ||||
							
								
								
									
										53
									
								
								gulpfile.js
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								gulpfile.js
									
									
									
									
									
								
							| @@ -21,40 +21,33 @@ | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /*global require,__dirname*/ | ||||
|  | ||||
| var gulp = require('gulp'), | ||||
|     requirejsOptimize = require('gulp-requirejs-optimize'), | ||||
|     sourcemaps = require('gulp-sourcemaps'), | ||||
|     rename = require('gulp-rename'), | ||||
|     sass = require('gulp-sass'), | ||||
|     bourbon = require('node-bourbon'), | ||||
|     jshint = require('gulp-jshint'), | ||||
|     jscs = require('gulp-jscs'), | ||||
|     replace = require('gulp-replace-task'), | ||||
|     karma = require('karma'), | ||||
|     path = require('path'), | ||||
|     fs = require('fs'), | ||||
|     git = require('git-rev-sync'), | ||||
|     moment = require('moment'), | ||||
|     merge = require('merge-stream'), | ||||
|     project = require('./package.json'), | ||||
|     _ = require('lodash'), | ||||
|     paths = { | ||||
|         main: 'main.js', | ||||
|         dist: 'dist', | ||||
|         assets: 'dist/assets', | ||||
|         scss: ['./platform/**/*.scss', './example/**/*.scss'], | ||||
|         assets: [ | ||||
|             './{example,platform}/**/*.{css,css.map,png,svg,ico,woff,eot,ttf}' | ||||
|         ], | ||||
|         scripts: [ 'main.js', 'platform/**/*.js', 'src/**/*.js' ], | ||||
|         specs: [ 'platform/**/*Spec.js', 'src/**/*Spec.js' ], | ||||
|         static: [ | ||||
|             'index.html', | ||||
|             'platform/**/*', | ||||
|             'example/**/*', | ||||
|             'bower_components/**/*' | ||||
|         ] | ||||
|     }, | ||||
|     options = { | ||||
|         requirejsOptimize: { | ||||
|             name: paths.main.replace(/\.js$/, ''), | ||||
|             name: 'bower_components/almond/almond.js', | ||||
|             include: paths.main.replace('.js', ''), | ||||
|             wrap: { | ||||
|                 startFile: "src/start.frag", | ||||
|                 endFile: "src/end.frag" | ||||
|             }, | ||||
|             mainConfigFile: paths.main, | ||||
|             wrapShim: true | ||||
|         }, | ||||
| @@ -63,7 +56,6 @@ var gulp = require('gulp'), | ||||
|             singleRun: true | ||||
|         }, | ||||
|         sass: { | ||||
|             includePaths: bourbon.includePaths, | ||||
|             sourceComments: true | ||||
|         }, | ||||
|         replace: { | ||||
| @@ -77,6 +69,8 @@ var gulp = require('gulp'), | ||||
|     }; | ||||
|  | ||||
| gulp.task('scripts', function () { | ||||
|     var requirejsOptimize = require('gulp-requirejs-optimize'); | ||||
|     var replace = require('gulp-replace-task'); | ||||
|     return gulp.src(paths.main) | ||||
|         .pipe(sourcemaps.init()) | ||||
|         .pipe(requirejsOptimize(options.requirejsOptimize)) | ||||
| @@ -86,10 +80,16 @@ gulp.task('scripts', function () { | ||||
| }); | ||||
|  | ||||
| gulp.task('test', function (done) { | ||||
|     var karma = require('karma'); | ||||
|     new karma.Server(options.karma, done).start(); | ||||
| }); | ||||
|  | ||||
| gulp.task('stylesheets', function () { | ||||
|     var sass = require('gulp-sass'); | ||||
|     var rename = require('gulp-rename'); | ||||
|     var bourbon = require('node-bourbon'); | ||||
|     options.sass.includePaths = bourbon.includePaths; | ||||
|  | ||||
|     return gulp.src(paths.scss, {base: '.'}) | ||||
|         .pipe(sourcemaps.init()) | ||||
|         .pipe(sass(options.sass).on('error', sass.logError)) | ||||
| @@ -103,6 +103,9 @@ gulp.task('stylesheets', function () { | ||||
| }); | ||||
|  | ||||
| gulp.task('lint', function () { | ||||
|     var jshint = require('gulp-jshint'); | ||||
|     var merge = require('merge-stream'); | ||||
|  | ||||
|     var nonspecs = paths.specs.map(function (glob) { | ||||
|             return "!" + glob; | ||||
|         }), | ||||
| @@ -117,6 +120,8 @@ gulp.task('lint', function () { | ||||
| }); | ||||
|  | ||||
| gulp.task('checkstyle', function () { | ||||
|     var jscs = require('gulp-jscs'); | ||||
|  | ||||
|     return gulp.src(paths.scripts) | ||||
|         .pipe(jscs()) | ||||
|         .pipe(jscs.reporter()) | ||||
| @@ -124,18 +129,20 @@ gulp.task('checkstyle', function () { | ||||
| }); | ||||
|  | ||||
| gulp.task('fixstyle', function () { | ||||
|     var jscs = require('gulp-jscs'); | ||||
|  | ||||
|     return gulp.src(paths.scripts, { base: '.' }) | ||||
|         .pipe(jscs({ fix: true })) | ||||
|         .pipe(gulp.dest('.')); | ||||
| }); | ||||
|  | ||||
| gulp.task('static', ['stylesheets'], function () { | ||||
|     return gulp.src(paths.static, { base: '.' }) | ||||
| gulp.task('assets', ['stylesheets'], function () { | ||||
|     return gulp.src(paths.assets) | ||||
|         .pipe(gulp.dest(paths.dist)); | ||||
| }); | ||||
|  | ||||
| gulp.task('watch', function () { | ||||
|     gulp.watch(paths.scss, ['stylesheets']); | ||||
|     return gulp.watch(paths.scss, ['stylesheets', 'assets']); | ||||
| }); | ||||
|  | ||||
| gulp.task('serve', function () { | ||||
| @@ -143,9 +150,9 @@ gulp.task('serve', function () { | ||||
|     var app = require('./app.js'); | ||||
| }); | ||||
|  | ||||
| gulp.task('develop', ['serve', 'stylesheets', 'watch']); | ||||
| gulp.task('develop', ['serve', 'install', 'watch']); | ||||
|  | ||||
| gulp.task('install', [ 'static', 'scripts' ]); | ||||
| gulp.task('install', [ 'assets', 'scripts' ]); | ||||
|  | ||||
| gulp.task('verify', [ 'lint', 'test', 'checkstyle' ]); | ||||
|  | ||||
|   | ||||
| @@ -31,10 +31,14 @@ | ||||
|     <script type="text/javascript"> | ||||
|         require(['main'], function (mct) { | ||||
|             require([ | ||||
|                 './tutorials/todo/todo', | ||||
|                 './example/imagery/bundle', | ||||
|                 './example/eventGenerator/bundle', | ||||
|                 './example/generator/bundle' | ||||
|             ], mct.run.bind(mct)); | ||||
|             ], function (todoPlugin) { | ||||
|                 mct.install(todoPlugin); | ||||
|                 mct.run(); | ||||
|             }) | ||||
|         }); | ||||
|     </script> | ||||
|     <link rel="stylesheet" href="platform/commonUI/general/res/css/startup-base.css"> | ||||
| @@ -48,7 +52,5 @@ | ||||
|     <div class="l-splash-holder s-splash-holder"> | ||||
|         <div class="l-splash s-splash"></div> | ||||
|     </div> | ||||
|  | ||||
|     <div ng-view></div> | ||||
| </body> | ||||
| </html> | ||||
|   | ||||
							
								
								
									
										68
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								main.js
									
									
									
									
									
								
							| @@ -28,13 +28,15 @@ requirejs.config({ | ||||
|         "angular-route": "bower_components/angular-route/angular-route.min", | ||||
|         "csv": "bower_components/comma-separated-values/csv.min", | ||||
|         "es6-promise": "bower_components/es6-promise/promise.min", | ||||
|         "EventEmitter": "bower_components/eventemitter3/index", | ||||
|         "moment": "bower_components/moment/moment", | ||||
|         "moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format", | ||||
|         "saveAs": "bower_components/FileSaver.js/FileSaver.min", | ||||
|         "screenfull": "bower_components/screenfull/dist/screenfull.min", | ||||
|         "text": "bower_components/text/text", | ||||
|         "uuid": "bower_components/node-uuid/uuid", | ||||
|         "zepto": "bower_components/zepto/zepto.min" | ||||
|         "zepto": "bower_components/zepto/zepto.min", | ||||
|         "lodash": "bower_components/lodash/lodash" | ||||
|     }, | ||||
|     "shim": { | ||||
|         "angular": { | ||||
| @@ -43,6 +45,9 @@ requirejs.config({ | ||||
|         "angular-route": { | ||||
|             "deps": ["angular"] | ||||
|         }, | ||||
|         "EventEmitter": { | ||||
|             "exports": "EventEmitter" | ||||
|         }, | ||||
|         "moment-duration-format": { | ||||
|             "deps": ["moment"] | ||||
|         }, | ||||
| @@ -51,53 +56,32 @@ requirejs.config({ | ||||
|         }, | ||||
|         "zepto": { | ||||
|             "exports": "Zepto" | ||||
|         }, | ||||
|         "lodash": { | ||||
|             "exports": "lodash" | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| define([ | ||||
|     './platform/framework/src/Main', | ||||
|     'legacyRegistry', | ||||
|     './src/defaultRegistry', | ||||
|     './src/MCT' | ||||
| ], function (Main, defaultRegistry, MCT) { | ||||
|     var mct = new MCT(); | ||||
|  | ||||
|     './platform/framework/bundle', | ||||
|     './platform/core/bundle', | ||||
|     './platform/representation/bundle', | ||||
|     './platform/commonUI/about/bundle', | ||||
|     './platform/commonUI/browse/bundle', | ||||
|     './platform/commonUI/edit/bundle', | ||||
|     './platform/commonUI/dialog/bundle', | ||||
|     './platform/commonUI/formats/bundle', | ||||
|     './platform/commonUI/general/bundle', | ||||
|     './platform/commonUI/inspect/bundle', | ||||
|     './platform/commonUI/mobile/bundle', | ||||
|     './platform/commonUI/themes/espresso/bundle', | ||||
|     './platform/commonUI/notification/bundle', | ||||
|     './platform/containment/bundle', | ||||
|     './platform/execution/bundle', | ||||
|     './platform/exporters/bundle', | ||||
|     './platform/telemetry/bundle', | ||||
|     './platform/features/clock/bundle', | ||||
|     './platform/features/imagery/bundle', | ||||
|     './platform/features/layout/bundle', | ||||
|     './platform/features/pages/bundle', | ||||
|     './platform/features/plot/bundle', | ||||
|     './platform/features/timeline/bundle', | ||||
|     './platform/features/table/bundle', | ||||
|     './platform/forms/bundle', | ||||
|     './platform/identity/bundle', | ||||
|     './platform/persistence/aggregator/bundle', | ||||
|     './platform/persistence/local/bundle', | ||||
|     './platform/persistence/queue/bundle', | ||||
|     './platform/policy/bundle', | ||||
|     './platform/entanglement/bundle', | ||||
|     './platform/search/bundle', | ||||
|     './platform/status/bundle', | ||||
|     './platform/commonUI/regions/bundle' | ||||
| ], function (Main, legacyRegistry) { | ||||
|     return { | ||||
|         legacyRegistry: legacyRegistry, | ||||
|         run: function () { | ||||
|             return new Main().run(legacyRegistry); | ||||
|         } | ||||
|     mct.legacyRegistry = defaultRegistry; | ||||
|     mct.run = function (domElement) { | ||||
|         if (!domElement) { domElement = document.body; } | ||||
|         var appDiv = document.createElement('div'); | ||||
|         appDiv.setAttribute('ng-view', ''); | ||||
|         appDiv.className = 'user-environ'; | ||||
|         domElement.appendChild(appDiv); | ||||
|         mct.start(); | ||||
|     }; | ||||
|     mct.on('start', function () { | ||||
|         return new Main().run(defaultRegistry); | ||||
|     }); | ||||
|  | ||||
|     return mct; | ||||
| }); | ||||
|   | ||||
							
								
								
									
										64
									
								
								object-provider.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								object-provider.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
|   <meta http-equiv="Content-type" content="text/html; charset=utf-8"> | ||||
|   <title>Groot Tutorial</title> | ||||
|   <script src="dist/main.js"></script> | ||||
| </head> | ||||
| <body> | ||||
| <script> | ||||
|  | ||||
|     // First, we need a source of objects, so we're going to define a few | ||||
|     // objects that we wish to expose.  The first object is a folder which | ||||
|     // contains the other objects. | ||||
|  | ||||
|  | ||||
|     var GROOT_ROOT = { | ||||
|         name: 'I am groot', | ||||
|         type: 'folder', | ||||
|         composition: [ | ||||
|             { | ||||
|                 namespace: 'groot', | ||||
|                 identifier: 'arms' | ||||
|             }, | ||||
|             { | ||||
|                 namespace: 'groot', | ||||
|                 identifier: 'legs' | ||||
|             }, | ||||
|             { | ||||
|                 namespace: 'groot', | ||||
|                 identifier: 'torso' | ||||
|             } | ||||
|         ] | ||||
|     }; | ||||
|  | ||||
|     // Now, we will define an object provider.  This will allow us to fetch the | ||||
|     // GROOT_ROOT object, plus any other objects in the `groot` namespace. | ||||
|     // For more info, see the Object API documentation. | ||||
|  | ||||
|     MCT.Objects.addProvider('groot', { | ||||
|         // we'll only define a get function, objects from this provider will | ||||
|         // not be mutable. | ||||
|         get: function (key) { | ||||
|             if (key.identifier === 'groot') { | ||||
|                 return Promise.resolve(GROOT_ROOT); | ||||
|             } | ||||
|             return Promise.resolve({ | ||||
|                 name: 'Groot\'s ' + key.identifier | ||||
|             }); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     // Finally, we need to add a "ROOT."  This is an identifier for an object | ||||
|     // that Open MCT will load at run time and show at the top-level of the | ||||
|     // navigation tree. | ||||
|  | ||||
|     MCT.Objects.addRoot({ | ||||
|         namespace: 'groot', | ||||
|         identifier: 'groot' | ||||
|     }); | ||||
|  | ||||
|     MCT.run(); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
| @@ -39,6 +39,7 @@ define([ | ||||
|     "text!./res/templates/items/items.html", | ||||
|     "text!./res/templates/browse/object-properties.html", | ||||
|     "text!./res/templates/browse/inspector-region.html", | ||||
|     "text!./res/templates/view-object.html", | ||||
|     'legacyRegistry' | ||||
| ], function ( | ||||
|     BrowseController, | ||||
| @@ -59,6 +60,7 @@ define([ | ||||
|     itemsTemplate, | ||||
|     objectPropertiesTemplate, | ||||
|     inspectorRegionTemplate, | ||||
|     viewObjectTemplate, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|  | ||||
| @@ -129,7 +131,7 @@ define([ | ||||
|             "representations": [ | ||||
|                 { | ||||
|                     "key": "view-object", | ||||
|                     "templateUrl": "templates/view-object.html" | ||||
|                     "template": viewObjectTemplate | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "browse-object", | ||||
|   | ||||
| @@ -48,6 +48,7 @@ define([ | ||||
|     "./src/directives/MCTSplitPane", | ||||
|     "./src/directives/MCTSplitter", | ||||
|     "./src/directives/MCTTree", | ||||
|     "./src/filters/ReverseFilter.js", | ||||
|     "text!./res/templates/bottombar.html", | ||||
|     "text!./res/templates/controls/action-button.html", | ||||
|     "text!./res/templates/controls/input-filter.html", | ||||
| @@ -96,6 +97,7 @@ define([ | ||||
|     MCTSplitPane, | ||||
|     MCTSplitter, | ||||
|     MCTTree, | ||||
|     ReverseFilter, | ||||
|     bottombarTemplate, | ||||
|     actionButtonTemplate, | ||||
|     inputFilterTemplate, | ||||
| @@ -146,7 +148,8 @@ define([ | ||||
|                     "depends": [ | ||||
|                         "stylesheets[]", | ||||
|                         "$document", | ||||
|                         "THEME" | ||||
|                         "THEME", | ||||
|                         "ASSETS_PATH" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
| @@ -158,7 +161,7 @@ define([ | ||||
|             ], | ||||
|             "filters": [ | ||||
|                 { | ||||
|                     "implementation": "filters/ReverseFilter.js", | ||||
|                     "implementation": ReverseFilter, | ||||
|                     "key": "reverse" | ||||
|                 } | ||||
|             ], | ||||
| @@ -404,6 +407,11 @@ define([ | ||||
|                     "key": "THEME", | ||||
|                     "value": "unspecified", | ||||
|                     "priority": "fallback" | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "ASSETS_PATH", | ||||
|                     "value": ".", | ||||
|                     "priority": "fallback" | ||||
|                 } | ||||
|             ], | ||||
|             "containers": [ | ||||
|   | ||||
| @@ -38,7 +38,7 @@ define( | ||||
|          * @param $document Angular's jqLite-wrapped document element | ||||
|          * @param {string} activeTheme the theme in use | ||||
|          */ | ||||
|         function StyleSheetLoader(stylesheets, $document, activeTheme) { | ||||
|         function StyleSheetLoader(stylesheets, $document, activeTheme, assetPath) { | ||||
|             var head = $document.find('head'), | ||||
|                 document = $document[0]; | ||||
|  | ||||
| @@ -47,6 +47,7 @@ define( | ||||
|                 // Create a link element, and construct full path | ||||
|                 var link = document.createElement('link'), | ||||
|                     path = [ | ||||
|                         assetPath, | ||||
|                         stylesheet.bundle.path, | ||||
|                         stylesheet.bundle.resources, | ||||
|                         stylesheet.stylesheetUrl | ||||
|   | ||||
| @@ -42,11 +42,19 @@ define( | ||||
|             function addWorker(worker) { | ||||
|                 var key = worker.key; | ||||
|                 if (!workerUrls[key]) { | ||||
|                     workerUrls[key] = [ | ||||
|                         worker.bundle.path, | ||||
|                         worker.bundle.sources, | ||||
|                         worker.scriptUrl | ||||
|                     ].join("/"); | ||||
|                     if (worker.scriptUrl) { | ||||
|                         workerUrls[key] = [ | ||||
|                             worker.bundle.path, | ||||
|                             worker.bundle.sources, | ||||
|                             worker.scriptUrl | ||||
|                         ].join("/"); | ||||
|                     } else if (worker.scriptText) { | ||||
|                         var blob = new Blob( | ||||
|                             [worker.scriptText], | ||||
|                             {type: 'application/javascript'} | ||||
|                         ); | ||||
|                         workerUrls[key] = URL.createObjectURL(blob); | ||||
|                     } | ||||
|                     sharedWorkers[key] = worker.shared; | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -27,6 +27,9 @@ define([ | ||||
|     "./src/controllers/TableOptionsController", | ||||
|     '../../commonUI/regions/src/Region', | ||||
|     '../../commonUI/browse/src/InspectorRegion', | ||||
|     "text!./res/templates/table-options-edit.html", | ||||
|     "text!./res/templates/rt-table.html", | ||||
|     "text!./res/templates/historical-table.html", | ||||
|     "legacyRegistry" | ||||
| ], function ( | ||||
|     MCTTable, | ||||
| @@ -35,6 +38,9 @@ define([ | ||||
|     TableOptionsController, | ||||
|     Region, | ||||
|     InspectorRegion, | ||||
|     tableOptionsEditTemplate, | ||||
|     rtTableTemplate, | ||||
|     historicalTableTemplate, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|     /** | ||||
| @@ -128,7 +134,7 @@ define([ | ||||
|                     "name": "Historical Table", | ||||
|                     "key": "table", | ||||
|                     "glyph": "\ue604", | ||||
|                     "templateUrl": "templates/historical-table.html", | ||||
|                     "template": historicalTableTemplate, | ||||
|                     "needs": [ | ||||
|                         "telemetry" | ||||
|                     ], | ||||
| @@ -139,7 +145,7 @@ define([ | ||||
|                     "name": "Real-time Table", | ||||
|                     "key": "rt-table", | ||||
|                     "glyph": "\ue620", | ||||
|                     "templateUrl": "templates/rt-table.html", | ||||
|                     "template": rtTableTemplate, | ||||
|                     "needs": [ | ||||
|                         "telemetry" | ||||
|                     ], | ||||
| @@ -157,7 +163,7 @@ define([ | ||||
|             "representations": [ | ||||
|                 { | ||||
|                     "key": "table-options-edit", | ||||
|                     "templateUrl": "templates/table-options-edit.html" | ||||
|                     "template": tableOptionsEditTemplate | ||||
|                 } | ||||
|             ], | ||||
|             "stylesheets": [ | ||||
|   | ||||
| @@ -28,6 +28,7 @@ define([ | ||||
|     "text!./res/templates/search-item.html", | ||||
|     "text!./res/templates/search.html", | ||||
|     "text!./res/templates/search-menu.html", | ||||
|     "text!./src/services/GenericSearchWorker.js", | ||||
|     'legacyRegistry' | ||||
| ], function ( | ||||
|     SearchController, | ||||
| @@ -37,6 +38,7 @@ define([ | ||||
|     searchItemTemplate, | ||||
|     searchTemplate, | ||||
|     searchMenuTemplate, | ||||
|     searchWorkerText, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|  | ||||
| @@ -114,7 +116,7 @@ define([ | ||||
|             "workers": [ | ||||
|                 { | ||||
|                     "key": "genericSearchWorker", | ||||
|                     "scriptUrl": "services/GenericSearchWorker.js" | ||||
|                     "scriptText": searchWorkerText | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|   | ||||
							
								
								
									
										50
									
								
								plugin-example.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								plugin-example.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
|   <meta http-equiv="Content-type" content="text/html; charset=utf-8"> | ||||
|   <title>Implementing a basic plugin</title> | ||||
|   <script src="dist/main.js"></script> | ||||
| </head> | ||||
| <body> | ||||
| <script> | ||||
|  | ||||
|     function WebPlugin(websites) { | ||||
|         this.websites = websites; | ||||
|  | ||||
|         var ROOTS = websites.reduce(function (rootMap, website) { | ||||
|             rootMap[website] = { | ||||
|                 namespace: website, | ||||
|                 identifier: 'page' | ||||
|             }; | ||||
|             return rootMap; | ||||
|         }, {}); | ||||
|  | ||||
|         function installPlugin(MCT) { | ||||
|             Object.keys(ROOTS).forEach(function (rootUrl) { | ||||
|                 MCT.Objects.addRoot(ROOTS[rootUrl]); | ||||
|                 MCT.Objects.addProvider(rootUrl, { | ||||
|                     get: function () { | ||||
|                         return Promise.resolve({ | ||||
|                             type: 'example.page', | ||||
|                             url: rootUrl, | ||||
|                             name: rootUrl | ||||
|                         }); | ||||
|                     } | ||||
|                 }); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         return installPlugin; | ||||
|     } | ||||
|  | ||||
|     var myWebPlugin = WebPlugin([ | ||||
|         'http://www.wikipedia.org/', | ||||
|         'http://nasa.github.io/openmct' | ||||
|     ]); | ||||
|  | ||||
|     MCT.install(myWebPlugin); | ||||
|  | ||||
|     MCT.run(); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,9 +1,9 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * Open MCT, Copyright (c) 2014-2016, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * 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. | ||||
| @@ -14,7 +14,7 @@ | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * 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. | ||||
| @@ -24,10 +24,28 @@ define(function () { | ||||
|  | ||||
|     function BundleRegistry() { | ||||
|         this.bundles = {}; | ||||
|         this.knownBundles = {}; | ||||
|     } | ||||
|  | ||||
|     BundleRegistry.prototype.register = function (path, definition) { | ||||
|         this.bundles[path] = definition; | ||||
|         if (this.knownBundles.hasOwnProperty(path)) { | ||||
|             throw new Error('Cannot register bundle with duplicate path', path); | ||||
|         } | ||||
|         this.knownBundles[path] = definition; | ||||
|     }; | ||||
|  | ||||
|     BundleRegistry.prototype.enable = function (path) { | ||||
|         if (!this.knownBundles[path]) { | ||||
|             throw new Error('Unknown bundle ' + path); | ||||
|         } | ||||
|         this.bundles[path] = this.knownBundles[path]; | ||||
|     }; | ||||
|  | ||||
|     BundleRegistry.prototype.disable = function (path) { | ||||
|         if (!this.bundles[path]) { | ||||
|             throw new Error('Tried to disable inactive bundle ' + path); | ||||
|         } | ||||
|         delete this.bundles[path]; | ||||
|     }; | ||||
|  | ||||
|     BundleRegistry.prototype.contains = function (path) { | ||||
| @@ -42,8 +60,14 @@ define(function () { | ||||
|         return Object.keys(this.bundles); | ||||
|     }; | ||||
|  | ||||
|     BundleRegistry.prototype.remove = function (path) { | ||||
|     BundleRegistry.prototype.remove = BundleRegistry.prototype.disable; | ||||
|  | ||||
|     BundleRegistry.prototype.delete = function (path) { | ||||
|         if (!this.knownBundles[path]) { | ||||
|             throw new Error('Cannot remove Unknown Bundle ' + path); | ||||
|         } | ||||
|         delete this.bundles[path]; | ||||
|         delete this.knownBundles[path]; | ||||
|     }; | ||||
|  | ||||
|     return BundleRegistry; | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * Open MCT, Copyright (c) 2014-2016, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * 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. | ||||
| @@ -14,7 +14,7 @@ | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * 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. | ||||
| @@ -51,6 +51,7 @@ define(['./BundleRegistry'], function (BundleRegistry) { | ||||
|             beforeEach(function () { | ||||
|                 testBundleDef = { someKey: "some value" }; | ||||
|                 bundleRegistry.register(testPath, testBundleDef); | ||||
|                 bundleRegistry.enable(testPath); | ||||
|             }); | ||||
|  | ||||
|             it("lists registered bundles", function () { | ||||
|   | ||||
							
								
								
									
										275
									
								
								src/MCT.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										275
									
								
								src/MCT.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,275 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'EventEmitter', | ||||
|     'legacyRegistry', | ||||
|     'uuid', | ||||
|     './api/api', | ||||
|     'text!./adapter/templates/edit-object-replacement.html', | ||||
|     './selection/Selection', | ||||
|     './api/objects/object-utils', | ||||
|     './ui/ViewRegistry' | ||||
| ], function ( | ||||
|     EventEmitter, | ||||
|     legacyRegistry, | ||||
|     uuid, | ||||
|     api, | ||||
|     editObjectTemplate, | ||||
|     Selection, | ||||
|     objectUtils, | ||||
|     ViewRegistry | ||||
| ) { | ||||
|     /** | ||||
|      * Open MCT is an extensible web application for building mission | ||||
|      * control user interfaces. This module is itself an instance of | ||||
|      * [MCT]{@link module:openmct.MCT}, which provides an interface for | ||||
|      * configuring and executing the application. | ||||
|      * | ||||
|      * @exports openmct | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * The Open MCT application. This may be configured by installing plugins | ||||
|      * or registering extensions before the application is started. | ||||
|      * @class MCT | ||||
|      * @memberof module:openmct | ||||
|      * @augments {EventEmitter} | ||||
|      */ | ||||
|     function MCT() { | ||||
|         EventEmitter.call(this); | ||||
|         this.legacyBundle = { extensions: { | ||||
|             services: [ | ||||
|                 { | ||||
|                     key: "openmct", | ||||
|                     implementation: function () { | ||||
|                         return this; | ||||
|                     }.bind(this) | ||||
|                 } | ||||
|             ] | ||||
|         } }; | ||||
|  | ||||
|         /** | ||||
|          * Tracks current selection state of the application. | ||||
|          * @private | ||||
|          */ | ||||
|         this.selection = new Selection(); | ||||
|  | ||||
|         /** | ||||
|          * MCT's time conductor, which may be used to synchronize view contents | ||||
|          * for telemetry- or time-based views. | ||||
|          * @type {module:openmct.TimeConductor} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name conductor | ||||
|          */ | ||||
|         this.conductor = new api.TimeConductor(); | ||||
|  | ||||
|         /** | ||||
|          * An interface for interacting with the composition of domain objects. | ||||
|          * The composition of a domain object is the list of other domain | ||||
|          * objects it "contains" (for instance, that should be displayed | ||||
|          * beneath it in the tree.) | ||||
|          * | ||||
|          * `composition` may be called as a function, in which case it acts | ||||
|          * as [`composition.get`]{@link module:openmct.CompositionAPI#get}. | ||||
|          * | ||||
|          * @type {module:openmct.CompositionAPI} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name composition | ||||
|          */ | ||||
|         this.composition = new api.CompositionAPI(); | ||||
|  | ||||
|         /** | ||||
|          * Registry for views of domain objects which should appear in the | ||||
|          * main viewing area. | ||||
|          * | ||||
|          * @type {module:openmct.ViewRegistry} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name mainViews | ||||
|          */ | ||||
|         this.mainViews = new ViewRegistry(); | ||||
|  | ||||
|         /** | ||||
|          * Registry for views which should appear in the Inspector area. | ||||
|          * These views will be chosen based on selection state, so | ||||
|          * providers should be prepared to test arbitrary objects for | ||||
|          * viewability. | ||||
|          * | ||||
|          * @type {module:openmct.ViewRegistry} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name inspectors | ||||
|          */ | ||||
|         this.inspectors = new ViewRegistry(); | ||||
|  | ||||
|         /** | ||||
|          * Registry for views which should appear in Edit Properties | ||||
|          * dialogs, and similar user interface elements used for | ||||
|          * modifying domain objects external to its regular views. | ||||
|          * | ||||
|          * @type {module:openmct.ViewRegistry} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name propertyEditors | ||||
|          */ | ||||
|         this.propertyEditors = new ViewRegistry(); | ||||
|  | ||||
|         /** | ||||
|          * Registry for views which should appear in the status indicator area. | ||||
|          * @type {module:openmct.ViewRegistry} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name indicators | ||||
|          */ | ||||
|         this.indicators = new ViewRegistry(); | ||||
|  | ||||
|         /** | ||||
|          * Registry for views which should appear in the toolbar area while | ||||
|          * editing. | ||||
|          * | ||||
|          * These views will be chosen based on selection state, so | ||||
|          * providers should be prepared to test arbitrary objects for | ||||
|          * viewability. | ||||
|          * | ||||
|          * @type {module:openmct.ViewRegistry} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name toolbars | ||||
|          */ | ||||
|         this.toolbars = new ViewRegistry(); | ||||
|  | ||||
|         /** | ||||
|          * Registry for domain object types which may exist within this | ||||
|          * instance of Open MCT. | ||||
|          * | ||||
|          * @type {module:openmct.TypeRegistry} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name types | ||||
|          */ | ||||
|         this.types = new api.TypeRegistry(); | ||||
|  | ||||
|         /** | ||||
|          * Utilities for attaching common behaviors to views. | ||||
|          * | ||||
|          * @type {module:openmct.GestureAPI} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name gestures | ||||
|          */ | ||||
|         this.gestures = new api.GestureAPI(); | ||||
|  | ||||
|         /** | ||||
|          * An interface for interacting with domain objects and the domain | ||||
|          * object hierarchy. | ||||
|          * | ||||
|          * @type {module:openmct.ObjectAPI} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name objects | ||||
|          */ | ||||
|         this.objects = new api.ObjectAPI(); | ||||
|  | ||||
|         /** | ||||
|          * An interface for retrieving and interpreting telemetry data associated | ||||
|          * with a domain object. | ||||
|          * | ||||
|          * @type {module:openmct.TelemetryAPI} | ||||
|          * @memberof module:openmct.MCT# | ||||
|          * @name telemetry | ||||
|          */ | ||||
|         this.telemetry = new api.TelemetryAPI(); | ||||
|  | ||||
|         this.TimeConductor = this.conductor; // compatibility for prototype | ||||
|         this.on('navigation', this.selection.clear.bind(this.selection)); | ||||
|     } | ||||
|  | ||||
|     MCT.prototype = Object.create(EventEmitter.prototype); | ||||
|  | ||||
|     Object.keys(api).forEach(function (k) { | ||||
|         MCT.prototype[k] = api[k]; | ||||
|     }); | ||||
|     MCT.prototype.MCT = MCT; | ||||
|  | ||||
|     MCT.prototype.legacyExtension = function (category, extension) { | ||||
|         this.legacyBundle.extensions[category] = | ||||
|             this.legacyBundle.extensions[category] || []; | ||||
|         this.legacyBundle.extensions[category].push(extension); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Set path to where assets are hosted.  This should be the path to main.js. | ||||
|      * @memberof module:openmct.MCT# | ||||
|      * @method setAssetPath | ||||
|      */ | ||||
|     MCT.prototype.setAssetPath = function (path) { | ||||
|         this.legacyExtension('constants', { | ||||
|             key: "ASSETS_PATH", | ||||
|             value: path | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Start running Open MCT. This should be called only after any plugins | ||||
|      * have been installed. | ||||
|      * @fires module:openmct.MCT~start | ||||
|      * @memberof module:openmct.MCT# | ||||
|      * @method start | ||||
|      * @param {HTMLElement} [domElement] the DOM element in which to run | ||||
|      *        MCT; if undefined, MCT will be run in the body of the document | ||||
|      */ | ||||
|     MCT.prototype.start = function (domElement) { | ||||
|         if (!domElement) { | ||||
|             domElement = document.body; | ||||
|         } | ||||
|  | ||||
|         var appDiv = document.createElement('div'); | ||||
|         appDiv.setAttribute('ng-view', ''); | ||||
|         appDiv.className = 'user-environ'; | ||||
|         domElement.appendChild(appDiv); | ||||
|  | ||||
|         this.legacyExtension('runs', { | ||||
|             depends: ['navigationService'], | ||||
|             implementation: function (navigationService) { | ||||
|                 navigationService | ||||
|                     .addListener(this.emit.bind(this, 'navigation')); | ||||
|             }.bind(this) | ||||
|         }); | ||||
|  | ||||
|         legacyRegistry.register('adapter', this.legacyBundle); | ||||
|         legacyRegistry.enable('adapter'); | ||||
|         /** | ||||
|          * Fired by [MCT]{@link module:openmct.MCT} when the application | ||||
|          * is started. | ||||
|          * @event start | ||||
|          * @memberof module:openmct.MCT~ | ||||
|          */ | ||||
|         this.emit('start'); | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Install a plugin in MCT. | ||||
|      * | ||||
|      * @param {Function} plugin a plugin install function which will be | ||||
|      *     invoked with the mct instance. | ||||
|      * @memberof module:openmct.MCT# | ||||
|      */ | ||||
|     MCT.prototype.install = function (plugin) { | ||||
|         plugin(this); | ||||
|     }; | ||||
|  | ||||
|     return MCT; | ||||
| }); | ||||
							
								
								
									
										57
									
								
								src/adapter/actions/ActionDialogDecorator.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/adapter/actions/ActionDialogDecorator.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     '../../api/objects/object-utils' | ||||
| ], function (objectUtils) { | ||||
|     function ActionDialogDecorator(mct, actionService) { | ||||
|         this.mct = mct; | ||||
|         this.actionService = actionService; | ||||
|     } | ||||
|  | ||||
|     ActionDialogDecorator.prototype.getActions = function (context) { | ||||
|         var mct = this.mct; | ||||
|  | ||||
|         return this.actionService.getActions(context).map(function (action) { | ||||
|             if (action.dialogService) { | ||||
|                 var domainObject = objectUtils.toNewFormat( | ||||
|                     context.domainObject.getModel(), | ||||
|                     objectUtils.parseKeyString(context.domainObject.getId()) | ||||
|                 ); | ||||
|                 var providers = mct.propertyEditors.get(domainObject); | ||||
|  | ||||
|                 if (providers.length > 0) { | ||||
|                     action.dialogService = Object.create(action.dialogService); | ||||
|                     action.dialogService.getUserInput = function (form, value) { | ||||
|                         return new mct.Dialog( | ||||
|                             providers[0].view(context.domainObject), | ||||
|                             form.title | ||||
|                         ).show(); | ||||
|                     }; | ||||
|                 } | ||||
|             } | ||||
|             return action; | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     return ActionDialogDecorator; | ||||
| }); | ||||
							
								
								
									
										127
									
								
								src/adapter/bundle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/adapter/bundle.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'legacyRegistry', | ||||
|     './actions/ActionDialogDecorator', | ||||
|     './directives/MCTView', | ||||
|     './services/Instantiate', | ||||
|     './capabilities/APICapabilityDecorator', | ||||
|     './policies/AdapterCompositionPolicy', | ||||
|     './runs/AlternateCompositionInitializer' | ||||
| ], function ( | ||||
|     legacyRegistry, | ||||
|     ActionDialogDecorator, | ||||
|     MCTView, | ||||
|     Instantiate, | ||||
|     APICapabilityDecorator, | ||||
|     AdapterCompositionPolicy, | ||||
|     AlternateCompositionInitializer | ||||
| ) { | ||||
|     legacyRegistry.register('src/adapter', { | ||||
|         "extensions": { | ||||
|             "directives": [ | ||||
|                 { | ||||
|                     key: "mctView", | ||||
|                     implementation: MCTView, | ||||
|                     depends: [ | ||||
|                         "newViews[]", | ||||
|                         "openmct" | ||||
|                     ] | ||||
|                 } | ||||
|             ], | ||||
|             services: [ | ||||
|                 { | ||||
|                     key: "instantiate", | ||||
|                     priority: "mandatory", | ||||
|                     implementation: Instantiate, | ||||
|                     depends: [ | ||||
|                         "capabilityService", | ||||
|                         "identifierService", | ||||
|                         "cacheService" | ||||
|                     ] | ||||
|                 } | ||||
|             ], | ||||
|             components: [ | ||||
|                 { | ||||
|                     type: "decorator", | ||||
|                     provides: "capabilityService", | ||||
|                     implementation: APICapabilityDecorator, | ||||
|                     depends: [ | ||||
|                         "$injector" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     type: "decorator", | ||||
|                     provides: "actionService", | ||||
|                     implementation: ActionDialogDecorator, | ||||
|                     depends: ["openmct"] | ||||
|                 } | ||||
|             ], | ||||
|             policies: [ | ||||
|                 { | ||||
|                     category: "composition", | ||||
|                     implementation: AdapterCompositionPolicy, | ||||
|                     depends: ["openmct"] | ||||
|                 } | ||||
|             ], | ||||
|             runs: [ | ||||
|                 { | ||||
|                     implementation: AlternateCompositionInitializer, | ||||
|                     depends: ["openmct"] | ||||
|                 } | ||||
|             ], | ||||
|             licenses: [ | ||||
|                 { | ||||
|                     "name": "almond", | ||||
|                     "version": "0.3.3", | ||||
|                     "description": "Lightweight RequireJS replacement for builds", | ||||
|                     "author": "jQuery Foundation", | ||||
|                     "website": "https://github.com/requirejs/almond", | ||||
|                     "copyright": "Copyright jQuery Foundation and other contributors, https://jquery.org/", | ||||
|                     "license": "license-mit", | ||||
|                     "link": "https://github.com/requirejs/almond/blob/master/LICENSE" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "lodash", | ||||
|                     "version": "3.10.1", | ||||
|                     "description": "Utility functions", | ||||
|                     "author": "Dojo Foundation", | ||||
|                     "website": "https://lodash.com", | ||||
|                     "copyright": "Copyright 2012-2015 The Dojo Foundation", | ||||
|                     "license": "license-mit", | ||||
|                     "link": "https://raw.githubusercontent.com/lodash/lodash/3.10.1/LICENSE" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "EventEmitter3", | ||||
|                     "version": "1.2.0", | ||||
|                     "description": "Event-driven programming support", | ||||
|                     "author": "Arnout Kazemier", | ||||
|                     "website": "https://github.com/primus/eventemitter3", | ||||
|                     "copyright": "Copyright (c) 2014 Arnout Kazemier", | ||||
|                     "license": "license-mit", | ||||
|                     "link": "https://github.com/primus/eventemitter3/blob/1.2.0/LICENSE" | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										59
									
								
								src/adapter/capabilities/APICapabilityDecorator.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/adapter/capabilities/APICapabilityDecorator.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     './synchronizeMutationCapability', | ||||
|     './AlternateCompositionCapability' | ||||
| ], function ( | ||||
|     synchronizeMutationCapability, | ||||
|     AlternateCompositionCapability | ||||
| ) { | ||||
|  | ||||
|     /** | ||||
|      * Overrides certain capabilities to keep consistency between old API | ||||
|      * and new API. | ||||
|      */ | ||||
|     function APICapabilityDecorator($injector, capabilityService) { | ||||
|         this.$injector = $injector; | ||||
|         this.capabilityService = capabilityService; | ||||
|     } | ||||
|  | ||||
|     APICapabilityDecorator.prototype.getCapabilities = function ( | ||||
|         model | ||||
|     ) { | ||||
|         var capabilities = this.capabilityService.getCapabilities(model); | ||||
|         if (capabilities.mutation) { | ||||
|             capabilities.mutation = | ||||
|                 synchronizeMutationCapability(capabilities.mutation); | ||||
|         } | ||||
|         if (AlternateCompositionCapability.appliesTo(model)) { | ||||
|             capabilities.composition = function (domainObject) { | ||||
|                 return new AlternateCompositionCapability(this.$injector, domainObject); | ||||
|             }.bind(this); | ||||
|         } | ||||
|  | ||||
|         return capabilities; | ||||
|     }; | ||||
|  | ||||
|     return APICapabilityDecorator; | ||||
|  | ||||
| }); | ||||
							
								
								
									
										107
									
								
								src/adapter/capabilities/AlternateCompositionCapability.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/adapter/capabilities/AlternateCompositionCapability.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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 Web 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * Module defining AlternateCompositionCapability. Created by vwoeltje on 11/7/14. | ||||
|  */ | ||||
| define([ | ||||
|     '../../api/objects/object-utils' | ||||
| ], function (objectUtils) { | ||||
|         function AlternateCompositionCapability($injector, domainObject) { | ||||
|             this.domainObject = domainObject; | ||||
|             this.getDependencies = function () { | ||||
|                 this.instantiate = $injector.get("instantiate"); | ||||
|                 this.contextualize = $injector.get("contextualize"); | ||||
|                 this.getDependencies = undefined; | ||||
|                 this.openmct = $injector.get("openmct"); | ||||
|             }.bind(this); | ||||
|         } | ||||
|  | ||||
|         AlternateCompositionCapability.prototype.add = function (child, index) { | ||||
|             if (typeof index !== 'undefined') { | ||||
|                 // At first glance I don't see a location in the existing | ||||
|                 // codebase where add is called with an index.  Won't support. | ||||
|                 throw new Error( | ||||
|                     'Composition Capability does not support adding at index' | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             function addChildToComposition(model) { | ||||
|                 var existingIndex = model.composition.indexOf(child.getId()); | ||||
|                 if (existingIndex === -1) { | ||||
|                     model.composition.push(child.getId()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return this.domainObject.useCapability( | ||||
|                     'mutation', | ||||
|                     addChildToComposition | ||||
|                 ) | ||||
|                 .then(this.invoke.bind(this)) | ||||
|                 .then(function (children) { | ||||
|                     return children.filter(function (c) { | ||||
|                         return c.getId() === child.getId(); | ||||
|                     })[0]; | ||||
|                 }); | ||||
|         }; | ||||
|  | ||||
|         AlternateCompositionCapability.prototype.contextualizeChild = function ( | ||||
|             child | ||||
|         ) { | ||||
|             if (this.getDependencies) { | ||||
|                 this.getDependencies(); | ||||
|             } | ||||
|  | ||||
|             var keyString = objectUtils.makeKeyString(child.key); | ||||
|             var oldModel = objectUtils.toOldFormat(child); | ||||
|             var newDO = this.instantiate(oldModel, keyString); | ||||
|             return this.contextualize(newDO, this.domainObject); | ||||
|  | ||||
|         }; | ||||
|  | ||||
|         AlternateCompositionCapability.prototype.invoke = function () { | ||||
|             var newFormatDO = objectUtils.toNewFormat( | ||||
|                 this.domainObject.getModel(), | ||||
|                 this.domainObject.getId() | ||||
|             ); | ||||
|  | ||||
|             if (this.getDependencies) { | ||||
|                 this.getDependencies(); | ||||
|             } | ||||
|  | ||||
|             var collection = this.openmct.composition.get(newFormatDO); | ||||
|             return collection.load() | ||||
|                 .then(function (children) { | ||||
|                     collection.destroy(); | ||||
|                     return children.map(this.contextualizeChild, this); | ||||
|                 }.bind(this)); | ||||
|         }; | ||||
|  | ||||
|         AlternateCompositionCapability.appliesTo = function (model) { | ||||
|             // Will get replaced by a runs exception to properly | ||||
|             // bind to running openmct instance | ||||
|             return false; | ||||
|         }; | ||||
|  | ||||
|         return AlternateCompositionCapability; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										49
									
								
								src/adapter/capabilities/synchronizeMutationCapability.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/adapter/capabilities/synchronizeMutationCapability.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|  | ||||
| ], function ( | ||||
|  | ||||
| ) { | ||||
|  | ||||
|     /** | ||||
|      * Wraps the mutation capability and synchronizes the mutation | ||||
|      */ | ||||
|     function synchronizeMutationCapability(mutationConstructor) { | ||||
|  | ||||
|         return function makeCapability(domainObject) { | ||||
|             var capability = mutationConstructor(domainObject); | ||||
|             var oldListen = capability.listen.bind(capability); | ||||
|             capability.listen = function (listener) { | ||||
|                 return oldListen(function (newModel) { | ||||
|                     capability.domainObject.model = | ||||
|                         JSON.parse(JSON.stringify(newModel)); | ||||
|                     listener(newModel); | ||||
|                 }); | ||||
|             }; | ||||
|             return capability; | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     return synchronizeMutationCapability; | ||||
| }); | ||||
							
								
								
									
										87
									
								
								src/adapter/directives/MCTView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/adapter/directives/MCTView.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'angular', | ||||
|     './Region', | ||||
|     '../../api/objects/object-utils' | ||||
| ], function ( | ||||
|     angular, | ||||
|     Region, | ||||
|     objectUtils | ||||
| ) { | ||||
|     function MCTView(newViews, PublicAPI) { | ||||
|         var definitions = {}; | ||||
|  | ||||
|         newViews.forEach(function (newView) { | ||||
|             definitions[newView.region] = definitions[newView.region] || {}; | ||||
|             definitions[newView.region][newView.key] = newView.factory; | ||||
|         }); | ||||
|  | ||||
|         return { | ||||
|             restrict: 'E', | ||||
|             link: function (scope, element, attrs) { | ||||
|                 var key, mctObject, regionId, region; | ||||
|  | ||||
|                 function maybeShow() { | ||||
|                     if (!definitions[regionId] || !definitions[regionId][key] || !mctObject) { | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     region.show(definitions[regionId][key].view(mctObject)); | ||||
|                 } | ||||
|  | ||||
|                 function setKey(k) { | ||||
|                     key = k; | ||||
|                     maybeShow(); | ||||
|                 } | ||||
|  | ||||
|                 function setObject(obj) { | ||||
|                     mctObject = undefined; | ||||
|                     PublicAPI.Objects.get(objectUtils.parseKeyString(obj.getId())) | ||||
|                         .then(function (mobj) { | ||||
|                             mctObject = mobj; | ||||
|                             maybeShow(); | ||||
|                         }); | ||||
|                 } | ||||
|  | ||||
|                 function setRegionId(r) { | ||||
|                     regionId = r; | ||||
|                     maybeShow(); | ||||
|                 } | ||||
|  | ||||
|                 region = new Region(element[0]); | ||||
|  | ||||
|                 scope.$watch('key', setKey); | ||||
|                 scope.$watch('region', setRegionId); | ||||
|                 scope.$watch('mctObject', setObject); | ||||
|             }, | ||||
|             scope: { | ||||
|                 key: "=", | ||||
|                 region: "=", | ||||
|                 mctObject: "=" | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     return MCTView; | ||||
| }); | ||||
							
								
								
									
										45
									
								
								src/adapter/directives/Region.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/adapter/directives/Region.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([], function () { | ||||
|     function Region(element) { | ||||
|         this.activeView = undefined; | ||||
|         this.element = element; | ||||
|     } | ||||
|  | ||||
|     Region.prototype.clear = function () { | ||||
|         if (this.activeView) { | ||||
|             this.activeView.destroy(); | ||||
|             this.activeView = undefined; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     Region.prototype.show = function (view) { | ||||
|         this.clear(); | ||||
|         this.activeView = view; | ||||
|         if (this.activeView) { | ||||
|             this.activeView.show(this.element); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     return Region; | ||||
| }); | ||||
							
								
								
									
										48
									
								
								src/adapter/policies/AdapterCompositionPolicy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/adapter/policies/AdapterCompositionPolicy.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([], function () { | ||||
|     function AdapterCompositionPolicy(mct) { | ||||
|         this.mct = mct; | ||||
|     } | ||||
|  | ||||
|     AdapterCompositionPolicy.prototype.allow = function ( | ||||
|         containerType, | ||||
|         childType | ||||
|     ) { | ||||
|         var containerObject = containerType.getInitialModel(); | ||||
|         var childObject = childType.getInitialModel(); | ||||
|  | ||||
|         containerObject.type = containerType.getKey(); | ||||
|         childObject.type = childType.getKey(); | ||||
|  | ||||
|         var composition = this.mct.Composition(containerObject); | ||||
|  | ||||
|         if (composition) { | ||||
|             return composition.canContain(childObject); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     }; | ||||
|  | ||||
|     return AdapterCompositionPolicy; | ||||
| }); | ||||
							
								
								
									
										36
									
								
								src/adapter/runs/AlternateCompositionInitializer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/adapter/runs/AlternateCompositionInitializer.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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 Web 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([ | ||||
|     '../capabilities/AlternateCompositionCapability' | ||||
| ], function (AlternateCompositionCapability) { | ||||
|     // Present to work around the need for openmct to be used | ||||
|     // from AlternateCompositionCapability.appliesTo, even though it | ||||
|     // cannot be injected. | ||||
|     function AlternateCompositionInitializer(openmct) { | ||||
|         AlternateCompositionCapability.appliesTo = function (model) { | ||||
|             return !model.composition && !!openmct.composition.get(model); | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     return AlternateCompositionInitializer; | ||||
| }); | ||||
							
								
								
									
										49
									
								
								src/adapter/services/Instantiate.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/adapter/services/Instantiate.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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( | ||||
|     ['../../../platform/core/src/objects/DomainObjectImpl'], | ||||
|     function (DomainObjectImpl) { | ||||
|  | ||||
|         /** | ||||
|          * Overrides platform version of instantiate, passes Id with model such | ||||
|          * that capability detection can utilize new format domain objects. | ||||
|          */ | ||||
|         function Instantiate( | ||||
|             capabilityService, | ||||
|             identifierService, | ||||
|             cacheService | ||||
|         ) { | ||||
|             return function (model, id) { | ||||
|                 id = id || identifierService.generate(); | ||||
|                 var old_id = model.id; | ||||
|                 model.id = id; | ||||
|                 var capabilities = capabilityService.getCapabilities(model); | ||||
|                 model.id = old_id; | ||||
|                 cacheService.put(id, model); | ||||
|                 return new DomainObjectImpl(id, model, capabilities); | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return Instantiate; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										46
									
								
								src/adapter/templates/edit-object-replacement.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/adapter/templates/edit-object-replacement.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| <div class="abs l-flex-col" ng-controller="EditObjectController as EditObjectController"> | ||||
|     <div mct-before-unload="EditObjectController.getUnloadWarning()" | ||||
|          class="holder flex-elem l-flex-row object-browse-bar "> | ||||
|         <div class="items-select left flex-elem l-flex-row grows"> | ||||
|             <mct-representation key="'back-arrow'" | ||||
|                                 mct-object="domainObject" | ||||
|                                 class="flex-elem l-back"></mct-representation> | ||||
|             <mct-representation key="'object-header'" | ||||
|                                 mct-object="domainObject" | ||||
|                                 class="l-flex-row flex-elem grows object-header"> | ||||
|             </mct-representation> | ||||
|         </div> | ||||
|         <div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed"> | ||||
|             <mct-representation key="'switcher'" | ||||
|                                 mct-object="domainObject" | ||||
|                                 ng-model="representation"> | ||||
|             </mct-representation> | ||||
|             <!-- Temporarily, on mobile, the action buttons are hidden--> | ||||
|             <mct-representation key="'action-group'" | ||||
|                                 mct-object="domainObject" | ||||
|                                 parameters="{ category: 'view-control' }" | ||||
|                                 class="mobile-hide"> | ||||
|             </mct-representation> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="holder l-flex-col flex-elem grows l-object-wrapper"> | ||||
|         <div class="holder l-flex-col flex-elem grows l-object-wrapper-inner"> | ||||
|             <!-- Toolbar and Save/Cancel buttons --> | ||||
|             <div class="l-edit-controls flex-elem l-flex-row flex-align-end"> | ||||
|                 <mct-representation key="'adapted-view-TOOLBAR'" | ||||
|                                     mct-object="domainObject" | ||||
|                                     class="flex-elem grows"> | ||||
|                 </mct-representation> | ||||
|                 <mct-representation key="'edit-action-buttons'" | ||||
|                                     mct-object="domainObject" | ||||
|                                     class='flex-elem conclude-editing'> | ||||
|                 </mct-representation> | ||||
|             </div> | ||||
|             <mct-representation key="representation.selected.key" | ||||
|                                 mct-object="representation.selected.key && domainObject" | ||||
|                                 class="abs flex-elem grows object-holder-main scroll" | ||||
|                                 toolbar="toolbar"> | ||||
|             </mct-representation> | ||||
|         </div><!--/ l-object-wrapper-inner --> | ||||
|     </div> | ||||
| </div> | ||||
							
								
								
									
										202
									
								
								src/api/TimeConductor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/api/TimeConductor.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(['EventEmitter'], function (EventEmitter) { | ||||
|  | ||||
|     /** | ||||
|      * The public API for setting and querying time conductor state. The | ||||
|      * time conductor is the means by which the temporal bounds of a view | ||||
|      * are controlled. Time-sensitive views will typically respond to | ||||
|      * changes to bounds or other properties of the time conductor and | ||||
|      * update the data displayed based on the time conductor state. | ||||
|      * | ||||
|      * The TimeConductor extends the EventEmitter class. A number of events are | ||||
|      * fired when properties of the time conductor change, which are | ||||
|      * documented below. | ||||
|      * @interface | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function TimeConductor() { | ||||
|         EventEmitter.call(this); | ||||
|  | ||||
|         //The Time System | ||||
|         this.system = undefined; | ||||
|         //The Time Of Interest | ||||
|         this.toi = undefined; | ||||
|  | ||||
|         this.boundsVal = { | ||||
|             start: undefined, | ||||
|             end: undefined | ||||
|         }; | ||||
|  | ||||
|         //Default to fixed mode | ||||
|         this.followMode = false; | ||||
|     } | ||||
|  | ||||
|     TimeConductor.prototype = Object.create(EventEmitter.prototype); | ||||
|  | ||||
|     /** | ||||
|      * Validate the given bounds. This can be used for pre-validation of | ||||
|      * bounds, for example by views validating user inputs. | ||||
|      * @param bounds The start and end time of the conductor. | ||||
|      * @returns {string | true} A validation error, or true if valid | ||||
|      * @memberof module:openmct.TimeConductor# | ||||
|      * @method validateBounds | ||||
|      */ | ||||
|     TimeConductor.prototype.validateBounds = function (bounds) { | ||||
|         if ((bounds.start === undefined) || | ||||
|             (bounds.end === undefined) || | ||||
|             isNaN(bounds.start) || | ||||
|             isNaN(bounds.end) | ||||
|         ) { | ||||
|             return "Start and end must be specified as integer values"; | ||||
|         } else if (bounds.start > bounds.end) { | ||||
|             return "Specified start date exceeds end bound"; | ||||
|         } | ||||
|         return true; | ||||
|     }; | ||||
|  | ||||
|     function throwOnError(validationResult) { | ||||
|         if (validationResult !== true) { | ||||
|             throw new Error(validationResult); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get or set the follow mode of the time conductor. In follow mode the | ||||
|      * time conductor ticks, regularly updating the bounds from a timing | ||||
|      * source appropriate to the selected time system and mode of the time | ||||
|      * conductor. | ||||
|      * @fires module:openmct.TimeConductor~follow | ||||
|      * @param {boolean} followMode | ||||
|      * @returns {boolean} | ||||
|      * @memberof module:openmct.TimeConductor# | ||||
|      * @method follow | ||||
|      */ | ||||
|     TimeConductor.prototype.follow = function (followMode) { | ||||
|         if (arguments.length > 0) { | ||||
|             this.followMode = followMode; | ||||
|             /** | ||||
|              * The TimeConductor has toggled into or out of follow mode. | ||||
|              * @event follow | ||||
|              * @memberof module:openmct.TimeConductor~ | ||||
|              * @property {boolean} followMode true if follow mode is | ||||
|              *           enabled, otherwise false. | ||||
|              */ | ||||
|             this.emit('follow', this.followMode); | ||||
|         } | ||||
|         return this.followMode; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @typedef {Object} TimeConductorBounds | ||||
|      * @property {number} start The start time displayed by the time conductor in ms since epoch. Epoch determined by current time system | ||||
|      * @property {number} end The end time displayed by the time conductor in ms since epoch. | ||||
|      * @memberof module:openmct.TimeConductor~ | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Get or set the start and end time of the time conductor. Basic validation | ||||
|      * of bounds is performed. | ||||
|      * | ||||
|      * @param {module:openmct.TimeConductorBounds~TimeConductorBounds} newBounds | ||||
|      * @throws {Error} Validation error | ||||
|      * @fires module:openmct.TimeConductor~bounds | ||||
|      * @returns {module:openmct.TimeConductorBounds~TimeConductorBounds} | ||||
|      * @memberof module:openmct.TimeConductor# | ||||
|      * @method bounds | ||||
|      */ | ||||
|     TimeConductor.prototype.bounds = function (newBounds) { | ||||
|         if (arguments.length > 0) { | ||||
|             throwOnError(this.validateBounds(newBounds)); | ||||
|             this.boundsVal = newBounds; | ||||
|             /** | ||||
|              * The start time, end time, or both have been updated. | ||||
|              * @event bounds | ||||
|              * @memberof module:openmct.TimeConductor~ | ||||
|              * @property {TimeConductorBounds} bounds | ||||
|              */ | ||||
|             this.emit('bounds', this.boundsVal); | ||||
|         } | ||||
|         return this.boundsVal; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Get or set the time system of the TimeConductor. Time systems determine | ||||
|      * units, epoch, and other aspects of time representation. When changing | ||||
|      * the time system in use, new valid bounds must also be provided. | ||||
|      * @param {TimeSystem} newTimeSystem | ||||
|      * @param {module:openmct.TimeConductor~TimeConductorBounds} bounds | ||||
|      * @fires module:openmct.TimeConductor~timeSystem | ||||
|      * @returns {TimeSystem} The currently applied time system | ||||
|      * @memberof module:openmct.TimeConductor# | ||||
|      * @method timeSystem | ||||
|      */ | ||||
|     TimeConductor.prototype.timeSystem = function (newTimeSystem, bounds) { | ||||
|         if (arguments.length >= 2) { | ||||
|             this.system = newTimeSystem; | ||||
|             /** | ||||
|              * The time system used by the time | ||||
|              * conductor has changed. A change in Time System will always be | ||||
|              * followed by a bounds event specifying new query bounds. | ||||
|              * | ||||
|              * @event module:openmct.TimeConductor~timeSystem | ||||
|              * @property {TimeSystem} The value of the currently applied | ||||
|              * Time System | ||||
|              * */ | ||||
|             this.emit('timeSystem', this.system); | ||||
|             // Do something with bounds here. Try and convert between | ||||
|             // time systems? Or just set defaults when time system changes? | ||||
|             // eg. | ||||
|             this.bounds(bounds); | ||||
|         } else if (arguments.length === 1) { | ||||
|             throw new Error('Must set bounds when changing time system'); | ||||
|         } | ||||
|         return this.system; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Get or set the Time of Interest. The Time of Interest is the temporal | ||||
|      * focus of the current view. It can be manipulated by the user from the | ||||
|      * time conductor or from other views. | ||||
|      * @fires module:openmct.TimeConductor~timeOfInterest | ||||
|      * @param newTOI | ||||
|      * @returns {number} the current time of interest | ||||
|      * @memberof module:openmct.TimeConductor# | ||||
|      * @method timeOfInterest | ||||
|      */ | ||||
|     TimeConductor.prototype.timeOfInterest = function (newTOI) { | ||||
|         if (arguments.length > 0) { | ||||
|             this.toi = newTOI; | ||||
|             /** | ||||
|              * The Time of Interest has moved. | ||||
|              * @event timeOfInterest | ||||
|              * @memberof module:openmct.TimeConductor~ | ||||
|              * @property {number} Current time of interest | ||||
|              */ | ||||
|             this.emit('timeOfInterest', this.toi); | ||||
|         } | ||||
|         return this.toi; | ||||
|     }; | ||||
|  | ||||
|     return TimeConductor; | ||||
| }); | ||||
							
								
								
									
										110
									
								
								src/api/TimeConductorSpec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/api/TimeConductorSpec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(['./TimeConductor'], function (TimeConductor) { | ||||
|     describe("The Time Conductor", function () { | ||||
|         var tc, | ||||
|             timeSystem, | ||||
|             bounds, | ||||
|             eventListener, | ||||
|             toi, | ||||
|             follow; | ||||
|  | ||||
|         beforeEach(function () { | ||||
|             tc = new TimeConductor(); | ||||
|             timeSystem = {}; | ||||
|             bounds = {start: 0, end: 0}; | ||||
|             eventListener = jasmine.createSpy("eventListener"); | ||||
|             toi = 111; | ||||
|             follow = true; | ||||
|         }); | ||||
|  | ||||
|         it("Supports setting and querying of time of interest and and follow mode", function () { | ||||
|             expect(tc.timeOfInterest()).not.toBe(toi); | ||||
|             tc.timeOfInterest(toi); | ||||
|             expect(tc.timeOfInterest()).toBe(toi); | ||||
|  | ||||
|             expect(tc.follow()).not.toBe(follow); | ||||
|             tc.follow(follow); | ||||
|             expect(tc.follow()).toBe(follow); | ||||
|         }); | ||||
|  | ||||
|         it("Allows setting of valid bounds", function () { | ||||
|             bounds = {start: 0, end: 1}; | ||||
|             expect(tc.bounds()).not.toBe(bounds); | ||||
|             expect(tc.bounds.bind(tc, bounds)).not.toThrow(); | ||||
|             expect(tc.bounds()).toBe(bounds); | ||||
|         }); | ||||
|  | ||||
|         it("Disallows setting of invalid bounds", function () { | ||||
|             bounds = {start: 1, end: 0}; | ||||
|             expect(tc.bounds()).not.toBe(bounds); | ||||
|             expect(tc.bounds.bind(tc, bounds)).toThrow(); | ||||
|             expect(tc.bounds()).not.toBe(bounds); | ||||
|  | ||||
|             bounds = {start: 1}; | ||||
|             expect(tc.bounds()).not.toBe(bounds); | ||||
|             expect(tc.bounds.bind(tc, bounds)).toThrow(); | ||||
|             expect(tc.bounds()).not.toBe(bounds); | ||||
|         }); | ||||
|  | ||||
|         it("Allows setting of time system with bounds", function () { | ||||
|             expect(tc.timeSystem()).not.toBe(timeSystem); | ||||
|             expect(tc.timeSystem.bind(tc, timeSystem, bounds)).not.toThrow(); | ||||
|             expect(tc.timeSystem()).toBe(timeSystem); | ||||
|         }); | ||||
|  | ||||
|         it("Disallows setting of time system without bounds", function () { | ||||
|             expect(tc.timeSystem()).not.toBe(timeSystem); | ||||
|             expect(tc.timeSystem.bind(tc, timeSystem)).toThrow(); | ||||
|             expect(tc.timeSystem()).not.toBe(timeSystem); | ||||
|         }); | ||||
|  | ||||
|         it("Emits an event when time system changes", function () { | ||||
|             expect(eventListener).not.toHaveBeenCalled(); | ||||
|             tc.on("timeSystem", eventListener); | ||||
|             tc.timeSystem(timeSystem, bounds); | ||||
|             expect(eventListener).toHaveBeenCalledWith(timeSystem); | ||||
|         }); | ||||
|  | ||||
|         it("Emits an event when time of interest changes", function () { | ||||
|             expect(eventListener).not.toHaveBeenCalled(); | ||||
|             tc.on("timeOfInterest", eventListener); | ||||
|             tc.timeOfInterest(toi); | ||||
|             expect(eventListener).toHaveBeenCalledWith(toi); | ||||
|         }); | ||||
|  | ||||
|         it("Emits an event when bounds change", function () { | ||||
|             expect(eventListener).not.toHaveBeenCalled(); | ||||
|             tc.on("bounds", eventListener); | ||||
|             tc.bounds(bounds); | ||||
|             expect(eventListener).toHaveBeenCalledWith(bounds); | ||||
|         }); | ||||
|  | ||||
|         it("Emits an event when follow mode changes", function () { | ||||
|             expect(eventListener).not.toHaveBeenCalled(); | ||||
|             tc.on("follow", eventListener); | ||||
|             tc.follow(follow); | ||||
|             expect(eventListener).toHaveBeenCalledWith(follow); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										59
									
								
								src/api/Type.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/api/Type.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(function () { | ||||
|     /** | ||||
|      * @typedef TypeDefinition | ||||
|      * @memberof module:openmct.Type~ | ||||
|      * @property {Metadata} metadata displayable metadata about this type | ||||
|      * @property {function (object)} [initialize] a function which initializes | ||||
|      *           the model for new domain objects of this type | ||||
|      * @property {boolean} [creatable] true if users should be allowed to | ||||
|      *           create this type (default: false) | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * A Type describes a kind of domain object that may appear or be | ||||
|      * created within Open MCT. | ||||
|      * | ||||
|      * @param {module:opemct.Type~TypeDefinition} definition | ||||
|      * @class Type | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function Type(definition) { | ||||
|         this.definition = definition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if a domain object is an instance of this type. | ||||
|      * @param domainObject | ||||
|      * @returns {boolean} true if the domain object is of this type | ||||
|      * @memberof module:openmct.Type# | ||||
|      * @method check | ||||
|      */ | ||||
|     Type.prototype.check = function (domainObject) { | ||||
|         // Depends on assignment from MCT. | ||||
|         return domainObject.type === this.key; | ||||
|     }; | ||||
|  | ||||
|     return Type; | ||||
| }); | ||||
							
								
								
									
										52
									
								
								src/api/api.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/api/api.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     './Type', | ||||
|     './TimeConductor', | ||||
|     './objects/ObjectAPI', | ||||
|     './composition/CompositionAPI', | ||||
|     './types/TypeRegistry', | ||||
|     './ui/Dialog', | ||||
|     './ui/GestureAPI', | ||||
|     './telemetry/TelemetryAPI' | ||||
| ], function ( | ||||
|     Type, | ||||
|     TimeConductor, | ||||
|     ObjectAPI, | ||||
|     CompositionAPI, | ||||
|     TypeRegistry, | ||||
|     Dialog, | ||||
|     GestureAPI, | ||||
|     TelemetryAPI | ||||
| ) { | ||||
|     return { | ||||
|         Type: Type, | ||||
|         TimeConductor: TimeConductor, | ||||
|         ObjectAPI: ObjectAPI, | ||||
|         CompositionAPI: CompositionAPI, | ||||
|         Dialog: Dialog, | ||||
|         TypeRegistry: TypeRegistry, | ||||
|         GestureAPI: GestureAPI, | ||||
|         TelemetryAPI: TelemetryAPI | ||||
|     }; | ||||
| }); | ||||
							
								
								
									
										136
									
								
								src/api/composition/CompositionAPI.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/api/composition/CompositionAPI.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'lodash', | ||||
|     'EventEmitter', | ||||
|     './DefaultCompositionProvider', | ||||
|     './CompositionCollection' | ||||
| ], function ( | ||||
|     _, | ||||
|     EventEmitter, | ||||
|     DefaultCompositionProvider, | ||||
|     CompositionCollection | ||||
| ) { | ||||
|     /** | ||||
|      * An interface for interacting with the composition of domain objects. | ||||
|      * The composition of a domain object is the list of other domain objects | ||||
|      * it "contains" (for instance, that should be displayed beneath it | ||||
|      * in the tree.) | ||||
|      * | ||||
|      * @interface CompositionAPI | ||||
|      * @returns {module:openmct.CompositionCollection} | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function CompositionAPI() { | ||||
|         this.registry = []; | ||||
|         this.policies = []; | ||||
|         this.addProvider(new DefaultCompositionProvider()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Add a composition provider. | ||||
|      * | ||||
|      * Plugins can add new composition providers to change the loading | ||||
|      * behavior for certain domain objects. | ||||
|      * | ||||
|      * @method addProvider | ||||
|      * @param {module:openmct.CompositionProvider} provider the provider to add | ||||
|      * @memberof module:openmct.CompositionAPI# | ||||
|      */ | ||||
|     CompositionAPI.prototype.addProvider = function (provider) { | ||||
|         this.registry.unshift(provider); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Retrieve the composition (if any) of this domain object. | ||||
|      * | ||||
|      * @method get | ||||
|      * @returns {module:openmct.CompositionCollection} | ||||
|      * @memberof module:openmct.CompositionAPI# | ||||
|      */ | ||||
|     CompositionAPI.prototype.get = function (domainObject) { | ||||
|         var provider = _.find(this.registry, function (p) { | ||||
|             return p.appliesTo(domainObject); | ||||
|         }); | ||||
|  | ||||
|         if (!provider) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         return new CompositionCollection(domainObject, provider); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * A composition policy is a function which either allows or disallows | ||||
|      * placing one object in another's composition. | ||||
|      * | ||||
|      * Open MCT's policy model requires consensus, so any one policy may | ||||
|      * reject composition by returning false. As such, policies should | ||||
|      * generally be written to return true in the default case. | ||||
|      * | ||||
|      * @callback CompositionPolicy | ||||
|      * @memberof module:openmct.CompositionAPI~ | ||||
|      * @param {module:openmct.DomainObject} containingObject the object which | ||||
|      *        would act as a container | ||||
|      * @param {module:openmct.DomainObject} containedObject the object which | ||||
|      *        would be contained | ||||
|      * @returns {boolean} false if this composition should be disallowed | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Add a composition policy. Composition policies may disallow domain | ||||
|      * objects from containing other domain objects. | ||||
|      * | ||||
|      * @method addPolicy | ||||
|      * @param {module:openmct.CompositionAPI~CompositionPolicy} policy | ||||
|      *        the policy to add | ||||
|      * @memberof module:openmct.CompositionAPI# | ||||
|      */ | ||||
|     CompositionAPI.prototype.addPolicy = function (policy) { | ||||
|         this.policies.push(policy); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Check whether or not a domain object is allowed to contain another | ||||
|      * domain object. | ||||
|      * | ||||
|      * @private | ||||
|      * @method checkPolicy | ||||
|      * @param {module:openmct.DomainObject} containingObject the object which | ||||
|      *        would act as a container | ||||
|      * @param {module:openmct.DomainObject} containedObject the object which | ||||
|      *        would be contained | ||||
|      * @returns {boolean} false if this composition should be disallowed | ||||
|  | ||||
|      * @param {module:openmct.CompositionAPI~CompositionPolicy} policy | ||||
|      *        the policy to add | ||||
|      * @memberof module:openmct.CompositionAPI# | ||||
|      */ | ||||
|     CompositionAPI.prototype.checkPolicy = function (container, containee) { | ||||
|         return this.policies.every(function (policy) { | ||||
|             return policy(container, containee); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     return CompositionAPI; | ||||
| }); | ||||
							
								
								
									
										231
									
								
								src/api/composition/CompositionCollection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								src/api/composition/CompositionCollection.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'EventEmitter', | ||||
|     'lodash', | ||||
|     '../objects/object-utils' | ||||
| ], function ( | ||||
|     EventEmitter, | ||||
|     _, | ||||
|     objectUtils | ||||
| ) { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * A CompositionCollection represents the list of domain objects contained | ||||
|      * by another domain object. It provides methods for loading this | ||||
|      * list asynchronously, and for modifying this list. | ||||
|      * | ||||
|      * @interface CompositionCollection | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain object | ||||
|      *        whose composition will be contained | ||||
|      * @param {module:openmct.CompositionProvider} provider the provider | ||||
|      *        to use to retrieve other domain objects | ||||
|      * @param {module:openmct.CompositionAPI} api the composition API, for | ||||
|      *        policy checks | ||||
|      * @memberof module:openmct | ||||
|      * @augments EventEmitter | ||||
|      */ | ||||
|     function CompositionCollection(domainObject, provider, api) { | ||||
|         EventEmitter.call(this); | ||||
|         this.domainObject = domainObject; | ||||
|         this.provider = provider; | ||||
|         this.api = api; | ||||
|         if (this.provider.on) { | ||||
|             this.provider.on( | ||||
|                 this.domainObject, | ||||
|                 'add', | ||||
|                 this.onProviderAdd, | ||||
|                 this | ||||
|             ); | ||||
|             this.provider.on( | ||||
|                 this.domainObject, | ||||
|                 'remove', | ||||
|                 this.onProviderRemove, | ||||
|                 this | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     CompositionCollection.prototype = Object.create(EventEmitter.prototype); | ||||
|  | ||||
|     CompositionCollection.prototype.onProviderAdd = function (child) { | ||||
|         this.add(child, true); | ||||
|     }; | ||||
|  | ||||
|     CompositionCollection.prototype.onProviderRemove = function (child) { | ||||
|         this.remove(child, true); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Get the index of a domain object within this composition. If the | ||||
|      * domain object is not contained here, -1 will be returned. | ||||
|      * | ||||
|      * A call to [load]{@link module:openmct.CompositionCollection#load} | ||||
|      * must have resolved before using this method. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} child the domain object for which | ||||
|      *        an index should be retrieved | ||||
|      * @returns {number} the index of that domain object | ||||
|      * @memberof module:openmct.CompositionCollection# | ||||
|      * @name indexOf | ||||
|      */ | ||||
|     CompositionCollection.prototype.indexOf = function (child) { | ||||
|         return _.findIndex(this.loadedChildren, function (other) { | ||||
|             return objectUtils.equals(child, other); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Get the index of a domain object within this composition. | ||||
|      * | ||||
|      * A call to [load]{@link module:openmct.CompositionCollection#load} | ||||
|      * must have resolved before using this method. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} child the domain object for which | ||||
|      *        containment should be checked | ||||
|      * @returns {boolean} true if the domain object is contained here | ||||
|      * @memberof module:openmct.CompositionCollection# | ||||
|      * @name contains | ||||
|      */ | ||||
|     CompositionCollection.prototype.contains = function (child) { | ||||
|         return this.indexOf(child) !== -1; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Check if a domain object can be added to this composition. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} child the domain object to add | ||||
|      * @memberof module:openmct.CompositionCollection# | ||||
|      * @name canContain | ||||
|      */ | ||||
|     CompositionCollection.prototype.canContain = function (domainObject) { | ||||
|         return this.api.checkPolicy(this.domainObject, domainObject); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Add a domain object to this composition. | ||||
|      * | ||||
|      * A call to [load]{@link module:openmct.CompositionCollection#load} | ||||
|      * must have resolved before using this method. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} child the domain object to add | ||||
|      * @param {boolean} skipMutate true if the underlying provider should | ||||
|      *        not be updated | ||||
|      * @memberof module:openmct.CompositionCollection# | ||||
|      * @name add | ||||
|      */ | ||||
|     CompositionCollection.prototype.add = function (child, skipMutate) { | ||||
|         if (!this.loadedChildren) { | ||||
|             throw new Error("Must load composition before you can add!"); | ||||
|         } | ||||
|         if (!this.canContain(child)) { | ||||
|             throw new Error("This object cannot contain that object."); | ||||
|         } | ||||
|         if (this.contains(child)) { | ||||
|             if (skipMutate) { | ||||
|                 return; // don't add twice, don't error. | ||||
|             } | ||||
|             throw new Error("Unable to add child: already in composition"); | ||||
|         } | ||||
|         this.loadedChildren.push(child); | ||||
|         this.emit('add', child); | ||||
|         if (!skipMutate) { | ||||
|             // add after we have added. | ||||
|             this.provider.add(this.domainObject, child); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Load the domain objects in this composition. | ||||
|      * | ||||
|      * @returns {Promise.<Array.<module:openmct.DomainObject>>} a promise for | ||||
|      *          the domain objects in this composition | ||||
|      * @memberof {module:openmct.CompositionCollection#} | ||||
|      * @name load | ||||
|      */ | ||||
|     CompositionCollection.prototype.load = function () { | ||||
|         return this.provider.load(this.domainObject) | ||||
|             .then(function (children) { | ||||
|                 this.loadedChildren = []; | ||||
|                 children.map(function (c) { | ||||
|                     this.add(c, true); | ||||
|                 }, this); | ||||
|                 this.emit('load'); | ||||
|                 return this.loadedChildren.slice(); | ||||
|             }.bind(this)); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Remove a domain object from this composition. | ||||
|      * | ||||
|      * A call to [load]{@link module:openmct.CompositionCollection#load} | ||||
|      * must have resolved before using this method. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} child the domain object to remove | ||||
|      * @param {boolean} skipMutate true if the underlying provider should | ||||
|      *        not be updated | ||||
|      * @memberof module:openmct.CompositionCollection# | ||||
|      * @name remove | ||||
|      */ | ||||
|     CompositionCollection.prototype.remove = function (child, skipMutate) { | ||||
|         if (!this.contains(child)) { | ||||
|             if (skipMutate) { | ||||
|                 return; | ||||
|             } | ||||
|             throw new Error("Unable to remove child: not found in composition"); | ||||
|         } | ||||
|         var index = this.indexOf(child); | ||||
|         var removed = this.loadedChildren.splice(index, 1)[0]; | ||||
|         this.emit('remove', index, child); | ||||
|         if (!skipMutate) { | ||||
|             // trigger removal after we have internally removed it. | ||||
|             this.provider.remove(this.domainObject, removed); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Stop using this composition collection. This will release any resources | ||||
|      * associated with this collection. | ||||
|      * @name destroy | ||||
|      * @memberof module:openmct.CompositionCollection# | ||||
|      */ | ||||
|     CompositionCollection.prototype.destroy = function () { | ||||
|         if (this.provider.off) { | ||||
|             this.provider.off( | ||||
|                 this.domainObject, | ||||
|                 'add', | ||||
|                 this.onProviderAdd, | ||||
|                 this | ||||
|             ); | ||||
|             this.provider.off( | ||||
|                 this.domainObject, | ||||
|                 'remove', | ||||
|                 this.onProviderRemove, | ||||
|                 this | ||||
|             ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     return CompositionCollection; | ||||
| }); | ||||
							
								
								
									
										150
									
								
								src/api/composition/DefaultCompositionProvider.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								src/api/composition/DefaultCompositionProvider.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'lodash', | ||||
|     'EventEmitter', | ||||
|     '../objects/ObjectAPI', | ||||
|     '../objects/object-utils' | ||||
| ], function ( | ||||
|     _, | ||||
|     EventEmitter, | ||||
|     ObjectAPI, | ||||
|     objectUtils | ||||
| ) { | ||||
|     /** | ||||
|      * A CompositionProvider provides the underlying implementation of | ||||
|      * composition-related behavior for certain types of domain object. | ||||
|      * | ||||
|      * @interface CompositionProvider | ||||
|      * @memberof module:openmct | ||||
|      * @augments EventEmitter | ||||
|      */ | ||||
|  | ||||
|     function makeEventName(domainObject, event) { | ||||
|         return event + ':' + objectUtils.makeKeyString(domainObject.key); | ||||
|     } | ||||
|  | ||||
|     function DefaultCompositionProvider() { | ||||
|         EventEmitter.call(this); | ||||
|     } | ||||
|  | ||||
|     DefaultCompositionProvider.prototype = | ||||
|         Object.create(EventEmitter.prototype); | ||||
|  | ||||
|     /** | ||||
|      * Check if this provider should be used to load composition for a | ||||
|      * particular domain object. | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain object | ||||
|      *        to check | ||||
|      * @returns {boolean} true if this provider can provide | ||||
|      *          composition for a given domain object | ||||
|      * @memberof module:openmct.CompositionProvider# | ||||
|      * @method appliesTo | ||||
|      */ | ||||
|     DefaultCompositionProvider.prototype.appliesTo = function (domainObject) { | ||||
|         return !!domainObject.composition; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Load any domain objects contained in the composition of this domain | ||||
|      * object. | ||||
|      * @param {module:openmct.DomainObjcet} domainObject the domain object | ||||
|      *        for which to load composition | ||||
|      * @returns {Promise.<Array.<module:openmct.DomainObject>>} a promise for | ||||
|      *          the domain objects in this composition | ||||
|      * @memberof module:openmct.CompositionProvider# | ||||
|      * @method load | ||||
|      */ | ||||
|     DefaultCompositionProvider.prototype.load = function (domainObject) { | ||||
|         return Promise.all(domainObject.composition.map(ObjectAPI.get)); | ||||
|     }; | ||||
|  | ||||
|     DefaultCompositionProvider.prototype.on = function ( | ||||
|         domainObject, | ||||
|         event, | ||||
|         listener, | ||||
|         context | ||||
|     ) { | ||||
|         // these can likely be passed through to the mutation service instead | ||||
|         // of using an eventemitter. | ||||
|         this.addListener( | ||||
|             makeEventName(domainObject, event), | ||||
|             listener, | ||||
|             context | ||||
|         ); | ||||
|     }; | ||||
|  | ||||
|     DefaultCompositionProvider.prototype.off = function ( | ||||
|         domainObject, | ||||
|         event, | ||||
|         listener, | ||||
|         context | ||||
|     ) { | ||||
|         // these can likely be passed through to the mutation service instead | ||||
|         // of using an eventemitter. | ||||
|         this.removeListener( | ||||
|             makeEventName(domainObject, event), | ||||
|             listener, | ||||
|             context | ||||
|         ); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Remove a domain object from another domain object's composition. | ||||
|      * | ||||
|      * This method is optional; if not present, adding to a domain object's | ||||
|      * composition using this provider will be disallowed. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain object | ||||
|      *        which should have its composition modified | ||||
|      * @param {module:openmct.DomainObject} child the domain object to remove | ||||
|      * @memberof module:openmct.CompositionProvider# | ||||
|      * @method remove | ||||
|      */ | ||||
|     DefaultCompositionProvider.prototype.remove = function (domainObject, child) { | ||||
|         // TODO: this needs to be synchronized via mutation | ||||
|         var index = domainObject.composition.indexOf(child); | ||||
|         domainObject.composition.splice(index, 1); | ||||
|         this.emit(makeEventName(domainObject, 'remove'), child); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Add a domain object to another domain object's composition. | ||||
|      * | ||||
|      * This method is optional; if not present, adding to a domain object's | ||||
|      * composition using this provider will be disallowed. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain object | ||||
|      *        which should have its composition modified | ||||
|      * @param {module:openmct.DomainObject} child the domain object to add | ||||
|      * @memberof module:openmct.CompositionProvider# | ||||
|      * @method add | ||||
|      */ | ||||
|     DefaultCompositionProvider.prototype.add = function (domainObject, child) { | ||||
|         // TODO: this needs to be synchronized via mutation | ||||
|         domainObject.composition.push(child.key); | ||||
|         this.emit(makeEventName(domainObject, 'add'), child); | ||||
|     }; | ||||
|  | ||||
|     return DefaultCompositionProvider; | ||||
| }); | ||||
							
								
								
									
										128
									
								
								src/api/objects/LegacyObjectAPIInterceptor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/api/objects/LegacyObjectAPIInterceptor.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     './object-utils', | ||||
|     './objectEventEmitter' | ||||
| ], function ( | ||||
|     utils, | ||||
|     objectEventEmitter | ||||
| ) { | ||||
|     function ObjectServiceProvider(objectService, instantiate, topic) { | ||||
|         this.objectService = objectService; | ||||
|         this.instantiate = instantiate; | ||||
|  | ||||
|         this.generalTopic = topic('mutation'); | ||||
|         this.bridgeEventBuses(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Bridges old and new style mutation events to provide compatibility between the two APIs | ||||
|      * @private | ||||
|      */ | ||||
|     ObjectServiceProvider.prototype.bridgeEventBuses = function () { | ||||
|         var removeGeneralTopicListener; | ||||
|         var handleLegacyMutation; | ||||
|  | ||||
|         var handleMutation = function (newStyleObject) { | ||||
|             var keyString = utils.makeKeyString(newStyleObject.key); | ||||
|             var oldStyleObject = this.instantiate(utils.toOldFormat(newStyleObject), keyString); | ||||
|  | ||||
|             // Don't trigger self | ||||
|             removeGeneralTopicListener(); | ||||
|  | ||||
|             oldStyleObject.getCapability('mutation').mutate(function () { | ||||
|                 return utils.toOldFormat(newStyleObject); | ||||
|             }); | ||||
|  | ||||
|             removeGeneralTopicListener = this.generalTopic.listen(handleLegacyMutation); | ||||
|         }.bind(this); | ||||
|  | ||||
|         handleLegacyMutation = function (legacyObject) { | ||||
|             var newStyleObject = utils.toNewFormat(legacyObject.getModel(), legacyObject.getId()); | ||||
|  | ||||
|             //Don't trigger self | ||||
|             objectEventEmitter.off('mutation', handleMutation); | ||||
|             objectEventEmitter.emit(newStyleObject.key.identifier + ":*", newStyleObject); | ||||
|             objectEventEmitter.on('mutation', handleMutation); | ||||
|         }.bind(this); | ||||
|  | ||||
|         objectEventEmitter.on('mutation', handleMutation); | ||||
|         removeGeneralTopicListener = this.generalTopic.listen(handleLegacyMutation); | ||||
|     }; | ||||
|  | ||||
|     ObjectServiceProvider.prototype.save = function (object) { | ||||
|         var key = object.key; | ||||
|  | ||||
|         return object.getCapability('persistence') | ||||
|                 .persist() | ||||
|                 .then(function () { | ||||
|                     return utils.toNewFormat(object, key); | ||||
|                 }); | ||||
|     }; | ||||
|  | ||||
|     ObjectServiceProvider.prototype.delete = function (object) { | ||||
|         // TODO! | ||||
|     }; | ||||
|  | ||||
|     ObjectServiceProvider.prototype.get = function (key) { | ||||
|         var keyString = utils.makeKeyString(key); | ||||
|         return this.objectService.getObjects([keyString]) | ||||
|             .then(function (results) { | ||||
|                 var model = results[keyString].getModel(); | ||||
|                 return utils.toNewFormat(model, key); | ||||
|             }); | ||||
|     }; | ||||
|  | ||||
|     // Injects new object API as a decorator so that it hijacks all requests. | ||||
|     // Object providers implemented on new API should just work, old API should just work, many things may break. | ||||
|     function LegacyObjectAPIInterceptor(openmct, ROOTS, instantiate, topic, objectService) { | ||||
|         this.getObjects = function (keys) { | ||||
|             var results = {}, | ||||
|                 promises = keys.map(function (keyString) { | ||||
|                     var key = utils.parseKeyString(keyString); | ||||
|                     return openmct.objects.get(key) | ||||
|                         .then(function (object) { | ||||
|                             object = utils.toOldFormat(object); | ||||
|                             results[keyString] = instantiate(object, keyString); | ||||
|                         }); | ||||
|                 }); | ||||
|  | ||||
|             return Promise.all(promises) | ||||
|                 .then(function () { | ||||
|                     return results; | ||||
|                 }); | ||||
|         }; | ||||
|  | ||||
|         openmct.objects.supersecretSetFallbackProvider( | ||||
|             new ObjectServiceProvider(objectService, instantiate, topic) | ||||
|         ); | ||||
|  | ||||
|         ROOTS.forEach(function (r) { | ||||
|             openmct.objects.addRoot(utils.parseKeyString(r.id)); | ||||
|         }); | ||||
|  | ||||
|         return this; | ||||
|     } | ||||
|  | ||||
|     return LegacyObjectAPIInterceptor; | ||||
| }); | ||||
							
								
								
									
										90
									
								
								src/api/objects/MutableObject.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/api/objects/MutableObject.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'lodash', | ||||
|     './objectEventEmitter' | ||||
| ], function ( | ||||
|     _, | ||||
|     objectEventEmitter | ||||
| ) { | ||||
|     var ANY_OBJECT_EVENT = "mutation"; | ||||
|  | ||||
|     /** | ||||
|      * The MutableObject wraps a DomainObject and provides getters and | ||||
|      * setters for | ||||
|      * @param eventEmitter | ||||
|      * @param object | ||||
|      * @interface MutableObject | ||||
|      */ | ||||
|     function MutableObject(object) { | ||||
|         this.object = object; | ||||
|         this.unlisteners = []; | ||||
|     } | ||||
|  | ||||
|     function qualifiedEventName(object, eventName) { | ||||
|         return [object.key.identifier, eventName].join(':'); | ||||
|     } | ||||
|  | ||||
|     MutableObject.prototype.stopListening = function () { | ||||
|         this.unlisteners.forEach(function (unlisten) { | ||||
|             unlisten(); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Observe changes to this domain object. | ||||
|      * @param {string} path the property to observe | ||||
|      * @param {Function} callback a callback to invoke when new values for | ||||
|      *        this property are observed | ||||
|      * @method on | ||||
|      * @memberof module:openmct.MutableObject# | ||||
|      */ | ||||
|     MutableObject.prototype.on = function (path, callback) { | ||||
|         var fullPath = qualifiedEventName(this.object, path); | ||||
|         objectEventEmitter.on(fullPath, callback); | ||||
|         this.unlisteners.push(objectEventEmitter.off.bind(objectEventEmitter, fullPath, callback)); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Modify this domain object. | ||||
|      * @param {string} path the property to modify | ||||
|      * @param {*} value the new value for this property | ||||
|      * @method set | ||||
|      * @memberof module:openmct.MutableObject# | ||||
|      */ | ||||
|     MutableObject.prototype.set = function (path, value) { | ||||
|  | ||||
|         _.set(this.object, path, value); | ||||
|         _.set(this.object, 'modified', Date.now()); | ||||
|  | ||||
|         //Emit event specific to property | ||||
|         objectEventEmitter.emit(qualifiedEventName(this.object, path), value); | ||||
|         //Emit wildcare event | ||||
|         objectEventEmitter.emit(qualifiedEventName(this.object, '*'), this.object); | ||||
|  | ||||
|         //Emit a general "any object" event | ||||
|         objectEventEmitter.emit(ANY_OBJECT_EVENT, this.object); | ||||
|     }; | ||||
|  | ||||
|     return MutableObject; | ||||
| }); | ||||
							
								
								
									
										234
									
								
								src/api/objects/ObjectAPI.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								src/api/objects/ObjectAPI.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'lodash', | ||||
|     './object-utils', | ||||
|     './MutableObject' | ||||
| ], function ( | ||||
|     _, | ||||
|     utils, | ||||
|     MutableObject | ||||
| ) { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Utilities for loading, saving, and manipulating domain objects. | ||||
|      * @interface ObjectAPI | ||||
|      * @memberof module:openmct | ||||
|      * @implements {module:openmct.ObjectProvider} | ||||
|      */ | ||||
|  | ||||
|     function ObjectAPI() { | ||||
|         this.providers = {}; | ||||
|         this.rootRegistry = []; | ||||
|         this.rootProvider = { | ||||
|             'get': function () { | ||||
|                 return Promise.resolve({ | ||||
|                     name: 'The root object', | ||||
|                     type: 'root', | ||||
|                     composition: this.rootRegistry | ||||
|                 }); | ||||
|             }.bind(this) | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     ObjectAPI.prototype.supersecretSetFallbackProvider = function (p) { | ||||
|         this.fallbackProvider = p; | ||||
|     }; | ||||
|  | ||||
|     // Retrieve the provider for a given key. | ||||
|     ObjectAPI.prototype.getProvider = function (key) { | ||||
|         if (key.identifier === 'ROOT') { | ||||
|             return this.rootProvider; | ||||
|         } | ||||
|         return this.providers[key.namespace] || this.fallbackProvider; | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Register a new object provider for a particular namespace. | ||||
|      * | ||||
|      * @param {string} namespace the namespace for which to provide objects | ||||
|      * @param {module:openmct.ObjectProvider} provider the provider which | ||||
|      *        will handle loading domain objects from this namespace | ||||
|      * @memberof {module:openmct.ObjectAPI#} | ||||
|      * @name addProvider | ||||
|      */ | ||||
|     ObjectAPI.prototype.addProvider = function (namespace, provider) { | ||||
|         this.providers[namespace] = provider; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Provides the ability to read, write, and delete domain objects. | ||||
|      * | ||||
|      * When registering a new object provider, all methods on this interface | ||||
|      * are optional. | ||||
|      * | ||||
|      * @interface ObjectProvider | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Save this domain object in its current state. | ||||
|      * | ||||
|      * @method save | ||||
|      * @memberof module:openmct.ObjectProvider# | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain object to | ||||
|      *        save | ||||
|      * @returns {Promise} a promise which will resolve when the domain object | ||||
|      *          has been saved, or be rejected if it cannot be saved | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Delete this domain object. | ||||
|      * | ||||
|      * @method delete | ||||
|      * @memberof module:openmct.ObjectProvider# | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain object to | ||||
|      *        delete | ||||
|      * @returns {Promise} a promise which will resolve when the domain object | ||||
|      *          has been deleted, or be rejected if it cannot be deleted | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Get a domain object. | ||||
|      * | ||||
|      * @method get | ||||
|      * @memberof module:openmct.ObjectProvider# | ||||
|      * @param {string} key the key for the domain object to load | ||||
|      * @returns {Promise} a promise which will resolve when the domain object | ||||
|      *          has been saved, or be rejected if it cannot be saved | ||||
|      */ | ||||
|  | ||||
|     [ | ||||
|         'save', | ||||
|         'delete', | ||||
|         'get' | ||||
|     ].forEach(function (method) { | ||||
|         ObjectAPI.prototype[method] = function () { | ||||
|             var key = arguments[0], | ||||
|                 provider = this.getProvider(key); | ||||
|  | ||||
|             if (!provider) { | ||||
|                 throw new Error('No Provider Matched'); | ||||
|             } | ||||
|  | ||||
|             if (!provider[method]) { | ||||
|                 throw new Error('Provider does not support [' + method + '].'); | ||||
|             } | ||||
|  | ||||
|             return provider[method].apply(provider, arguments); | ||||
|         }; | ||||
|     }); | ||||
|  | ||||
|     /** | ||||
|      * Add a root-level object. | ||||
|      * @param {module:openmct.DomainObject} domainObject the root-level object | ||||
|      *        to add. | ||||
|      * @method addRoot | ||||
|      * @memberof module:openmct.ObjectAPI# | ||||
|      */ | ||||
|     ObjectAPI.prototype.addRoot = function (key) { | ||||
|         this.rootRegistry.unshift(key); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Remove a root-level object. | ||||
|      * @param {module:openmct.ObjectAPI~Identifier} id the identifier of the | ||||
|      *        root-level object to remove. | ||||
|      * @method removeRoot | ||||
|      * @memberof module:openmct.ObjectAPI# | ||||
|      */ | ||||
|     ObjectAPI.prototype.removeRoot = function (key) { | ||||
|         this.rootRegistry = this.rootRegistry.filter(function (k) { | ||||
|             return ( | ||||
|                 k.identifier !== key.identifier || | ||||
|                 k.namespace !== key.namespace | ||||
|             ); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Modify a domain object. | ||||
|      * @param {module:openmct.DomainObject} object the object to mutate | ||||
|      * @param {string} path the property to modify | ||||
|      * @param {*} value the new value for this property | ||||
|      * @method mutate | ||||
|      * @memberof module:openmct.ObjectAPI# | ||||
|      */ | ||||
|     ObjectAPI.prototype.mutate = function (domainObject, path, value) { | ||||
|         return new MutableObject(domainObject).set(path, value); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Observe changes to a domain object. | ||||
|      * @param {module:openmct.DomainObject} object the object to observe | ||||
|      * @param {string} path the property to observe | ||||
|      * @param {Function} callback a callback to invoke when new values for | ||||
|      *        this property are observed | ||||
|      * @method observe | ||||
|      * @memberof module:openmct.ObjectAPI# | ||||
|      */ | ||||
|     ObjectAPI.prototype.observe = function (domainObject, path, callback) { | ||||
|         var mutableObject = new MutableObject(domainObject); | ||||
|         mutableObject.on(path, callback); | ||||
|         return mutableObject.stopListening.bind(mutableObject); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Uniquely identifies a domain object. | ||||
|      * | ||||
|      * @typedef Identifier | ||||
|      * @memberof module:openmct.ObjectAPI~ | ||||
|      * @property {string} namespace the namespace to/from which this domain | ||||
|      *           object should be loaded/stored. | ||||
|      * @property {string} key a unique identifier for the domain object | ||||
|      *           within that namespace | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * A domain object is an entity of relevance to a user's workflow, that | ||||
|      * should appear as a distinct and meaningful object within the user | ||||
|      * interface. Examples of domain objects are folders, telemetry sensors, | ||||
|      * and so forth. | ||||
|      * | ||||
|      * A few common properties are defined for domain objects. Beyond these, | ||||
|      * individual types of domain objects may add more as they see fit. | ||||
|      * | ||||
|      * @property {module:openmct.ObjectAPI~Identifier} identifier a key/namespace pair which | ||||
|      *           uniquely identifies this domain object | ||||
|      * @property {string} type the type of domain object | ||||
|      * @property {string} name the human-readable name for this domain object | ||||
|      * @property {string} [creator] the user name of the creator of this domain | ||||
|      *           object | ||||
|      * @property {number} [modified] the time, in milliseconds since the UNIX | ||||
|      *           epoch, at which this domain object was last modified | ||||
|      * @property {module:openmct.ObjectAPI~Identifier[]} [composition] if | ||||
|      *           present, this will be used by the default composition provider | ||||
|      *           to load domain objects | ||||
|      * @typedef DomainObject | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|  | ||||
|     return ObjectAPI; | ||||
| }); | ||||
							
								
								
									
										51
									
								
								src/api/objects/bundle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/api/objects/bundle.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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 define*/ | ||||
|  | ||||
| define([ | ||||
|     './LegacyObjectAPIInterceptor', | ||||
|     'legacyRegistry' | ||||
| ], function ( | ||||
|     LegacyObjectAPIInterceptor, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|     legacyRegistry.register('src/api/objects', { | ||||
|         name: 'Object API', | ||||
|         description: 'The public Objects API', | ||||
|         extensions: { | ||||
|             components: [ | ||||
|                 { | ||||
|                     provides: "objectService", | ||||
|                     type: "decorator", | ||||
|                     priority: "mandatory", | ||||
|                     implementation: LegacyObjectAPIInterceptor, | ||||
|                     depends: [ | ||||
|                         "openmct", | ||||
|                         "roots[]", | ||||
|                         "instantiate", | ||||
|                         "topic" | ||||
|                     ] | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										109
									
								
								src/api/objects/object-utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/api/objects/object-utils.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|  | ||||
| ], function ( | ||||
|  | ||||
| ) { | ||||
|  | ||||
|     // take a key string and turn it into a key object | ||||
|     // 'scratch:root' ==> {namespace: 'scratch', identifier: 'root'} | ||||
|     var parseKeyString = function (key) { | ||||
|         if (typeof key === 'object') { | ||||
|             return key; | ||||
|         } | ||||
|         var namespace = '', | ||||
|             identifier = key; | ||||
|         for (var i = 0, escaped = false; i < key.length; i++) { | ||||
|             if (escaped) { | ||||
|                 escaped = false; | ||||
|                 namespace += key[i]; | ||||
|             } else { | ||||
|                 if (key[i] === "\\") { | ||||
|                     escaped = true; | ||||
|                 } else if (key[i] === ":") { | ||||
|                     // namespace = key.slice(0, i); | ||||
|                     identifier = key.slice(i + 1); | ||||
|                     break; | ||||
|                 } | ||||
|                 namespace += key[i]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (key === namespace) { | ||||
|             namespace = ''; | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             namespace: namespace, | ||||
|             identifier: identifier | ||||
|         }; | ||||
|     }; | ||||
|  | ||||
|     // take a key and turn it into a key string | ||||
|     // {namespace: 'scratch', identifier: 'root'} ==> 'scratch:root' | ||||
|     var makeKeyString = function (key) { | ||||
|         if (typeof key === 'string') { | ||||
|             return key; | ||||
|         } | ||||
|         if (!key.namespace) { | ||||
|             return key.identifier; | ||||
|         } | ||||
|         return [ | ||||
|             key.namespace.replace(':', '\\:'), | ||||
|             key.identifier.replace(':', '\\:') | ||||
|         ].join(':'); | ||||
|     }; | ||||
|  | ||||
|     // Converts composition to use key strings instead of keys | ||||
|     var toOldFormat = function (model) { | ||||
|         model = JSON.parse(JSON.stringify(model)); | ||||
|         delete model.key; | ||||
|         if (model.composition) { | ||||
|             model.composition = model.composition.map(makeKeyString); | ||||
|         } | ||||
|         return model; | ||||
|     }; | ||||
|  | ||||
|     // converts composition to use keys instead of key strings | ||||
|     var toNewFormat = function (model, key) { | ||||
|         model = JSON.parse(JSON.stringify(model)); | ||||
|         model.key = key; | ||||
|         if (model.composition) { | ||||
|             model.composition = model.composition.map(parseKeyString); | ||||
|         } | ||||
|         return model; | ||||
|     }; | ||||
|  | ||||
|     var equals = function (a, b) { | ||||
|         return makeKeyString(a.key) === makeKeyString(b.key); | ||||
|     }; | ||||
|  | ||||
|     return { | ||||
|         toOldFormat: toOldFormat, | ||||
|         toNewFormat: toNewFormat, | ||||
|         makeKeyString: makeKeyString, | ||||
|         parseKeyString: parseKeyString, | ||||
|         equals: equals | ||||
|     }; | ||||
| }); | ||||
							
								
								
									
										32
									
								
								src/api/objects/objectEventEmitter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/api/objects/objectEventEmitter.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     "EventEmitter" | ||||
| ], function ( | ||||
|     EventEmitter | ||||
| ) { | ||||
|     /** | ||||
|      * Provides a singleton event bus for sharing between objects. | ||||
|      */ | ||||
|     return new EventEmitter(); | ||||
| }); | ||||
							
								
								
									
										319
									
								
								src/api/telemetry/TelemetryAPI.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								src/api/telemetry/TelemetryAPI.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,319 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'lodash', | ||||
|     'EventEmitter' | ||||
| ], function ( | ||||
|     _, | ||||
|     EventEmitter | ||||
| ) { | ||||
|     /** | ||||
|      * A LimitEvaluator may be used to detect when telemetry values | ||||
|      * have exceeded nominal conditions. | ||||
|      * | ||||
|      * @interface LimitEvaluator | ||||
|      * @memberof module:openmct.TelemetryAPI~ | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Check for any limit violations associated with a telemetry datum. | ||||
|      * @method evaluate | ||||
|      * @param {*} datum the telemetry datum to evaluate | ||||
|      * @param {TelemetryProperty} the property to check for limit violations | ||||
|      * @memberof module:openmct.TelemetryAPI~LimitEvaluator | ||||
|      * @returns {module:openmct.TelemetryAPI~LimitViolation} metadata about | ||||
|      *          the limit violation, or undefined if a value is within limits | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * A violation of limits defined for a telemetry property. | ||||
|      * @typedef LimitViolation | ||||
|      * @memberof {module:openmct.TelemetryAPI~} | ||||
|      * @property {string} cssclass the class (or space-separated classes) to | ||||
|      *           apply to display elements for values which violate this limit | ||||
|      * @property {string} name the human-readable name for the limit violation | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * A TelemetryFormatter converts telemetry values for purposes of | ||||
|      * display as text. | ||||
|      * | ||||
|      * @interface TelemetryFormatter | ||||
|      * @memberof module:openmct.TelemetryAPI~ | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Retrieve the 'key' from the datum and format it accordingly to | ||||
|      * telemetry metadata in domain object. | ||||
|      * | ||||
|      * @method format | ||||
|      * @memberof module:openmct.TelemetryAPI~TelemetryFormatter# | ||||
|      */ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     // format map is a placeholder until we figure out format service. | ||||
|     var FORMAT_MAP = { | ||||
|         generic: function (range) { | ||||
|             return function (datum) { | ||||
|                 return datum[range.key]; | ||||
|             }; | ||||
|         }, | ||||
|         enum: function (range) { | ||||
|             var enumMap = _.indexBy(range.enumerations, 'value'); | ||||
|             return function (datum) { | ||||
|                 try { | ||||
|                     return enumMap[datum[range.valueKey]].text; | ||||
|                 } catch (e) { | ||||
|                     return datum[range.valueKey]; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     FORMAT_MAP.number = | ||||
|         FORMAT_MAP.float = | ||||
|         FORMAT_MAP.integer = | ||||
|         FORMAT_MAP.ascii = | ||||
|         FORMAT_MAP.generic; | ||||
|  | ||||
|     /** | ||||
|      * Describes a property which would be found in a datum of telemetry | ||||
|      * associated with a particular domain object. | ||||
|      * | ||||
|      * @typedef TelemetryProperty | ||||
|      * @memberof module:openmct.TelemetryAPI~ | ||||
|      * @property {string} key the name of the property in the datum which | ||||
|      *           contains this telemetry value | ||||
|      * @property {string} name the human-readable name for this property | ||||
|      * @property {string} [units] the units associated with this property | ||||
|      * @property {boolean} [temporal] true if this property is a timestamp, or | ||||
|      *           may be otherwise used to order telemetry in a time-like | ||||
|      *           fashion; default is false | ||||
|      * @property {boolean} [numeric] true if the values for this property | ||||
|      *           can be interpreted plainly as numbers; default is true | ||||
|      * @property {boolean} [enumerated] true if this property may have only | ||||
|      *           certain specific values; default is false | ||||
|      * @property {string} [values] for enumerated states, an ordered list | ||||
|      *           of possible values | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Describes and bounds requests for telemetry data. | ||||
|      * | ||||
|      * @typedef TelemetryRequest | ||||
|      * @memberof module:openmct.TelemetryAPI~ | ||||
|      * @property {string} sort the key of the property to sort by. This may | ||||
|      *           be prefixed with a "+" or a "-" sign to sort in ascending | ||||
|      *           or descending order respectively. If no prefix is present, | ||||
|      *           ascending order will be used. | ||||
|      * @property {*} start the lower bound for values of the sorting property | ||||
|      * @property {*} end the upper bound for values of the sorting property | ||||
|      * @property {string[]} strategies symbolic identifiers for strategies | ||||
|      *           (such as `minmax`) which may be recognized by providers; | ||||
|      *           these will be tried in order until an appropriate provider | ||||
|      *           is found | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Provides telemetry data. To connect to new data sources, new | ||||
|      * TelemetryProvider implementations should be | ||||
|      * [registered]{@link module:openmct.TelemetryAPI#addProvider}. | ||||
|      * | ||||
|      * @interface TelemetryProvider | ||||
|      * @memberof module:openmct.TelemetryAPI~ | ||||
|      */ | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * An interface for retrieving telemetry data associated with a domain | ||||
|      * object. | ||||
|      * | ||||
|      * @interface TelemetryAPI | ||||
|      * @augments module:openmct.TelemetryAPI~TelemetryProvider | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function TelemetryAPI() { | ||||
|         this.providersByStrategy = {}; | ||||
|         this.defaultProviders = []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if this provider can supply telemetry data associated with | ||||
|      * this domain object. | ||||
|      * | ||||
|      * @method canProvideTelemetry | ||||
|      * @param {module:openmct.DomainObject} domainObject the object for | ||||
|      *        which telemetry would be provided | ||||
|      * @returns {boolean} true if telemetry can be provided | ||||
|      * @memberof module:openmct.TelemetryAPI~TelemetryProvider# | ||||
|      */ | ||||
|     TelemetryAPI.prototype.canProvideTelemetry = function (domainObject) { | ||||
|         return this.defaultProviders.some(function (provider) { | ||||
|             return provider.canProvideTelemetry(domainObject); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Register a telemetry provider with the telemetry service. This | ||||
|      * allows you to connect alternative telemetry sources. | ||||
|      * @method addProvider | ||||
|      * @memberof module:openmct.TelemetryAPI# | ||||
|      * @param {module:openmct.TelemetryAPI~TelemetryProvider} provider the new | ||||
|      *        telemetry provider | ||||
|      * @param {string} [strategy] the request strategy supported by | ||||
|      *        this provider. If omitted, this will be used as a | ||||
|      *        default provider (when no strategy is requested or no | ||||
|      *        matching strategy is found.) | ||||
|      */ | ||||
|     TelemetryAPI.prototype.addProvider = function (provider, strategy) { | ||||
|         if (!strategy) { | ||||
|             this.defaultProviders.push(provider); | ||||
|         } else { | ||||
|             this.providersByStrategy[strategy] = | ||||
|                 this.providersByStrategy[strategy] || []; | ||||
|             this.providersByStrategy[strategy].push(provider); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     TelemetryAPI.prototype.findProvider = function (domainObject, strategy) { | ||||
|         function supportsDomainObject(provider) { | ||||
|             return provider.canProvideTelemetry(domainObject); | ||||
|         } | ||||
|  | ||||
|         if (strategy) { | ||||
|             var eligibleProviders = | ||||
|                 (this.providersByStrategy[strategy] || []) | ||||
|                     .filter(supportsDomainObject); | ||||
|             if (eligibleProviders.length > 0) { | ||||
|                 return eligibleProviders[0]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return this.defaultProviders.filter(supportsDomainObject)[0]; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Request historical telemetry for a domain object. | ||||
|      * The `options` argument allows you to specify filters | ||||
|      * (start, end, etc.), sort order, and strategies for retrieving | ||||
|      * telemetry (aggregation, latest available, etc.). | ||||
|      * | ||||
|      * @method request | ||||
|      * @memberof module:openmct.TelemetryAPI~TelemetryProvider# | ||||
|      * @param {module:openmct.DomainObject} domainObject the object | ||||
|      *        which has associated telemetry | ||||
|      * @param {module:openmct.TelemetryAPI~TelemetryRequest} options | ||||
|      *        options for this historical request | ||||
|      * @returns {Promise.<object[]>} a promise for an array of | ||||
|      *          telemetry data | ||||
|      */ | ||||
|     TelemetryAPI.prototype.request = function (domainObject, options) { | ||||
|         var provider = this.findProvider(domainObject, options.strategy); | ||||
|         return provider ? | ||||
|             provider.request(domainObject, options) : | ||||
|             Promise.reject([]); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Subscribe to realtime telemetry for a specific domain object. | ||||
|      * The callback will be called whenever data is received from a | ||||
|      * realtime provider. | ||||
|      * | ||||
|      * @method subscribe | ||||
|      * @memberof module:openmct.TelemetryAPI~TelemetryProvider# | ||||
|      * @param {module:openmct.DomainObject} domainObject the object | ||||
|      *        which has associated telemetry | ||||
|      * @param {Function} callback the callback to invoke with new data, as | ||||
|      *        it becomes available | ||||
|      * @param {module:openmct.TelemetryAPI~TelemetryRequest} options | ||||
|      *        options for this request | ||||
|      * @returns {Function} a function which may be called to terminate | ||||
|      *          the subscription | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Get a list of all telemetry properties defined for this | ||||
|      * domain object. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain | ||||
|      *        object for which to request telemetry | ||||
|      * @returns {module:openmct.TelemetryAPI~TelemetryProperty[]} | ||||
|      *          telemetry metadata | ||||
|      * @method properties | ||||
|      * @memberof module:openmct.TelemetryAPI~TelemetryProvider# | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Telemetry formatters help you format telemetry values for | ||||
|      * display. Under the covers, they use telemetry metadata to | ||||
|      * interpret your telemetry data, and then they use the format API | ||||
|      * to format that data for display. | ||||
|      * | ||||
|      * This method is optional. | ||||
|      * If a provider does not implement this method, it is presumed | ||||
|      * that all telemetry associated with this domain object can | ||||
|      * be formatted correctly by string coercion. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain | ||||
|      *        object for which to format telemetry | ||||
|      * @returns {module:openmct.TelemetryAPI~TelemetryFormatter} | ||||
|      * @method formatter | ||||
|      * @memberof module:openmct.TelemetryAPI~TelemetryProvider# | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Get a limit evaluator for this domain object. | ||||
|      * Limit Evaluators help you evaluate limit and alarm status of individual telemetry datums for display purposes without having to interact directly with the Limit API. | ||||
|      * | ||||
|      * This method is optional. | ||||
|      * If a provider does not implement this method, it is presumed | ||||
|      * that no limits are defined for this domain object's telemetry. | ||||
|      * | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain | ||||
|      *        object for which to evaluate limits | ||||
|      * @returns {module:openmct.TelemetryAPI~LimitEvaluator} | ||||
|      * @method limitEvaluator | ||||
|      * @memberof module:openmct.TelemetryAPI~TelemetryProvider# | ||||
|      */ | ||||
|     _.forEach({ | ||||
|         subscribe: undefined, | ||||
|         properties: [], | ||||
|         formatter: undefined, | ||||
|         limitEvaluator: undefined | ||||
|     }, function (defaultValue, method) { | ||||
|         TelemetryAPI.prototype[method] = function (domainObject) { | ||||
|             var provider = this.findProvider(domainObject); | ||||
|             return provider ? | ||||
|                 provider[method].apply(provider, arguments) : | ||||
|                 defaultValue; | ||||
|         }; | ||||
|     }); | ||||
|  | ||||
|     return TelemetryAPI; | ||||
| }); | ||||
							
								
								
									
										45
									
								
								src/api/telemetry/bundle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/api/telemetry/bundle.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     './TelemetryAPI', | ||||
|     'legacyRegistry' | ||||
| ], function ( | ||||
|     TelemetryAPI, | ||||
|     legacyRegistry | ||||
| ) { | ||||
|     legacyRegistry.register('api/telemetry-api', { | ||||
|         name: 'Telemetry API', | ||||
|         description: 'The public Telemetry API', | ||||
|         extensions: { | ||||
|             runs: [ | ||||
|                 { | ||||
|                     key: "TelemetryAPI", | ||||
|                     implementation: TelemetryAPI, | ||||
|                     depends: [ | ||||
|                         'formatService' | ||||
|                     ] | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										51
									
								
								src/api/types/TypeRegistry.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/api/types/TypeRegistry.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([], function () { | ||||
|  | ||||
|     /** | ||||
|      * A TypeRegistry maintains the definitions for different types | ||||
|      * that domain objects may have. | ||||
|      * @interface TypeRegistry | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function TypeRegistry() { | ||||
|         this.types = {}; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Register a new type of view. | ||||
|      * | ||||
|      * @param {string} typeKey a string identifier for this type | ||||
|      * @param {module:openmct.Type} type the type to add | ||||
|      * @method addProvider | ||||
|      * @memberof module:openmct.TypeRegistry# | ||||
|      */ | ||||
|     TypeRegistry.prototype.addType = function (typeKey, type) { | ||||
|         this.types[typeKey] = type; | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     return TypeRegistry; | ||||
| }); | ||||
|  | ||||
|  | ||||
							
								
								
									
										107
									
								
								src/api/ui/Dialog.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/api/ui/Dialog.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(['text!./dialog.html', 'zepto'], function (dialogTemplate, $) { | ||||
|  | ||||
|     /** | ||||
|      * A dialog may be displayed to show blocking content to users. | ||||
|      * @param {module:openmct.View} view the view to show in the dialog | ||||
|      * @param {string} [title] the title for this dialog | ||||
|      * @constructor | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function Dialog(view, title) { | ||||
|         this.view = view; | ||||
|         this.title = title; | ||||
|         this.showing = false; | ||||
|         this.enabledState = true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display this dialog. | ||||
|      * @returns {Promise} a promise that will be resolved if the user | ||||
|      *          chooses "OK", an rejected if the user chooses "cancel" | ||||
|      * @method show | ||||
|      * @memberof module:openmct.Dialog# | ||||
|      */ | ||||
|     Dialog.prototype.show = function () { | ||||
|         if (this.showing) { | ||||
|             throw new Error("Dialog already showing."); | ||||
|         } | ||||
|  | ||||
|         var $body = $('body'); | ||||
|         var $dialog = $(dialogTemplate); | ||||
|         var $contents = $dialog.find('.contents .editor'); | ||||
|         var $close = $dialog.find('.close'); | ||||
|  | ||||
|         var $ok = $dialog.find('.ok'); | ||||
|         var $cancel = $dialog.find('.cancel'); | ||||
|  | ||||
|         if (this.title) { | ||||
|             $dialog.find('.title').text(this.title); | ||||
|         } | ||||
|  | ||||
|         $body.append($dialog); | ||||
|         this.view.show($contents[0]); | ||||
|         this.$dialog = $dialog; | ||||
|         this.$ok = $ok; | ||||
|         this.showing = true; | ||||
|  | ||||
|         [$ok, $cancel, $close].forEach(function ($button) { | ||||
|             $button.on('click', this.hide.bind(this)); | ||||
|         }.bind(this)); | ||||
|  | ||||
|         return new Promise(function (resolve, reject) { | ||||
|             $ok.on('click', resolve); | ||||
|             $cancel.on('click', reject); | ||||
|             $close.on('click', reject); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     Dialog.prototype.hide = function () { | ||||
|         if (!this.showing) { | ||||
|             return; | ||||
|         } | ||||
|         this.$dialog.remove(); | ||||
|         this.view.destroy(); | ||||
|         this.showing = false; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Get or set the "enabled" state of the OK button for this dialog. | ||||
|      * @param {boolean} [state] true to enable, false to disable | ||||
|      * @returns {boolean} true if enabled, false if disabled | ||||
|      * @method enabled | ||||
|      * @memberof module:openmct.Dialog# | ||||
|      */ | ||||
|     Dialog.prototype.enabled = function (state) { | ||||
|         if (state !== undefined) { | ||||
|             this.enabledState = state; | ||||
|             if (this.showing) { | ||||
|                 this.$ok.toggleClass('disabled', !state); | ||||
|             } | ||||
|         } | ||||
|         return this.enabledState; | ||||
|     }; | ||||
|  | ||||
|     return Dialog; | ||||
| }); | ||||
							
								
								
									
										68
									
								
								src/api/ui/GestureAPI.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/api/ui/GestureAPI.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([], function () { | ||||
|     /** | ||||
|      * Allows support for common user actions to be attached to views. | ||||
|      * @interface GestureAPI | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function GestureAPI(selectGesture, contextMenuGesture) { | ||||
|         this.selectGesture = selectGesture; | ||||
|         this.contextMenuGesture = contextMenuGesture; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Designate an HTML element as selectable, and associated with a | ||||
|      * particular object. | ||||
|      * | ||||
|      * @param {HTMLElement} htmlElement the element to make selectable | ||||
|      * @param {*} item the object which should become selected when this | ||||
|      *        element is clicked. | ||||
|      * @returns {Function} a function to remove selectability from this | ||||
|      *          HTML element. | ||||
|      * @method selectable | ||||
|      * @memberof module:openmct.GestureAPI# | ||||
|      */ | ||||
|     GestureAPI.prototype.selectable = function (htmlElement, item) { | ||||
|         return this.selectGesture.apply(htmlElement, item); | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Designate an HTML element as having a context menu associated with | ||||
|      * the provided item. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {HTMLElement} htmlElement the element to make selectable | ||||
|      * @param {*} item the object for which a context menu should appear | ||||
|      * @returns {Function} a function to remove this geture from this | ||||
|      *          HTML element. | ||||
|      * @method selectable | ||||
|      * @memberof module:openmct.GestureAPI# | ||||
|      */ | ||||
|     GestureAPI.prototype.contextMenu = function (htmlElement, item) { | ||||
|         return this.contextMenuGesture.apply(htmlElement, item); | ||||
|     }; | ||||
|  | ||||
|     return GestureAPI; | ||||
| }); | ||||
							
								
								
									
										21
									
								
								src/api/ui/dialog.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/api/ui/dialog.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| <div class="abs overlay"> | ||||
|     <div class="abs blocker"></div> | ||||
|     <div class="abs holder"> | ||||
|         <a class="clk-icon icon ui-symbol close">x</a> | ||||
|         <div class="abs contents"> | ||||
|             <div class="abs top-bar"> | ||||
|                 <div class="title"></div> | ||||
|                 <div class="hint"></div> | ||||
|             </div> | ||||
|             <div class='abs editor'> | ||||
|             </div> | ||||
|             <div class="abs bottom-bar"> | ||||
|                 <a class='s-btn major ok'>OK</a> | ||||
|                 <a class='s-btn cancel'>Cancel</a> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										135
									
								
								src/defaultRegistry.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/defaultRegistry.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([ | ||||
|     'legacyRegistry', | ||||
|  | ||||
|     '../src/adapter/bundle', | ||||
|     '../src/api/objects/bundle', | ||||
|  | ||||
|     '../example/builtins/bundle', | ||||
|     '../example/composite/bundle', | ||||
|     '../example/eventGenerator/bundle', | ||||
|     '../example/export/bundle', | ||||
|     '../example/extensions/bundle', | ||||
|     '../example/forms/bundle', | ||||
|     '../example/generator/bundle', | ||||
|     '../example/identity/bundle', | ||||
|     '../example/imagery/bundle', | ||||
|     '../example/mobile/bundle', | ||||
|     '../example/msl/bundle', | ||||
|     '../example/notifications/bundle', | ||||
|     '../example/persistence/bundle', | ||||
|     '../example/plotOptions/bundle', | ||||
|     '../example/policy/bundle', | ||||
|     '../example/profiling/bundle', | ||||
|     '../example/scratchpad/bundle', | ||||
|     '../example/taxonomy/bundle', | ||||
|     '../example/worker/bundle', | ||||
|  | ||||
|     '../platform/commonUI/about/bundle', | ||||
|     '../platform/commonUI/browse/bundle', | ||||
|     '../platform/commonUI/dialog/bundle', | ||||
|     '../platform/commonUI/edit/bundle', | ||||
|     '../platform/commonUI/formats/bundle', | ||||
|     '../platform/commonUI/general/bundle', | ||||
|     '../platform/commonUI/inspect/bundle', | ||||
|     '../platform/commonUI/mobile/bundle', | ||||
|     '../platform/commonUI/notification/bundle', | ||||
|     '../platform/commonUI/regions/bundle', | ||||
|     '../platform/commonUI/themes/espresso/bundle', | ||||
|     '../platform/commonUI/themes/snow/bundle', | ||||
|     '../platform/containment/bundle', | ||||
|     '../platform/core/bundle', | ||||
|     '../platform/entanglement/bundle', | ||||
|     '../platform/execution/bundle', | ||||
|     '../platform/exporters/bundle', | ||||
|     '../platform/features/clock/bundle', | ||||
|     '../platform/features/conductor/bundle', | ||||
|     '../platform/features/imagery/bundle', | ||||
|     '../platform/features/layout/bundle', | ||||
|     '../platform/features/pages/bundle', | ||||
|     '../platform/features/plot/bundle', | ||||
|     '../platform/features/static-markup/bundle', | ||||
|     '../platform/features/table/bundle', | ||||
|     '../platform/features/timeline/bundle', | ||||
|     '../platform/forms/bundle', | ||||
|     '../platform/framework/bundle', | ||||
|     '../platform/framework/src/load/Bundle', | ||||
|     '../platform/identity/bundle', | ||||
|     '../platform/persistence/aggregator/bundle', | ||||
|     '../platform/persistence/couch/bundle', | ||||
|     '../platform/persistence/elastic/bundle', | ||||
|     '../platform/persistence/local/bundle', | ||||
|     '../platform/persistence/queue/bundle', | ||||
|     '../platform/policy/bundle', | ||||
|     '../platform/representation/bundle', | ||||
|     '../platform/search/bundle', | ||||
|     '../platform/status/bundle', | ||||
|     '../platform/telemetry/bundle' | ||||
| ], function (legacyRegistry) { | ||||
|  | ||||
|     var DEFAULTS = [ | ||||
|         'src/adapter', | ||||
|         'src/api/objects', | ||||
|         'platform/framework', | ||||
|         'platform/core', | ||||
|         'platform/representation', | ||||
|         'platform/commonUI/about', | ||||
|         'platform/commonUI/browse', | ||||
|         'platform/commonUI/edit', | ||||
|         'platform/commonUI/dialog', | ||||
|         'platform/commonUI/formats', | ||||
|         'platform/commonUI/general', | ||||
|         'platform/commonUI/inspect', | ||||
|         'platform/commonUI/mobile', | ||||
|         'platform/commonUI/themes/espresso', | ||||
|         'platform/commonUI/notification', | ||||
|         'platform/containment', | ||||
|         'platform/execution', | ||||
|         'platform/exporters', | ||||
|         'platform/telemetry', | ||||
|         'platform/features/clock', | ||||
|         'platform/features/imagery', | ||||
|         'platform/features/layout', | ||||
|         'platform/features/pages', | ||||
|         'platform/features/plot', | ||||
|         'platform/features/timeline', | ||||
|         'platform/features/table', | ||||
|         'platform/forms', | ||||
|         'platform/identity', | ||||
|         'platform/persistence/aggregator', | ||||
|         'platform/persistence/local', | ||||
|         'platform/persistence/queue', | ||||
|         'platform/policy', | ||||
|         'platform/entanglement', | ||||
|         'platform/search', | ||||
|         'platform/status', | ||||
|         'platform/commonUI/regions' | ||||
|     ]; | ||||
|  | ||||
|     DEFAULTS.forEach(function (bundlePath) { | ||||
|         legacyRegistry.enable(bundlePath); | ||||
|     }); | ||||
|  | ||||
|     return legacyRegistry; | ||||
| }); | ||||
							
								
								
									
										3
									
								
								src/end.frag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/end.frag
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
|  | ||||
|    return require('main');  | ||||
| })); | ||||
| @@ -1,9 +1,9 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * Open MCT, Copyright (c) 2014-2016, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * 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. | ||||
| @@ -14,7 +14,7 @@ | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * 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. | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * Open MCT, Copyright (c) 2014-2016, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * 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. | ||||
| @@ -14,7 +14,7 @@ | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * 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. | ||||
|   | ||||
							
								
								
									
										78
									
								
								src/selection/ContextManager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/selection/ContextManager.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(['zepto'], function ($) { | ||||
|     /** | ||||
|      * @typedef Context | ||||
|      * @property {*} item | ||||
|      * @property {HTMLElement} element | ||||
|      * @property {Context} parent the containing context (may be undefined) | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|  | ||||
|  | ||||
|     function ContextManager() { | ||||
|         this.counter = 0; | ||||
|         this.contexts = {}; | ||||
|     } | ||||
|  | ||||
|     ContextManager.prototype.nextId = function () { | ||||
|         this.counter += 1; | ||||
|         return "context-" + this.counter; | ||||
|     }; | ||||
|  | ||||
|     ContextManager.prototype.context = function (item, htmlElement) { | ||||
|         var $element = $(htmlElement); | ||||
|         var id = $element.attr('data-context') || this.nextId(); | ||||
|  | ||||
|         $element.attr('data-context', id); | ||||
|  | ||||
|         if (this.contexts[id] && this.contexts[id].item !== item) { | ||||
|             this.release(htmlElement); | ||||
|         } | ||||
|  | ||||
|         if (!this.contexts[id]) { | ||||
|             var $parent = $element.closest('[data-context]'); | ||||
|             var parentId = $parent.attr('data-context'); | ||||
|             var parentContext = parentId ? this.contexts[parentId] : undefined; | ||||
|             this.contexts[id] = { | ||||
|                 item: item, | ||||
|                 element: htmlElement, | ||||
|                 parent: parentContext | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return this.contexts[id]; | ||||
|     }; | ||||
|  | ||||
|     ContextManager.prototype.release = function (htmlElement) { | ||||
|         var $element = $(htmlElement); | ||||
|         var id = $element.attr('data-context'); | ||||
|  | ||||
|         if (id) { | ||||
|             delete this.contexts[id]; | ||||
|             $element.removeAttr('data-context'); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     return ContextManager; | ||||
| }); | ||||
							
								
								
									
										58
									
								
								src/selection/HoverGesture.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/selection/HoverGesture.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(['zepto'], function ($) { | ||||
|     function HoverGesture(hoverManager) { | ||||
|         this.hoverManager = hoverManager; | ||||
|     } | ||||
|  | ||||
|     HoverGesture.prototype.apply = function (htmlElement) { | ||||
|         var $element = $(htmlElement); | ||||
|         var hoverManager = this.hoverManager; | ||||
|  | ||||
|         function update() { | ||||
|             $(hoverManager.all()).removeClass('hovering'); | ||||
|             $(hoverManager.top()).addClass('hovering'); | ||||
|         } | ||||
|  | ||||
|         function enter() { | ||||
|             hoverManager.add(htmlElement); | ||||
|             update(); | ||||
|         } | ||||
|  | ||||
|         function leave() { | ||||
|             hoverManager.remove(htmlElement); | ||||
|             update(); | ||||
|         } | ||||
|  | ||||
|         $element.on('mouseenter', enter); | ||||
|         $element.on('mouseleave', leave); | ||||
|  | ||||
|         return function () { | ||||
|             leave(); | ||||
|             $element.off('mouseenter', enter); | ||||
|             $element.off('mouseleave', leave); | ||||
|         }.bind(this); | ||||
|     }; | ||||
|  | ||||
|     return HoverGesture; | ||||
| }); | ||||
							
								
								
									
										60
									
								
								src/selection/SelectGesture.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/selection/SelectGesture.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(['zepto'], function ($) { | ||||
|     function SelectGesture(selection, contextManager) { | ||||
|         this.selection = selection; | ||||
|         this.contextManager = contextManager; | ||||
|     } | ||||
|  | ||||
|     SelectGesture.prototype.apply = function (htmlElement, item) { | ||||
|         var $element = $(htmlElement); | ||||
|         var contextManager = this.contextManager; | ||||
|         var selection = this.selection; | ||||
|         var path = contextManager.path(item, htmlElement); | ||||
|  | ||||
|         function select() { | ||||
|             selection.add(path); | ||||
|         } | ||||
|  | ||||
|         function change() { | ||||
|             var selected = selection.primary(); | ||||
|             $element.toggleClass( | ||||
|                 'selected', | ||||
|                 selected && path.matches(selected) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $element.addClass('selectable'); | ||||
|         $element.on('click', select); | ||||
|         selection.on('change', change); | ||||
|         change(); // Initialize | ||||
|  | ||||
|         return function () { | ||||
|             contextManager.release(htmlElement); | ||||
|             $element.off('click', select); | ||||
|             selection.off('change', change); | ||||
|         }; | ||||
|     }; | ||||
|  | ||||
|     return SelectGesture; | ||||
| }); | ||||
							
								
								
									
										69
									
								
								src/selection/Selection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/selection/Selection.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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(['EventEmitter'], function (EventEmitter) { | ||||
|  | ||||
|     /** | ||||
|      * Manages selection state for Open MCT | ||||
|      * @private | ||||
|      */ | ||||
|     function Selection() { | ||||
|         EventEmitter.call(this); | ||||
|         this.selected = []; | ||||
|     } | ||||
|  | ||||
|     Selection.prototype = Object.create(EventEmitter.prototype); | ||||
|  | ||||
|     Selection.prototype.add = function (context) { | ||||
|         this.clear(); // Only allow single select as initial simplification | ||||
|         this.selected.push(context); | ||||
|         this.emit('change'); | ||||
|     }; | ||||
|  | ||||
|     Selection.prototype.remove = function (path) { | ||||
|         this.selected = this.selected.filter(function (otherPath) { | ||||
|             return !path.matches(otherPath); | ||||
|         }); | ||||
|         this.emit('change'); | ||||
|     }; | ||||
|  | ||||
|     Selection.prototype.contains = function (path) { | ||||
|         return this.selected.some(function (otherPath) { | ||||
|             return path.matches(otherPath); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     Selection.prototype.clear = function () { | ||||
|         this.selected = []; | ||||
|         this.emit('change'); | ||||
|     }; | ||||
|  | ||||
|     Selection.prototype.primary = function () { | ||||
|         return this.selected[this.selected.length - 1]; | ||||
|     }; | ||||
|  | ||||
|     Selection.prototype.all = function () { | ||||
|         return this.selected; | ||||
|     }; | ||||
|  | ||||
|     return Selection; | ||||
| }); | ||||
							
								
								
									
										39
									
								
								src/start.frag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/start.frag
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * Open MCT https://nasa.github.io/openmct/ | ||||
|  * Version @@version | ||||
|  * Built @@timestamp | ||||
|  * Revision @@revision | ||||
|  * Branch @@branch | ||||
|  */ | ||||
|  | ||||
| (function (root, factory) { | ||||
|     if (typeof define === 'function' && define.amd) { | ||||
|         define([], factory); | ||||
|     } else if (typeof exports === 'object') { | ||||
|         module.exports = factory(); | ||||
|     } else { | ||||
|         root.MCT = factory(); | ||||
|     } | ||||
| }(this, function() { | ||||
							
								
								
									
										152
									
								
								src/ui/ViewRegistry.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								src/ui/ViewRegistry.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2016, 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([], function () { | ||||
|     /** | ||||
|      * A ViewRegistry maintains the definitions for different kinds of views | ||||
|      * that may occur in different places in the user interface. | ||||
|      * @interface ViewRegistry | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|     function ViewRegistry() { | ||||
|         this.providers = []; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @private for platform-internal use | ||||
|      * @param {*} item the object to be viewed | ||||
|      * @returns {module:openmct.ViewProvider[]} any providers | ||||
|      *          which can provide views of this object | ||||
|      */ | ||||
|     ViewRegistry.prototype.get = function (item) { | ||||
|         return this.providers.filter(function (provider) { | ||||
|             return provider.canView(item); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Register a new type of view. | ||||
|      * | ||||
|      * @param {module:openmct.ViewProvider} provider the provider for this view | ||||
|      * @method addProvider | ||||
|      * @memberof module:openmct.ViewRegistry# | ||||
|      */ | ||||
|     ViewRegistry.prototype.addProvider = function (provider) { | ||||
|         this.providers.push(provider); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * A View is used to provide displayable content, and to react to | ||||
|      * associated life cycle events. | ||||
|      * | ||||
|      * @name View | ||||
|      * @interface | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Populate the supplied DOM element with the contents of this view. | ||||
|      * | ||||
|      * View implementations should use this method to attach any | ||||
|      * listeners or acquire other resources that are necessary to keep | ||||
|      * the contents of this view up-to-date. | ||||
|      * | ||||
|      * @param {HTMLElement} container the DOM element to populate | ||||
|      * @method show | ||||
|      * @memberof module:openmct.View# | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Release any resources associated with this view. | ||||
|      * | ||||
|      * View implementations should use this method to detach any | ||||
|      * listeners or release other resources that are no longer necessary | ||||
|      * once a view is no longer used. | ||||
|      * | ||||
|      * @method destroy | ||||
|      * @memberof module:openmct.View# | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Exposes types of views in Open MCT. | ||||
|      * | ||||
|      * @interface ViewProvider | ||||
|      * @memberof module:openmct | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Check if this provider can supply views for a domain object. | ||||
|      * | ||||
|      * When called by Open MCT, this may include additional arguments | ||||
|      * which are on the path to the object to be viewed; for instance, | ||||
|      * when viewing "A Folder" within "My Items", this method will be | ||||
|      * invoked with "A Folder" (as a domain object) as the first argument, | ||||
|      * and "My Items" as the second argument. | ||||
|      * | ||||
|      * @method canView | ||||
|      * @memberof module:openmct.ViewProvider# | ||||
|      * @param {module:openmct.DomainObject} domainObject the domain object | ||||
|      *        to be viewed | ||||
|      * @returns {boolean} true if this domain object can be viewed using | ||||
|      *          this provider | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Provide a view of this object. | ||||
|      * | ||||
|      * When called by Open MCT, this may include additional arguments | ||||
|      * which are on the path to the object to be viewed; for instance, | ||||
|      * when viewing "A Folder" within "My Items", this method will be | ||||
|      * invoked with "A Folder" (as a domain object) as the first argument, | ||||
|      * and "My Items" as the second argument. | ||||
|      * | ||||
|      * @method view | ||||
|      * @memberof module:openmct.ViewProvider# | ||||
|      * @param {*} object the object to be viewed | ||||
|      * @returns {module:openmct.View} a view of this domain object | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Get metadata associated with this view provider. This may be used | ||||
|      * to populate the user interface with options associated with this | ||||
|      * view provider. | ||||
|      * | ||||
|      * @method metadata | ||||
|      * @memberof module:openmct.ViewProvider# | ||||
|      * @returns {module:openmct.ViewProvider~ViewMetadata} view metadata | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * @typedef ViewMetadata | ||||
|      * @memberof module:openmct.ViewProvider~ | ||||
|      * @property {string} name the human-readable name of this view | ||||
|      * @property {string} key a machine-readable name for this view | ||||
|      * @property {string} [description] a longer-form description (typically | ||||
|      *           a single sentence or short paragraph) of this kind of view | ||||
|      * @property {string} cssclass the CSS class to apply to labels for this | ||||
|      *           view (to add icons, for instance) | ||||
|      */ | ||||
|  | ||||
|     return ViewRegistry; | ||||
|  | ||||
| }); | ||||
							
								
								
									
										10
									
								
								test-main.js
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								test-main.js
									
									
									
									
									
								
							| @@ -48,13 +48,15 @@ requirejs.config({ | ||||
|         "angular-route": "bower_components/angular-route/angular-route.min", | ||||
|         "csv": "bower_components/comma-separated-values/csv.min", | ||||
|         "es6-promise": "bower_components/es6-promise/promise.min", | ||||
|         "EventEmitter": "bower_components/eventemitter3/index", | ||||
|         "moment": "bower_components/moment/moment", | ||||
|         "moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format", | ||||
|         "saveAs": "bower_components/FileSaver.js/FileSaver.min", | ||||
|         "screenfull": "bower_components/screenfull/dist/screenfull.min", | ||||
|         "text": "bower_components/text/text", | ||||
|         "uuid": "bower_components/node-uuid/uuid", | ||||
|         "zepto": "bower_components/zepto/zepto.min" | ||||
|         "zepto": "bower_components/zepto/zepto.min", | ||||
|         "lodash": "bower_components/lodash/lodash" | ||||
|     }, | ||||
|  | ||||
|     "shim": { | ||||
| @@ -64,6 +66,9 @@ requirejs.config({ | ||||
|         "angular-route": { | ||||
|             "deps": [ "angular" ] | ||||
|         }, | ||||
|         "EventEmitter": { | ||||
|             "exports": "EventEmitter" | ||||
|         }, | ||||
|         "moment-duration-format": { | ||||
|             "deps": [ "moment" ] | ||||
|         }, | ||||
| @@ -72,6 +77,9 @@ requirejs.config({ | ||||
|         }, | ||||
|         "zepto": { | ||||
|             "exports": "Zepto" | ||||
|         }, | ||||
|         "lodash": { | ||||
|             "exports": "lodash" | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|   | ||||
							
								
								
									
										127
									
								
								tutorial-server/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								tutorial-server/app.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| /*global require,process,console*/ | ||||
|  | ||||
| var CONFIG = { | ||||
|     port: 8081, | ||||
|     dictionary: "dictionary.json", | ||||
|     interval: 1000 | ||||
| }; | ||||
|  | ||||
| (function () { | ||||
|     "use strict"; | ||||
|  | ||||
|     var WebSocketServer = require('ws').Server, | ||||
|         fs = require('fs'), | ||||
|         wss = new WebSocketServer({ port: CONFIG.port }), | ||||
|         dictionary = JSON.parse(fs.readFileSync(CONFIG.dictionary, "utf8")), | ||||
|         spacecraft = { | ||||
|             "prop.fuel": 77, | ||||
|             "prop.thrusters": "OFF", | ||||
|             "comms.recd": 0, | ||||
|             "comms.sent": 0, | ||||
|             "pwr.temp": 245, | ||||
|             "pwr.c": 8.15, | ||||
|             "pwr.v": 30 | ||||
|         }, | ||||
|         histories = {}, | ||||
|         listeners = []; | ||||
|  | ||||
|     function updateSpacecraft() { | ||||
|         spacecraft["prop.fuel"] = Math.max( | ||||
|             0, | ||||
|             spacecraft["prop.fuel"] - | ||||
|             (spacecraft["prop.thrusters"] === "ON" ? 0.5 : 0) | ||||
|         ); | ||||
|         spacecraft["pwr.temp"] = spacecraft["pwr.temp"] * 0.985 | ||||
|         + Math.random() * 0.25 + Math.sin(Date.now()); | ||||
|         spacecraft["pwr.c"] = spacecraft["pwr.c"] * 0.985; | ||||
|         spacecraft["pwr.v"] = 30 + Math.pow(Math.random(), 3); | ||||
|     } | ||||
|  | ||||
|     function generateTelemetry() { | ||||
|         var timestamp = Date.now(), sent = 0; | ||||
|         Object.keys(spacecraft).forEach(function (id) { | ||||
|             var state = { timestamp: timestamp, value: spacecraft[id] }; | ||||
|             histories[id] = histories[id] || []; // Initialize | ||||
|             histories[id].push(state); | ||||
|             spacecraft["comms.sent"] += JSON.stringify(state).length; | ||||
|         }); | ||||
|         listeners.forEach(function (listener) { | ||||
|             listener(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     function update() { | ||||
|         updateSpacecraft(); | ||||
|         generateTelemetry(); | ||||
|     } | ||||
|  | ||||
|     function handleConnection(ws) { | ||||
|         var subscriptions = {}, // Active subscriptions for this connection | ||||
|             handlers = {        // Handlers for specific requests | ||||
|                 dictionary: function () { | ||||
|                     ws.send(JSON.stringify({ | ||||
|                         type: "dictionary", | ||||
|                         value: dictionary | ||||
|                     })); | ||||
|                 }, | ||||
|                 subscribe: function (id) { | ||||
|                     subscriptions[id] = true; | ||||
|                 }, | ||||
|                 unsubscribe: function (id) { | ||||
|                     delete subscriptions[id]; | ||||
|                 }, | ||||
|                 history: function (id) { | ||||
|                     ws.send(JSON.stringify({ | ||||
|                         type: "history", | ||||
|                         id: id, | ||||
|                         value: histories[id] | ||||
|                     })); | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|         function notifySubscribers() { | ||||
|             Object.keys(subscriptions).forEach(function (id) { | ||||
|                 var history = histories[id]; | ||||
|                 if (history) { | ||||
|                     ws.send(JSON.stringify({ | ||||
|                         type: "data", | ||||
|                         id: id, | ||||
|                         value: history[history.length - 1] | ||||
|                     })); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         // Listen for requests | ||||
|         ws.on('message', function (message) { | ||||
|             var parts = message.split(' '), | ||||
|                 handler = handlers[parts[0]]; | ||||
|             if (handler) { | ||||
|                 handler.apply(handlers, parts.slice(1)); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         // Stop sending telemetry updates for this connection when closed | ||||
|         ws.on('close', function () { | ||||
|             listeners = listeners.filter(function (listener) { | ||||
|                 return listener !== notifySubscribers; | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         // Notify subscribers when telemetry is updated | ||||
|         listeners.push(notifySubscribers); | ||||
|     } | ||||
|  | ||||
|     update(); | ||||
|     setInterval(update, CONFIG.interval); | ||||
|  | ||||
|     wss.on('connection', handleConnection); | ||||
|  | ||||
|     console.log("Example spacecraft running on port "); | ||||
|     console.log("Press Enter to toggle thruster state."); | ||||
|     process.stdin.on('data', function (data) { | ||||
|         spacecraft['prop.thrusters'] = | ||||
|             (spacecraft['prop.thrusters'] === "OFF") ? "ON" : "OFF"; | ||||
|         console.log("Thrusters " + spacecraft["prop.thrusters"]); | ||||
|     }); | ||||
| }()); | ||||
							
								
								
									
										66
									
								
								tutorial-server/dictionary.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								tutorial-server/dictionary.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| { | ||||
|     "name": "Example Spacecraft", | ||||
|     "identifier": "sc", | ||||
|     "subsystems": [ | ||||
|         { | ||||
|             "name": "Propulsion", | ||||
|             "identifier": "prop", | ||||
|             "measurements": [ | ||||
|                 { | ||||
|                     "name": "Fuel", | ||||
|                     "identifier": "prop.fuel", | ||||
|                     "units": "kilograms", | ||||
|                     "type": "float" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Thrusters", | ||||
|                     "identifier": "prop.thrusters", | ||||
|                     "units": "None", | ||||
|                     "type": "string" | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|             "name": "Communications", | ||||
|             "identifier": "comms", | ||||
|             "measurements": [ | ||||
|                 { | ||||
|                     "name": "Received", | ||||
|                     "identifier": "comms.recd", | ||||
|                     "units": "bytes", | ||||
|                     "type": "integer" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Sent", | ||||
|                     "identifier": "comms.sent", | ||||
|                     "units": "bytes", | ||||
|                     "type": "integer" | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|             "name": "Power", | ||||
|             "identifier": "pwr", | ||||
|             "measurements": [ | ||||
|                 { | ||||
|                     "name": "Generator Temperature", | ||||
|                     "identifier": "pwr.temp", | ||||
|                     "units": "\u0080C", | ||||
|                     "type": "float" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Generator Current", | ||||
|                     "identifier": "pwr.c", | ||||
|                     "units": "A", | ||||
|                     "type": "float" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Generator Voltage", | ||||
|                     "identifier": "pwr.v", | ||||
|                     "units": "V", | ||||
|                     "type": "float" | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										66
									
								
								tutorials/bargraph/bundle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								tutorials/bargraph/bundle.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| define([ | ||||
|     'legacyRegistry', | ||||
|     './src/controllers/BarGraphController' | ||||
| ], function ( | ||||
|     legacyRegistry, | ||||
|     BarGraphController | ||||
|     ) { | ||||
|     legacyRegistry.register("tutorials/bargraph", { | ||||
|         "name": "Bar Graph", | ||||
|         "description": "Provides the Bar Graph view of telemetry elements.", | ||||
|         "extensions": { | ||||
|             "views": [ | ||||
|                 { | ||||
|                     "name": "Bar Graph", | ||||
|                     "key": "example.bargraph", | ||||
|                     "glyph": "H", | ||||
|                     "templateUrl": "templates/bargraph.html", | ||||
|                     "needs": [ "telemetry" ], | ||||
|                     "delegation": true, | ||||
|                     "editable": true, | ||||
|                     "toolbar": { | ||||
|                         "sections": [ | ||||
|                             { | ||||
|                                 "items": [ | ||||
|                                     { | ||||
|                                         "name": "Low", | ||||
|                                         "property": "low", | ||||
|                                         "required": true, | ||||
|                                         "control": "textfield", | ||||
|                                         "size": 4 | ||||
|                                     }, | ||||
|                                     { | ||||
|                                         "name": "Middle", | ||||
|                                         "property": "middle", | ||||
|                                         "required": true, | ||||
|                                         "control": "textfield", | ||||
|                                         "size": 4 | ||||
|                                     }, | ||||
|                                     { | ||||
|                                         "name": "High", | ||||
|                                         "property": "high", | ||||
|                                         "required": true, | ||||
|                                         "control": "textfield", | ||||
|                                         "size": 4 | ||||
|                                     } | ||||
|                                 ] | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "stylesheets": [ | ||||
|                 { | ||||
|                     "stylesheetUrl": "css/bargraph.css" | ||||
|                 } | ||||
|             ], | ||||
|             "controllers": [ | ||||
|                 { | ||||
|                     "key": "BarGraphController", | ||||
|                     "implementation": BarGraphController, | ||||
|                     "depends": [ "$scope", "telemetryHandler" ] | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										35
									
								
								tutorials/bargraph/res/templates/bargraph.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tutorials/bargraph/res/templates/bargraph.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <div class="example-bargraph" ng-controller="BarGraphController"> | ||||
|     <div class="example-tick-labels"> | ||||
|         <div ng-repeat="value in [low, middle, high] track by $index" | ||||
|              class="example-tick-label" | ||||
|              style="bottom: {{ toPercent(value) }}%"> | ||||
|             {{value}} | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="example-graph-area"> | ||||
|         <div ng-repeat="telemetryObject in telemetryObjects" | ||||
|              style="left: {{barWidth * $index}}%; width: {{barWidth}}%" | ||||
|              class="example-bar-holder"> | ||||
|             <div class="example-bar" | ||||
|                  ng-style="{ | ||||
|                      bottom: getBottom(telemetryObject) + '%', | ||||
|                      top: getTop(telemetryObject) + '%' | ||||
|                  }"> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div style="bottom: {{ toPercent(middle) }}%" | ||||
|              class="example-graph-tick"> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="example-bar-labels"> | ||||
|         <div ng-repeat="telemetryObject in telemetryObjects" | ||||
|              style="left: {{barWidth * $index}}%; width: {{barWidth}}%" | ||||
|              class="example-bar-holder example-label"> | ||||
|             <mct-representation key="'label'" | ||||
|                                 mct-object="telemetryObject"> | ||||
|             </mct-representation> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
							
								
								
									
										75
									
								
								tutorials/bargraph/src/controllers/BarGraphController.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								tutorials/bargraph/src/controllers/BarGraphController.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| define(function () { | ||||
|     function BarGraphController($scope, telemetryHandler) { | ||||
|         var handle; | ||||
|  | ||||
|         // Expose configuration constants directly in scope | ||||
|         function exposeConfiguration() { | ||||
|             $scope.low = $scope.configuration.low; | ||||
|             $scope.middle = $scope.configuration.middle; | ||||
|             $scope.high = $scope.configuration.high; | ||||
|         } | ||||
|  | ||||
|         // Populate a default value in the configuration | ||||
|         function setDefault(key, value) { | ||||
|             if ($scope.configuration[key] === undefined) { | ||||
|                 $scope.configuration[key] = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Getter-setter for configuration properties (for view proxy) | ||||
|         function getterSetter(property) { | ||||
|             return function (value) { | ||||
|                 value = parseFloat(value); | ||||
|                 if (!isNaN(value)) { | ||||
|                     $scope.configuration[property] = value; | ||||
|                     exposeConfiguration(); | ||||
|                 } | ||||
|                 return $scope.configuration[property]; | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         // Add min/max defaults | ||||
|         setDefault('low', -1); | ||||
|         setDefault('middle', 0); | ||||
|         setDefault('high', 1); | ||||
|         exposeConfiguration($scope.configuration); | ||||
|  | ||||
|         // Expose view configuration options | ||||
|         if ($scope.selection) { | ||||
|             $scope.selection.proxy({ | ||||
|                 low: getterSetter('low'), | ||||
|                 middle: getterSetter('middle'), | ||||
|                 high: getterSetter('high') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         // Convert value to a percent between 0-100 | ||||
|         $scope.toPercent = function (value) { | ||||
|             var pct = 100 * (value - $scope.low) / | ||||
|                 ($scope.high - $scope.low); | ||||
|             return Math.min(100, Math.max(0, pct)); | ||||
|         }; | ||||
|  | ||||
|         // Get bottom and top (as percentages) for current value | ||||
|         $scope.getBottom = function (telemetryObject) { | ||||
|             var value = handle.getRangeValue(telemetryObject); | ||||
|             return $scope.toPercent(Math.min($scope.middle, value)); | ||||
|         }; | ||||
|         $scope.getTop = function (telemetryObject) { | ||||
|             var value = handle.getRangeValue(telemetryObject); | ||||
|             return 100 - $scope.toPercent(Math.max($scope.middle, value)); | ||||
|         }; | ||||
|  | ||||
|         // Use the telemetryHandler to get telemetry objects here | ||||
|         handle = telemetryHandler.handle($scope.domainObject, function () { | ||||
|             $scope.telemetryObjects = handle.getTelemetryObjects(); | ||||
|             $scope.barWidth = | ||||
|                 100 / Math.max(($scope.telemetryObjects).length, 1); | ||||
|         }); | ||||
|  | ||||
|         // Release subscriptions when scope is destroyed | ||||
|         $scope.$on('$destroy', handle.unsubscribe); | ||||
|     } | ||||
|  | ||||
|     return BarGraphController; | ||||
| }); | ||||
							
								
								
									
										90
									
								
								tutorials/telemetry/bundle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								tutorials/telemetry/bundle.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| define([ | ||||
|     'legacyRegistry', | ||||
|     './src/ExampleTelemetryServerAdapter', | ||||
|     './src/ExampleTelemetryInitializer', | ||||
|     './src/ExampleTelemetryModelProvider' | ||||
| ], function ( | ||||
|     legacyRegistry, | ||||
|     ExampleTelemetryServerAdapter, | ||||
|     ExampleTelemetryInitializer, | ||||
|     ExampleTelemetryModelProvider | ||||
| ) { | ||||
|     legacyRegistry.register("tutorials/telemetry", { | ||||
|         "name": "Example Telemetry Adapter", | ||||
|         "extensions": { | ||||
|             "types": [ | ||||
|                 { | ||||
|                     "name": "Spacecraft", | ||||
|                     "key": "example.spacecraft", | ||||
|                     "glyph": "o" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Subsystem", | ||||
|                     "key": "example.subsystem", | ||||
|                     "glyph": "o", | ||||
|                     "model": { "composition": [] } | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Measurement", | ||||
|                     "key": "example.measurement", | ||||
|                     "glyph": "T", | ||||
|                     "model": { "telemetry": {} }, | ||||
|                     "telemetry": { | ||||
|                         "source": "example.source", | ||||
|                         "domains": [ | ||||
|                             { | ||||
|                                 "name": "Time", | ||||
|                                 "key": "timestamp" | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "roots": [ | ||||
|                 { | ||||
|                     "id": "example:sc", | ||||
|                     "priority": "preferred", | ||||
|                     "model": { | ||||
|                         "type": "example.spacecraft", | ||||
|                         "name": "My Spacecraft", | ||||
|                         "composition": [] | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "services": [ | ||||
|                 { | ||||
|                     "key": "example.adapter", | ||||
|                     "implementation": "ExampleTelemetryServerAdapter.js", | ||||
|                     "depends": [ "$q", "EXAMPLE_WS_URL" ] | ||||
|                 } | ||||
|             ], | ||||
|             "constants": [ | ||||
|                 { | ||||
|                     "key": "EXAMPLE_WS_URL", | ||||
|                     "priority": "fallback", | ||||
|                     "value": "ws://localhost:8081" | ||||
|                 } | ||||
|             ], | ||||
|             "runs": [ | ||||
|                 { | ||||
|                     "implementation": "ExampleTelemetryInitializer.js", | ||||
|                     "depends": [ "example.adapter", "objectService" ] | ||||
|                 } | ||||
|             ], | ||||
|             "components": [ | ||||
|                 { | ||||
|                     "provides": "modelService", | ||||
|                     "type": "provider", | ||||
|                     "implementation": "ExampleTelemetryModelProvider.js", | ||||
|                     "depends": [ "example.adapter", "$q" ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "provides": "telemetryService", | ||||
|                     "type": "provider", | ||||
|                     "implementation": "ExampleTelemetryProvider.js", | ||||
|                     "depends": [ "example.adapter", "$q" ] | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										47
									
								
								tutorials/telemetry/src/ExampleTelemetryInitializer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								tutorials/telemetry/src/ExampleTelemetryInitializer.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| define( | ||||
|     function () { | ||||
|         "use strict"; | ||||
|  | ||||
|         var TAXONOMY_ID = "example:sc", | ||||
|             PREFIX = "example_tlm:"; | ||||
|  | ||||
|         function ExampleTelemetryInitializer(adapter, objectService) { | ||||
|             // Generate a domain object identifier for a dictionary element | ||||
|             function makeId(element) { | ||||
|                 return PREFIX + element.identifier; | ||||
|             } | ||||
|  | ||||
|             // When the dictionary is available, add all subsystems | ||||
|             // to the composition of My Spacecraft | ||||
|             function initializeTaxonomy(dictionary) { | ||||
|                 // Get the top-level container for dictionary objects | ||||
|                 // from a group of domain objects. | ||||
|                 function getTaxonomyObject(domainObjects) { | ||||
|                     return domainObjects[TAXONOMY_ID]; | ||||
|                 } | ||||
|  | ||||
|                 // Populate | ||||
|                 function populateModel(taxonomyObject) { | ||||
|                     return taxonomyObject.useCapability( | ||||
|                         "mutation", | ||||
|                         function (model) { | ||||
|                             model.name = | ||||
|                                 dictionary.name; | ||||
|                             model.composition = | ||||
|                                 dictionary.subsystems.map(makeId); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|  | ||||
|                 // Look up My Spacecraft, and populate it accordingly. | ||||
|                 objectService.getObjects([TAXONOMY_ID]) | ||||
|                     .then(getTaxonomyObject) | ||||
|                     .then(populateModel); | ||||
|             } | ||||
|  | ||||
|             adapter.dictionary().then(initializeTaxonomy); | ||||
|         } | ||||
|  | ||||
|         return ExampleTelemetryInitializer; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										78
									
								
								tutorials/telemetry/src/ExampleTelemetryModelProvider.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								tutorials/telemetry/src/ExampleTelemetryModelProvider.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| define( | ||||
|     function () { | ||||
|         "use strict"; | ||||
|  | ||||
|         var PREFIX = "example_tlm:", | ||||
|             FORMAT_MAPPINGS = { | ||||
|                 float: "number", | ||||
|                 integer: "number", | ||||
|                 string: "string" | ||||
|             }; | ||||
|  | ||||
|         function ExampleTelemetryModelProvider(adapter, $q) { | ||||
|             var modelPromise, empty = $q.when({}); | ||||
|  | ||||
|             // Check if this model is in our dictionary (by prefix) | ||||
|             function isRelevant(id) { | ||||
|                 return id.indexOf(PREFIX) === 0; | ||||
|             } | ||||
|  | ||||
|             // Build a domain object identifier by adding a prefix | ||||
|             function makeId(element) { | ||||
|                 return PREFIX + element.identifier; | ||||
|             } | ||||
|  | ||||
|             // Create domain object models from this dictionary | ||||
|             function buildTaxonomy(dictionary) { | ||||
|                 var models = {}; | ||||
|  | ||||
|                 // Create & store a domain object model for a measurement | ||||
|                 function addMeasurement(measurement) { | ||||
|                     var format = FORMAT_MAPPINGS[measurement.type]; | ||||
|                     models[makeId(measurement)] = { | ||||
|                         type: "example.measurement", | ||||
|                         name: measurement.name, | ||||
|                         telemetry: { | ||||
|                             key: measurement.identifier, | ||||
|                             ranges: [{ | ||||
|                                 key: "value", | ||||
|                                 name: "Value", | ||||
|                                 units: measurement.units, | ||||
|                                 format: format | ||||
|                             }] | ||||
|                         } | ||||
|                     }; | ||||
|                 } | ||||
|  | ||||
|                 // Create & store a domain object model for a subsystem | ||||
|                 function addSubsystem(subsystem) { | ||||
|                     var measurements = | ||||
|                         (subsystem.measurements || []); | ||||
|                     models[makeId(subsystem)] = { | ||||
|                         type: "example.subsystem", | ||||
|                         name: subsystem.name, | ||||
|                         composition: measurements.map(makeId) | ||||
|                     }; | ||||
|                     measurements.forEach(addMeasurement); | ||||
|                 } | ||||
|  | ||||
|                 (dictionary.subsystems || []).forEach(addSubsystem); | ||||
|  | ||||
|                 return models; | ||||
|             } | ||||
|  | ||||
|             // Begin generating models once the dictionary is available | ||||
|             modelPromise = adapter.dictionary().then(buildTaxonomy); | ||||
|  | ||||
|             return { | ||||
|                 getModels: function (ids) { | ||||
|                     // Return models for the dictionary only when they | ||||
|                     // are relevant to the request. | ||||
|                     return ids.some(isRelevant) ? modelPromise : empty; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return ExampleTelemetryModelProvider; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										80
									
								
								tutorials/telemetry/src/ExampleTelemetryProvider.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								tutorials/telemetry/src/ExampleTelemetryProvider.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| define( | ||||
|     ['./ExampleTelemetrySeries'], | ||||
|     function (ExampleTelemetrySeries) { | ||||
|         "use strict"; | ||||
|  | ||||
|         var SOURCE = "example.source"; | ||||
|  | ||||
|         function ExampleTelemetryProvider(adapter, $q) { | ||||
|             var subscribers = {}; | ||||
|  | ||||
|             // Used to filter out requests for telemetry | ||||
|             // from some other source | ||||
|             function matchesSource(request) { | ||||
|                 return (request.source === SOURCE); | ||||
|             } | ||||
|  | ||||
|             // Listen for data, notify subscribers | ||||
|             adapter.listen(function (message) { | ||||
|                 var packaged = {}; | ||||
|                 packaged[SOURCE] = {}; | ||||
|                 packaged[SOURCE][message.id] = | ||||
|                     new ExampleTelemetrySeries([message.value]); | ||||
|                 (subscribers[message.id] || []).forEach(function (cb) { | ||||
|                     cb(packaged); | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|             return { | ||||
|                 requestTelemetry: function (requests) { | ||||
|                     var packaged = {}, | ||||
|                         relevantReqs = requests.filter(matchesSource); | ||||
|  | ||||
|                     // Package historical telemetry that has been received | ||||
|                     function addToPackage(history) { | ||||
|                         packaged[SOURCE][history.id] = | ||||
|                             new ExampleTelemetrySeries(history.value); | ||||
|                     } | ||||
|  | ||||
|                     // Retrieve telemetry for a specific measurement | ||||
|                     function handleRequest(request) { | ||||
|                         var key = request.key; | ||||
|                         return adapter.history(key).then(addToPackage); | ||||
|                     } | ||||
|  | ||||
|                     packaged[SOURCE] = {}; | ||||
|                     return $q.all(relevantReqs.map(handleRequest)) | ||||
|                         .then(function () { return packaged; }); | ||||
|                 }, | ||||
|                 subscribe: function (callback, requests) { | ||||
|                     var keys = requests.filter(matchesSource) | ||||
|                         .map(function (req) { return req.key; }); | ||||
|  | ||||
|                     function notCallback(cb) { | ||||
|                         return cb !== callback; | ||||
|                     } | ||||
|  | ||||
|                     function unsubscribe(key) { | ||||
|                         subscribers[key] = | ||||
|                             (subscribers[key] || []).filter(notCallback); | ||||
|                         if (subscribers[key].length < 1) { | ||||
|                             adapter.unsubscribe(key); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     keys.forEach(function (key) { | ||||
|                         subscribers[key] = subscribers[key] || []; | ||||
|                         adapter.subscribe(key); | ||||
|                         subscribers[key].push(callback); | ||||
|                     }); | ||||
|  | ||||
|                     return function () { | ||||
|                         keys.forEach(unsubscribe); | ||||
|                     }; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return ExampleTelemetryProvider; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										23
									
								
								tutorials/telemetry/src/ExampleTelemetrySeries.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tutorials/telemetry/src/ExampleTelemetrySeries.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| /*global define*/ | ||||
|  | ||||
| define( | ||||
|     function () { | ||||
|         "use strict"; | ||||
|  | ||||
|         function ExampleTelemetrySeries(data) { | ||||
|             return { | ||||
|                 getPointCount: function () { | ||||
|                     return data.length; | ||||
|                 }, | ||||
|                 getDomainValue: function (index) { | ||||
|                     return (data[index] || {}).timestamp; | ||||
|                 }, | ||||
|                 getRangeValue: function (index) { | ||||
|                     return (data[index] || {}).value; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return ExampleTelemetrySeries; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										60
									
								
								tutorials/telemetry/src/ExampleTelemetryServerAdapter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								tutorials/telemetry/src/ExampleTelemetryServerAdapter.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
|         "use strict"; | ||||
|  | ||||
|         function ExampleTelemetryServerAdapter($q, wsUrl) { | ||||
|             var ws = new WebSocket(wsUrl), | ||||
|                 histories = {}, | ||||
|                 listeners = [], | ||||
|                 dictionary = $q.defer(); | ||||
|  | ||||
|             // Handle an incoming message from the server | ||||
|             ws.onmessage = function (event) { | ||||
|                 var message = JSON.parse(event.data); | ||||
|  | ||||
|                 switch (message.type) { | ||||
|                 case "dictionary": | ||||
|                     dictionary.resolve(message.value); | ||||
|                     break; | ||||
|                 case "history": | ||||
|                     histories[message.id].resolve(message); | ||||
|                     delete histories[message.id]; | ||||
|                     break; | ||||
|                 case "data": | ||||
|                     listeners.forEach(function (listener) { | ||||
|                         listener(message); | ||||
|                     }); | ||||
|                     break; | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             // Request dictionary once connection is established | ||||
|             ws.onopen = function () { | ||||
|                 ws.send("dictionary"); | ||||
|             }; | ||||
|  | ||||
|             return { | ||||
|                 dictionary: function () { | ||||
|                     return dictionary.promise; | ||||
|                 }, | ||||
|                 history: function (id) { | ||||
|                     histories[id] = histories[id] || $q.defer(); | ||||
|                     ws.send("history " + id); | ||||
|                     return histories[id].promise; | ||||
|                 }, | ||||
|                 subscribe: function (id) { | ||||
|                     ws.send("subscribe " + id); | ||||
|                 }, | ||||
|                 unsubscribe: function (id) { | ||||
|                     ws.send("unsubscribe " + id); | ||||
|                 }, | ||||
|                 listen: function (callback) { | ||||
|                     listeners.push(callback); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return ExampleTelemetryServerAdapter; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										3
									
								
								tutorials/todo/todo-dialog.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tutorials/todo/todo-dialog.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| <label>Description: | ||||
|     <input type="text" class="description"> | ||||
| </label> | ||||
							
								
								
									
										5
									
								
								tutorials/todo/todo-task.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tutorials/todo/todo-task.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| <li> | ||||
|     <input type="checkbox" class="example-task-checked"> | ||||
|     <span class="example-task-description"> | ||||
|     </span> | ||||
| </li> | ||||
							
								
								
									
										9
									
								
								tutorials/todo/todo-toolbar.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tutorials/todo/todo-toolbar.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <div class="tool-bar btn-bar contents abs"> | ||||
|     <a class="s-btn labeled example-add"> | ||||
|         <span class="ui-symbol icon">+</span> | ||||
|         <span class="title-label">Add Task</span> | ||||
|     </a> | ||||
|     <a class="s-btn example-remove"> | ||||
|         <span class="ui-symbol icon">Z</span> | ||||
|     </a> | ||||
| </div> | ||||
							
								
								
									
										29
									
								
								tutorials/todo/todo.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								tutorials/todo/todo.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| .example-todo div.example-button-group { | ||||
|     margin-top: 12px; | ||||
|     margin-bottom: 12px; | ||||
| } | ||||
|  | ||||
| .example-todo .example-button-group a { | ||||
|     padding: 3px; | ||||
|     margin: 3px; | ||||
| } | ||||
|  | ||||
| .example-todo .example-button-group a.selected { | ||||
|     border: 1px gray solid; | ||||
|     border-radius: 3px; | ||||
|     background: #444; | ||||
| } | ||||
|  | ||||
| .example-todo .example-task-completed .example-task-description { | ||||
|     text-decoration: line-through; | ||||
|     opacity: 0.75; | ||||
| } | ||||
|  | ||||
| .example-todo .example-task-description.selected { | ||||
|     background: #46A; | ||||
|     border-radius: 3px; | ||||
| } | ||||
|  | ||||
| .example-todo .example-message { | ||||
|     font-style: italic; | ||||
| } | ||||
							
								
								
									
										14
									
								
								tutorials/todo/todo.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tutorials/todo/todo.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <div class="example-todo"> | ||||
|     <div class="example-button-group"> | ||||
|         <a class="example-todo-button" data-filter="all">All</a> | ||||
|         <a class="example-todo-button" data-filter="incomplete">Incomplete</a> | ||||
|         <a class="example-todo-button" data-filter="complete">Complete</a> | ||||
|     </div> | ||||
|  | ||||
|     <ul class="example-todo-task-list"> | ||||
|     </ul> | ||||
|  | ||||
|     <div class="example-no-tasks"> | ||||
|         There are no tasks to show. | ||||
|     </div> | ||||
| </div> | ||||
							
								
								
									
										273
									
								
								tutorials/todo/todo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								tutorials/todo/todo.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,273 @@ | ||||
| define([ | ||||
|     "text!./todo.html", | ||||
|     "text!./todo-task.html", | ||||
|     "text!./todo-toolbar.html", | ||||
|     "text!./todo-dialog.html", | ||||
|     "../../src/api/objects/object-utils", | ||||
|     "zepto" | ||||
| ], function (todoTemplate, taskTemplate, toolbarTemplate, dialogTemplate, utils, $) { | ||||
|     /** | ||||
|      * @param {mct.MCT} mct | ||||
|      */ | ||||
|     return function todoPlugin(mct) { | ||||
|         var todoType = new mct.Type({ | ||||
|             metadata: { | ||||
|                 label: "To-Do List", | ||||
|                 glyph: "2", | ||||
|                 description: "A list of things that need to be done." | ||||
|             }, | ||||
|             initialize: function (model) { | ||||
|                 model.tasks = [ | ||||
|                     { description: "This is a task." } | ||||
|                 ]; | ||||
|             }, | ||||
|             creatable: true | ||||
|         }); | ||||
|  | ||||
|         function TodoView(domainObject) { | ||||
|             this.tasks = domainObject.tasks; | ||||
|             this.filterValue = "all"; | ||||
|  | ||||
|             this.setTaskStatus = this.setTaskStatus.bind(this); | ||||
|             this.selectTask = this.selectTask.bind(this); | ||||
|  | ||||
| <<<<<<< HEAD | ||||
|             this.mutableObject = mct.Objects.getMutable(domainObject); | ||||
|             this.mutableObject.on('tasks', this.updateTasks.bind(this)); | ||||
| ======= | ||||
|             //If anything on object changes, re-render view | ||||
|             this.mutableObject.on("*", this.objectChanged); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.show = function (container) { | ||||
|             var self = this; | ||||
|             this.destroy(); | ||||
|  | ||||
|             self.$els = $(todoTemplate); | ||||
|             self.$buttons = { | ||||
|                 all: self.$els.find('.example-todo-button-all'), | ||||
|                 incomplete: self.$els.find('.example-todo-button-incomplete'), | ||||
|                 complete: self.$els.find('.example-todo-button-complete') | ||||
|             }; | ||||
|  | ||||
|             $(container).empty().append(self.$els); | ||||
| >>>>>>> origin/api-tutorials | ||||
|  | ||||
|             this.$el = $(todoTemplate); | ||||
|             this.$emptyMessage = this.$el.find('.example-no-tasks'); | ||||
|             this.$taskList = this.$el.find('.example-todo-task-list'); | ||||
|             this.$el.on('click', '[data-filter]', this.updateFilter.bind(this)); | ||||
|             this.$el.on('change', 'li', this.setTaskStatus.bind(this)); | ||||
|             this.$el.on('click', '.example-task-description', this.selectTask.bind(this)); | ||||
|  | ||||
| <<<<<<< HEAD | ||||
|             this.updateSelection = this.updateSelection.bind(this); | ||||
|             mct.selection.on('change', this.updateSelection); | ||||
|         } | ||||
|  | ||||
|         TodoView.prototype.show = function (container) { | ||||
|             $(container).empty().append(this.$el); | ||||
|             this.render(); | ||||
| ======= | ||||
|             self.initialize(); | ||||
|             self.objectChanged(this.domainObject); | ||||
|  | ||||
|             mct.selection.on('change', self.render); | ||||
| >>>>>>> origin/api-tutorials | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.destroy = function () { | ||||
|             this.mutableObject.stopListening(); | ||||
|             mct.selection.off('change', this.updateSelection); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.updateSelection = function (selection) { | ||||
|             if (selection && selection.length) { | ||||
|                 this.selection = selection[0].index; | ||||
|             } else { | ||||
|                 this.selection = -1; | ||||
|             } | ||||
|             this.render(); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.updateTasks = function (tasks) { | ||||
|             this.tasks = tasks; | ||||
|             this.render(); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.updateFilter = function (e) { | ||||
|             this.filterValue = $(e.target).data('filter'); | ||||
|             this.render(); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.setTaskStatus = function (e) { | ||||
|             var $checkbox = $(e.target); | ||||
|             var taskIndex = $checkbox.data('taskIndex'); | ||||
|             var completed = !!$checkbox.prop('checked'); | ||||
|             this.tasks[taskIndex].completed = completed; | ||||
|             this.mutableObject.set('tasks[' + taskIndex + '].checked', completed); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.selectTask = function (e) { | ||||
|             var taskIndex = $(e.target).data('taskIndex'); | ||||
|             mct.selection.clear(); | ||||
|             mct.selection.select({index: taskIndex}); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.getFilteredTasks = function () { | ||||
|             return this.tasks.filter({ | ||||
|                 all: function () { | ||||
|                     return true; | ||||
|                 }, | ||||
|                 incomplete: function (task) { | ||||
|                     return !task.completed; | ||||
|                 }, | ||||
|                 complete: function (task) { | ||||
|                     return task.completed; | ||||
|                 } | ||||
|             }[this.filterValue]); | ||||
|         }; | ||||
|  | ||||
|         TodoView.prototype.render = function () { | ||||
|             var filteredTasks = this.getFilteredTasks(); | ||||
|             this.$emptyMessage.toggle(filteredTasks.length === 0); | ||||
|             this.$taskList.empty(); | ||||
|             filteredTasks | ||||
|                 .forEach(function (task) { | ||||
|                     var $taskEl = $(taskTemplate), | ||||
|                         taskIndex = this.tasks.indexOf(task); | ||||
|                     $taskEl.find('.example-task-checked') | ||||
|                         .prop('checked', task.completed) | ||||
|                         .attr('data-task-index', taskIndex); | ||||
|                     $taskEl.find('.example-task-description') | ||||
|                         .text(task.description) | ||||
|                         .toggleClass('selected', taskIndex === this.selection) | ||||
|                         .attr('data-task-index', taskIndex); | ||||
|  | ||||
|                     this.$taskList.append($taskEl); | ||||
|                 }, this); | ||||
|         }; | ||||
|  | ||||
|         function TodoToolbarView(domainObject) { | ||||
|             this.tasks = domainObject.tasks; | ||||
|             this.mutableObject = mct.Objects.getMutable(domainObject); | ||||
|  | ||||
|             this.handleSelectionChange = this.handleSelectionChange.bind(this); | ||||
|  | ||||
|             this.mutableObject.on('tasks', this.updateTasks.bind(this)); | ||||
|             mct.selection.on('change', this.handleSelectionChange); | ||||
|             this.$el = $(toolbarTemplate); | ||||
|             this.$remove = this.$el.find('.example-remove'); | ||||
|             this.$el.on('click', '.example-add', this.addTask.bind(this)); | ||||
|             this.$el.on('click', '.example-remove', this.removeTask.bind(this)); | ||||
|         } | ||||
|  | ||||
|         TodoToolbarView.prototype.updateTasks = function (tasks) { | ||||
|             this.tasks = tasks; | ||||
|         }; | ||||
|  | ||||
|         TodoToolbarView.prototype.addTask = function () { | ||||
|             var $dialog = $(dialogTemplate), | ||||
|                 view = { | ||||
|                     show: function (container) { | ||||
|                         $(container).append($dialog); | ||||
|                     }, | ||||
|                     destroy: function () {} | ||||
|                 }; | ||||
|  | ||||
|             mct.dialog(view, "Add a Task").then(function () { | ||||
|                 var description = $dialog.find('input').val(); | ||||
|                 this.tasks.push({description: description}); | ||||
|                 this.mutableObject.set('tasks', this.tasks); | ||||
|             }.bind(this)); | ||||
|         }; | ||||
|  | ||||
|         TodoToolbarView.prototype.removeTask = function () { | ||||
|             if (this.selection >= 0) { | ||||
|                 this.tasks.splice(this.selection, 1); | ||||
|                 this.mutableObject.set('tasks', this.tasks); | ||||
|                 mct.selection.clear(); | ||||
|                 this.render(); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         TodoToolbarView.prototype.show = function (container) { | ||||
|             var self = this; | ||||
|             this.destroy(); | ||||
|             this.$els = $(toolbarTemplate); | ||||
|             this.render(); | ||||
|             $(container).append(this.$els); | ||||
|         }; | ||||
|  | ||||
|         TodoToolbarView.prototype.render = function () { | ||||
|             var self = this; | ||||
|             var $els = this.$els; | ||||
|  | ||||
|             self.mutableObject = mct.Objects.getMutable(this.domainObject); | ||||
|  | ||||
|             var $add = $els.find('a.example-add'); | ||||
|             var $remove = $els.find('a.example-remove'); | ||||
|  | ||||
|             $add.on('click', function () { | ||||
|                 var $dialog = $(dialogTemplate), | ||||
|                     view = { | ||||
|                         show: function (container) { | ||||
|                             $(container).append($dialog); | ||||
|                         }, | ||||
|                         destroy: function () {} | ||||
|                     }; | ||||
|  | ||||
|                 new mct.Dialog(view, "Add a Task").show().then(function () { | ||||
|                     var description = $dialog.find('input').val(); | ||||
|                     var tasks = self.mutableObject.get('tasks'); | ||||
|                     tasks.push({ description: description }); | ||||
|                     self.mutableObject.set('tasks', tasks); | ||||
|                 }); | ||||
|             }); | ||||
|             $remove.on('click', function () { | ||||
|                 var index = mct.selection.selected()[0].index; | ||||
|                 if (index !== undefined) { | ||||
|                     var tasks = self.mutableObject.get('tasks').filter(function (t, i) { | ||||
|                         return i !== index; | ||||
|                     }); | ||||
|                     self.mutableObject.set("tasks", tasks); | ||||
|                     self.mutableObject.set("selected", undefined); | ||||
|                     mct.selection.clear(); | ||||
|                 } | ||||
|             }); | ||||
|             self.$remove = $remove; | ||||
|             self.handleSelectionChange(); | ||||
|             mct.selection.on('change', self.handleSelectionChange); | ||||
|         }; | ||||
|  | ||||
|         TodoToolbarView.prototype.handleSelectionChange = function () { | ||||
|             var selected = mct.selection.selected(); | ||||
|             if (this.$remove) { | ||||
|                 this.$remove.toggle(selected.length > 0); | ||||
|             } | ||||
|             this.render(); | ||||
|         }; | ||||
|  | ||||
|         TodoToolbarView.prototype.destroy = function () { | ||||
|             mct.selection.off('change', this.handleSelectionChange); | ||||
|             this.mutableObject.stopListening(); | ||||
|         }; | ||||
|  | ||||
|         mct.type('example.todo', todoType); | ||||
|         mct.view(mct.regions.main, { | ||||
|             view: function (domainObject) { | ||||
|                 return new TodoView(domainObject); | ||||
|             }, | ||||
|             canView: todoType.check.bind(todoType) | ||||
|         }); | ||||
|  | ||||
|         mct.view(mct.regions.toolbar, { | ||||
|             view: function (domainObject) { | ||||
|                 return new TodoToolbarView(domainObject); | ||||
|             }, | ||||
|             canView: todoType.check.bind(todoType) | ||||
|         }); | ||||
|  | ||||
|         return mct; | ||||
|     }; | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user