Table of Contents

Open MCT Developer Guide

Victor Woeltjen

victor.woeltjen@nasa.gov

September 23, 2015
Document Version 1.1

Date Version Summary of Changes Author
April 29, 2015 0 Initial Draft Victor Woeltjen
May 12, 2015 0.1 Victor Woeltjen
June 4, 2015 1.0 Name Changes Victor Woeltjen
October 4, 2015 1.1 Conversion to MarkDown Andrew Henry
April 5, 2016 1.2 Added Mct-table directive Andrew Henry

Introduction

The purpose of this guide is to familiarize software developers with the Open MCT Web platform.

What is Open MCT

Open MCT is a platform for building user interface and display tools, developed at the NASA Ames Research Center in collaboration with teams at the Jet Propulsion Laboratory. It is written in HTML5, CSS3, and JavaScript, using AngularJS as a framework. Its intended use is to create single-page web applications which integrate data and behavior from a variety of sources and domains.

Open MCT has been developed to support the remote operation of space vehicles, so some of its features are specific to that task; however, it is flexible enough to be adapted to a variety of other application domains where a display tool oriented toward browsing, composing, and visualizing would be useful.

Open MCT provides:

Client-Server Relationship

Open MCT is client software - it runs entirely in the user's web browser. As such, it is largely 'server agnostic'; any web server capable of serving files from paths is capable of providing Open MCT.

While Open MCT can be configured to run as a standalone client, this is rarely very useful. Instead, it is intended to be used as a display and interaction layer for information obtained from a variety of back-end services. Doing so requires authoring or utilizing adapter plugins which allow Open MCT Web to interact with these services.

Typically, the pattern here is to provide a known interface that Open MCT can utilize, and implement it such that it interacts with whatever back-end provides the relevant information. Examples of back-ends that can be utilized in this fashion include databases for the persistence of user-created objects, or sources of telemetry data.

See the Architecture Guide for information on the client-server relationship.

Developing with Open MCT

Building applications with Open MCT typically means authoring and utilizing a set of plugins which provide application-specific details about how Open MCT Web should behave.

Technologies

Open MCT sources are written in JavaScript, with a number of configuration files written in JSON. Displayable components are written in HTML5 and CSS3.
Open MCT is built using AngularJS from Google. A good understanding of Angular is recommended for developers working with Open MCT Web.

Forking

Open MCT does not currently have a single stand-alone artifact that can be used as a library. Instead, the recommended approach for creating a new application is to start by forking/branching Open MCT, and then adding new features from there. Put another way, Open MCT's source structure is built to serve as a template for specific applications.

Forking in this manner should not require that you edit Open MCT's sources. The preferred approach is to create a new directory (peer to index.html) for the new application, then add new bundles (as described in the Framework chapter) within that directory.

To initially clone the Open MCT repository: git clone <repository URL> <local repo directory> -b open-master

To create a fork to begin working on a new application using Open MCT:

cd <local repo directory>  
git checkout open-master
git checkout -b <new branch name>

As a convention used internally, applications built using Open MCT have master branch names with an identifying prefix. For instance, if building an application called 'Foo', the last statement above would look like:

git checkout -b foo-master

This convention is not enforced or understood by Open MCT in any way; it is mentioned here as a more general recommendation.

Overview

Open MCT is implemented as a framework component which manages a set of other components. These components, called bundles, act as containers to group sets of related functionality; individual units of functionality are expressed within these bundles as extensions.

Extensions declare dependencies on other extensions (either individually or categorically), and the framework provides actual extension instances at run-time to satisfy these declared dependency. This dependency injection approach allows software components which have been authored separately (e.g. as plugins) but to collaborate at run-time.

Open MCT's framework layer is implemented on top of AngularJS's dependency injection mechanism and is modelled after OSGi and its Declarative Services component model. In particular, this is where the term bundle comes from.

Framework Overview

The framework's role in the application is to manage connections between bundles. All application-specific behavior is provided by individual bundles, or as the result of their collaboration.

The framework is described in more detail in the Framework Overview of the architecture guide.

Tiers

While all bundles in a running Open MCT instance are effectively peers, it is useful to think of them as a tiered architecture, where each tier adds more specificity to the application.

Diagram 1

Note that bundles in any tier can go off and consult back-end services. In practice, this responsibility is handled at the Application and/or Plugin tiers; Open MCT is built to be server-agnostic, so any back-end is considered an application-specific detail.

Platform Overview

The "tiered" architecture described in the preceding text describes a way of thinking of and categorizing software components of a Open MCT application, as well as the framework layer's role in mediating between these components. Once the framework layer has wired these software components together, however, the application's logical architecture emerges.

An overview of the logical architecture of the platform is given in the Platform Architecture section of the Platform guide

Web Services

As mentioned in the Introduction, Open MCT is a platform single-page applications which runs entirely in the browser. Most applications will want to additionally interact with server-side resources, to (for example) read telemetry data or store user-created objects. This interaction is handled by individual bundles using APIs which are supported in browser (such as XMLHttpRequest, typically wrapped by Angular's $http.)

Diagram 2

This architectural approach ensures a loose coupling between applications built using Open MCT and the backends which support them.

Glossary

Certain terms are used throughout Open MCT with consistent meanings or conventions. Other developer documentation, particularly in-line documentation, may presume an understanding of these terms.

Framework

Open MCT is built on the AngularJS framework. A good understanding of that framework is recommended.

Open MCT adds an extra layer on top of AngularJS to (a) generalize its dependency injection mechanism slightly, particularly to handle many-to-one relationships; and (b) handle script loading. Combined, these features become a plugin mechanism.

This framework layer operates on two key concepts:

The framework layer, loaded and initiated from index.html, is the main point of entry for an application built on Open MCT. It is responsible for wiring together the application at run time (much of this responsibility is actually delegated to Angular); at a high-level, the framework does this by proceeding through four stages:

  1. Loading definitions: JSON declarations are loaded for all bundles which will constitute the application, and wrapped in a useful API for subsequent stages.
  2. Resolving extensions: Any scripts which provide implementations for extensions exposed by bundles are loaded, using Require.
  3. Registering extensions Resolved extensions are registered with Angular, such that they can be used by the application at run-time. This stage includes both registration of Angular built-ins (directives, controllers, routes, constants, and services) as well as registration of non-Angular extensions.
  4. Bootstrapping The Angular application is bootstrapped; at that point, Angular takes over and populates the body of the page using the extensions that have been registered.

Bundles

The basic configurable unit of Open MCT is the bundle. This term has been used a bit already; now we'll get to a more formal definition.

A bundle is a directory which contains:

The bundle definition is the main point of entry for the bundle. The framework looks at this to determine which components need to be loaded and how they interact.

A plugin in Open MCT is a bundle. The platform itself is also decomposed into bundles, each of which provides some category of functionality. The difference between a bundle and a plugin is purely a matter of the intended use; a plugin is just a bundle that is meant to be easily added or removed. When developing, it is typically more useful to think in terms of bundles.

Configuring Active Bundles

To decide which bundles should be loaded, the framework loads a file named bundles.json (peer to the index.html file which serves the application) to determine which bundles should be loaded. This file should contain a single JSON array of strings, where each is the path to a bundle. These paths should not include bundle.json (this is implicit) or a trailing slash.

For instance, if bundles.json contained:

[ 
    "example/builtins", 
    "example/extensions" 
] 

...then the Open MCT framework would look for bundle definitions at example/builtins/bundle.json and example/extensions/bundle.json, relative to the path of index.html. No other bundles would be loaded.

Bundle Definition

A bundle definition (the bundle.json file located within a bundle) contains a description of the bundle itself, as well as the information exposed by the bundle.

This definition is expressed as a single JSON object with the following properties (all of which are optional, falling back to reasonable defaults):

For example, the bundle definition for example/policy looks like:

{
    "name": "Example Policy", 
    "description": "Provides an example of using policies.", 
    "sources": "src", 
    "extensions": { 
        "policies": [ 
            { 
                "implementation": "ExamplePolicy.js", 
                "category": "action" 
            }
        ] 
    } 
}

Bundle Directory Structure

In addition to the directories defined in the bundle definition, a bundle will typically contain other directories not used at run-time. Additionally, some useful development scripts (such as the command line build and the test suite) expect this directory structure to be in use, and may ignore options chosen by bundle.json. It is recommended that the directory structure described below be used for new bundles.

For example, the directory structure for bundle platform/commonUI/about looks like:

Platform
  |
  |-commonUI
  |
  +-about
    |
    |-res
    |
    |-src
    |
    |-test
    |
    |-bundle.json
    |
    +-README.md

Extensions

While bundles provide groupings of related behaviors, the individual units of behavior are called extensions.

Extensions belong to categories; an extension category is the machine-readable identifier used to identify groups of extensions. In the extensions property of a bundle definition, the keys are extension categories and the values are arrays of extension definitions.

General Extensions

Extensions are intended as a general-purpose mechanism for adding new types of functionality to Open MCT.

An extension category is registered with Angular under the name of the extension, plus a suffix of two square brackets; so, an Angular service (or, generally, any other extension) can access the full set of registered extensions, from all bundles, by including this string (e.g. types[] to get all type definitions) in a dependency declaration.

As a convention, extension categories are given single-word, plural nouns for names within Open MCT (e.g. types.) This convention is not enforced by the platform in any way. For extension categories introduced by external plugins, it is recommended to prefix the extension category with a vendor identifier (or similar) followed by a dot, to avoid collisions.

Extension Definitions

The properties used in extension definitions are typically unique to each category of extension; a few properties have standard interpretations by the platform.

Extensions do not need to have an implementation. If no implementation is provided, consumers of the extension category will receive the extension definition as a plain JavaScript object. Otherwise, they will receive the partialized (see below) constructor for that implementation, which will additionally have all properties from the extension definition attached.

Partial Construction

In general, extensions are intended to be implemented as constructor functions, which will be used elsewhere to instantiate new objects of that type. However, the Angular-supported method for dependency injection is (effectively) constructor-style injection; so, both declared dependencies and run-time arguments are competing for space in a constructor's arguments.

To resolve this, the Open MCT framework registers extension instances in a partially constructed form. That is, the constructor exposed by the extension's implementation is effectively decomposed into two calls; the first takes the dependencies, and returns the constructor in its second form, which takes the remaining arguments.

This means that, when writing implementations, the constructor function should be written to include all declared dependencies, followed by all run-time arguments. When using extensions, only the run-time arguments need to be provided.

Priority

Within each extension category, registration occurs in priority order. An extension's priority may be specified as a priority property in its extension definition; this may be a number, or a symbolic string. Extensions are registered in reverse order (highest-priority first), and symbolic strings are mapped to the numeric values as follows:

These symbolic names are chosen to support usage where many extensions may satisfy a given need, but only one may be used; in this case, as a convention it should be the lowest-ordered (highest-priority) extensions available. In other cases, a full set (or multi-element subset) of extensions may be desired, with a specific ordering; in these cases, it is preferable to specify priority numerically when declaring extensions, and to understand that extensions will be sorted according to these conventions when using them.

Angular Built-ins

Several entities supported Angular are expressed and managed as extensions in Open MCT. Specifically, these extension categories are directives, controllers, services, constants, runs, and routes.

Angular Directives

New directives may be registered as extensions of the directives category. Implementations of directives in this category should take only dependencies as arguments, and should return a directive definition object.

The directive's name should be provided as a key property of its extension definition, in camel-case format.

Angular Controllers

New controllers may be registered as extensions of the controllers category. The implementation is registered directly as the controller; its only constructor arguments are its declared dependencies.

The directive's identifier should be provided as a key property of its extension definition.

Angular Services

New services may be registered as extensions of the services category. The implementation is registered via a service call, so it will be instantiated with the new operator.

Angular Constants

Constant values may be registered as extensions of the constants category. These extensions have no implementation; instead, they should contain a property key , which is the name under which the constant will be registered, and a property value , which is the constant value that will be registered.

Angular Runs

In some cases, you want to register code to run as soon as the application starts; these can be registered as extensions of the runs category. Implementations registered in this category will be invoked (with their declared dependencies) when the Open MCT application first starts. (Note that, in this case, the implementation is better thought of as just a function, as opposed to a constructor function.)

Angular Routes

Extensions of category routes will be registered with Angular's route provider. Extensions of this category have no implementations, and need only two properties in their definition:

Composite Services

Composite services are described in the Composite Services section of the framework guide.

A component should include the following properties in its extension definition:

In addition to any declared dependencies, aggregators and decorators both receive one more argument (immediately following declared dependencies) that is provided by the framework. For an aggregator, this will be an array of all providers of the same service (that is, with matching provides properties); for a decorator, this will be whichever provider, decorator, or aggregator is next in the sequence of decorators.

Services exposed by the Open MCT platform are often declared as composite services, as this form is open for a variety of common modifications.

Core API

Most of Open MCT's relevant API is provided and/or mediated by the framework; that is, much of developing for Open MCT is a matter of adding extensions which access other parts of the platform by means of dependency injection.

The core bundle (platform/core) introduces a few additional object types meant to be passed along by other services.

Domain Objects

Domain objects are the most fundamental component of Open MCT's information model. A domain object is some distinct thing relevant to a user's workflow, such as a telemetry channel, display, or similar. Open MCT is a tool for viewing, browsing, manipulating, and otherwise interacting with a graph of domain objects.

A domain object should be conceived of as the union of the following:

At run-time, a domain object has the following interface:

Identifier Syntax

For most purposes, a domain object identifier can be treated as a purely symbolic string; these are typically generated by Open MCT and plug-ins should rarely be concerned with its internal structure.

A domain object identifier has one or two parts, separated by a colon.

Some examples:

<identifier> ::= <space> ":" <key> | <key>
<space> ::= <id char>+
<key> ::= <id char>+
<id char> ::= <letter> | <digit> | "-" | "." | "_"

Domain Object Actions

An Action is behavior that can be performed upon/using a DomainObject. An Action has the following interface:

Action instances are typically obtained via a domain object's action capability.

Action Contexts

An action context is a JavaScript object with the following properties:

Telemetry

Telemetry series data in Open MCT is represented by a common interface, and packaged in a consistent manner to facilitate passing telemetry updates around multiple visualizations.

Telemetry Requests

A telemetry request is a JavaScript object containing the following properties:

Additional properties may be included in telemetry requests which have specific interpretations for specific sources.

Telemetry Responses

When returned from the telemetryService (see Telemetry Services section), telemetry series data will be packaged in a source -> key -> TelemetrySeries fashion. That is, telemetry is passed in an object containing key-value pairs. Keys identify telemetry sources; values are objects containing additional key-value pairs. In this object, keys identify individual telemetry series (and match they key property from corresponding requests) and values are TelemetrySeries objects (see below.)

Telemetry Series

A telemetry series is a specific sequence of data, typically associated with a specific instrument. Telemetry is modeled as an ordered sequence of domain and range values, where domain values must be non-decreasing but range values do not. (Typically, domain values are interpreted as UTC timestamps in milliseconds relative to the UNIX epoch.) A series must have at least one domain and one range, and may have more than one.

Telemetry series data in Open MCT is expressed via the following TelemetrySeries interface:

Telemetry Metadata

Domain objects which have associated telemetry also expose metadata about that telemetry; this is retrievable via the getMetadata() of the telemetry capability. This will return a single JavaScript object containing the following properties:

Note that this metadata is also used as the prototype for telemetry requests made using this capability.

Types

A domain object's type is represented as a Type object, which has the following interface:

Type Features

Features of a domain object type are expressed as symbolic string identifiers. They are defined in practice by usage; currently, the Open MCT platform only uses the creation feature to determine which domain object types should appear in the Create menu.

Type Properties

Types declare the user-editable properties of their domain object instances in order to allow the forms which appear in the Create and Edit Properties dialogs to be generated by the platform. A TypeProperty has the following interface:

Extension Categories

The information in this section is focused on registering new extensions of specific types; it does not contain a catalog of the extension instances of these categories provided by the platform. Relevant summaries there are provided in subsequent sections.

Actions Category

An action is a thing that can be done to or using a domain object, typically as initiated by the user.

An action's implementation:

An action's bundle definition (and/or getMetadata() return value) may include:

Capabilities Category

Capabilities are exposed by domain objects (e.g. via the getCapability method) but most commonly originate as extensions of this category.

Extension definitions for capabilities should include both an implementation, and a property named key whose value should be a string used as a machine-readable identifier for that capability, e.g. when passed as the argument to a domain object's getCapability(key) call.

A capability's implementation should have methods specific to that capability; that is, there is no common format for capability implementations, aside from support for invocation via the useCapability shorthand.

A capability's implementation will take a single argument (in addition to any declared dependencies), which is the domain object that will expose that capability.

A capability's implementation may also expose a static method appliesTo(model) which should return a boolean value, and will be used by the platform to filter down capabilities to those which should be exposed by specific domain objects, based on their domain object models.

Containers Category

Containers provide options for the mct-container directive.

The definition for an extension in the containers category should include:

Note that templateUrl is not supported for containers.

Controls Category

Controls provide options for the mct-control directive.

These standard control types are included in the forms bundle:

New controls may be added as extensions of the controls category. Extensions of this category have two properties:

Within the template for a control, the following variables will be included in scope:

Gestures Category

A gesture is a user action which can be taken upon a representation of a domain object.

Examples of gestures included in the platform are:

Gesture definitions have a property key which is used as a machine-readable identifier for the gesture (e.g. drag, drop, menu above.)

A gesture's implementation is instantiated once per representation that uses the gesture. This class will receive the jqLite-wrapped mct-representation element and the domain object being represented as arguments, and should do any necessary "wiring" (e.g. listening for events) during its constructor call. The gesture's implementation may also expose an optional destroy() method which will be called when the gesture should be removed, to avoid memory leaks by way of unremoved listeners.

Indicators Category

An indicator is an element that should appear in the status area at the bottom of a running Open MCT client instance.

Standard Indicators

Indicators which wish to appear in the common form of an icon-text pair should provide implementations with the following methods:

Note that all methods are optional, and are called directly from an Angular template, so they should be appropriate to run during digest cycles.

Custom Indicators

Indicators which wish to have an arbitrary appearance (instead of following the icon-text convention commonly used) may specify a template property in their extension definition. The value of this property will be used as the key for an mct-include directive (so should refer to an extension of category templates .) This template will be rendered to the status area. Indicators of this variety do not need to provide an implementation.

Licenses Category

The extension category licenses can be used to add entries into the 'Licensing information' page, reachable from Open MCT's About dialog.

Licenses may have the following properties, all of which are strings:

Policies Category

Policies are used to handle decisions made using Open MCT's policyService; examples of these decisions are determining the applicability of certain actions, or checking whether or not a domain object of one type can contain a domain object of a different type. See the section on the Policies for an overview of Open MCT's policy model.

A policy's extension definition should include:

A policy's implementation should include a single method, allow(candidate, context). The specific types used for candidate and context vary by policy category; in general, what is being asked is 'is this candidate allowed in this context?' This method should return a boolean value.

Open MCT's policy model requires consensus; a policy decision is allowed when and only when all policies choose to allow it. As such, policies should generally be written to reject a certain case, and allow (by returning true) anything else.

Representations Category

A representation is an Angular template used to display a domain object. The representations extension category is used to add options for the mct-representation directive.

A representation definition should include the following properties:

Representation Scope

While representations do not have implementations, per se, they do refer to Angular templates which need to interact with information (e.g. the domain object being represented) provided by the platform. This information is passed in through the template's scope, such that simple representations may be created by providing only templates. (More complex representations will need controllers which are referenced from templates. See https://docs.angularjs.org/guide/controller for more information on controllers in Angular.)

A representation's scope will contain:

Representers Category

The representers extension category is used to add additional behavior to the mct-representation directive. This extension category is intended primarily for use internal to the platform.

Unlike representations, which describe specific ways to represent domain objects, representers are used to modify or augment the process of representing domain objects in general. For example, support for the gestures extension category is added by a representer.

A representer needs only provide an implementation. When an mct-representation is linked (see https://docs.angularjs.org/guide/directive ) or when the domain object being represented changes, a new representer of each declared type is instantiated. The constructor arguments for a representer are the same as the arguments to the link function in an Angular directive: scope the Angular scope for this representation; element the jqLite-wrapped mct-representation element, and attrs a set of key-value pairs of that element's attributes. Representers may wish to populate the scope, attach event listeners to the element, etc.

This implementation must provide a single method, destroy(), which will be invoked when the representer is no longer needed.

Roots Category

The extension category roots is used to provide root-level domain object models. Root-level domain objects appear at the top-level of the tree hierarchy. For example, the My Items folder is added as an extension of this category.

Extensions of this category should have the following properties:

Stylesheets Category

The stylesheets extension category is used to add CSS files to style the application. Extension definitions for this category should include one property:

To control the order of CSS files, use priority (see the section on Extension Definitions above.)

Templates Category

The templates extension category is used to expose Angular templates under symbolic identifiers. These can then be utilized using the mct-include directive, which behaves similarly to ng-include except that it uses these symbolic identifiers instead of paths.

A template's extension definition should include the following properties:

Note that, when multiple templates are present with the same key , the one with the highest priority will be used from mct-include. This behavior can be used to override templates exposed by the platform (to change the logo which appears in the bottom right, for instance.)

Templates do not have implementations.

Types Category

The types extension category describes types of domain objects which may appear within Open MCT.

A type's extension definition should have the following properties:

Types do not have implementations.

Versions Category

The versions extension category is used to introduce line items in Open MCT Web's About dialog. These should have the following properties:

To control the ordering of line items within the About dialog, use priority. (See section on Extensions above.)

This extension category does not have implementations.

Views Category

The views extension category is used to determine which options appear to the user as available views of domain objects of specific types. A view's extension definition has the same properties as a representation (and views can be utilized via mct-representation); additionally:

View Scope

Views do not have implementations, but do get the same properties in scope that are provided for representations.

When a view is in Edit mode, this scope will additionally contain:

Selection State

A view's selection state is, conceptually, a set of JavaScript objects. The presence of methods/properties on these objects determine which toolbar controls are visible, and what state they manage and/or behavior they invoke.

This set may contain up to two different objects: The view proxy, which is used to make changes to the view as a whole, and the selected object, which is used to represent some state within the view. (Future versions of Open MCT may support multiple selected objects.)

The selection object made available during Edit mode has the following methods:

Workers Category

The workers extension category allows scripts to be run as web workers using the workerService.

An extension of this category has no implementation. The following properties are supported:

Directives

Open MCT defines several Angular directives that are intended for use both internally within the platform, and by plugins.

Container

The mct-container is similar to the mct-include directive insofar as it allows templates to be referenced by symbolic keys instead of by URL. Unlike mct-include it supports transclusion.

Unlike mct-include mct-container accepts a key as a plain string attribute, instead of as an Angular expression.

Control

The mct-control directive is used to display user input elements. Several controls are included with the platform to wrap default input types. This directive is primarily intended for internal use by the mct-form and mct-toolbar directives.

When using mct-control the attributes ng-model ng-disabled ng-required and ng-pattern may also be used. These have the usual meaning (as they would for an input element) except for ng-model; when used, it will actually be ngModel[field] (see below) that is two-way bound by this control. This allows mct-control elements to more easily delegate to other mct-control instances, and also facilitates usage for generated forms.

This directive supports the following additional attributes, all specified as Angular expressions:

Drag

The mct-drag directive is used to support drag-based gestures on HTML elements. Note that this is not 'drag' in the 'drag-and-drop' sense, but 'drag' in the more general 'mouse down, mouse move, mouse up' sense.

This takes the form of three attributes:

In each case, a variable delta will be provided to the expression; this is a two-element array or the horizontal and vertical pixel offset of the current mouse position relative to the mouse position where dragging began.

Form

The mct-form directive is used to generate forms using a declarative structure, and to gather back user input. It is applicable at the element level and supports the following attributes:

Form Structure

Forms in Open MCT have a common structure to permit consistent display. A form is broken down into sections, which will be displayed in groups; each section is broken down into rows, each of which provides a control for a single property. Input from this form is two-way bound to the object passed via ng-model.

A form's structure is represented by a JavaScript object in the following form:

{ 
    "name": ... title to display for the form, as a string ..., 
    "sections": [
    { 
        "name": ... title to display for the section ..., 
        "rows": [ 
            { 
                "name": ... title to display for this row ...,
                "control": ... symbolic key for the control ..., 
                "key": ... field name in ng-model ... 
                "pattern": ... optional, reg exp to match against ... 
                "required": ... optional boolean ... 
                "options": [ 
                    "name": ... name to display (e.g. in a select) ..., 
                    "value": ... value to store in the model ... 
                ] 
                }, 
            ... and other rows ... 
        ] 
    }, 
    ... and other sections ... 
    ] 
} 

Note that pattern may be specified as a string, to simplify storing for structures as JSON when necessary. The string should be given in a form appropriate to pass to a RegExp constructor.

Form Controls

A few standard control types are included in the platform/forms bundle:

Include

The mct-include directive is similar to ng-include , except that it takes a symbolic identifier for a template instead of a URL. Additionally, templates included via mct-include will have an isolated scope.

The directive should be used at the element level and supports the following attributes, all of which are specified as Angular expressions:

Representation

The mct-representation directive is used to include templates which specifically represent domain objects. Usage is similar to mct-include.

The directive should be used at the element level and supports the following attributes, all of which are specified as Angular expressions:

Resize

The mct-resize directive is used to monitor the size of an HTML element. It is specified as an attribute whose value is an Angular expression that will be evaluated when the size of the HTML element changes. This expression will be provided a single variable, bounds which is an object containing two properties, width and height describing the size in pixels of the element.

When using this directive, an attribute mct-resize-interval may optionally be provided. Its value is an Angular expression describing the number of milliseconds to wait before next checking the size of the HTML element; this expression is evaluated when the directive is linked and reevaluated whenever the size is checked.

Scroll

The mct-scroll-x and mct-scroll-y directives are used to both monitor and control the horizontal and vertical scroll bar state of an element, respectively. They are intended to be used as attributes whose values are assignable Angular expressions which two-way bind to the scroll bar state.

Toolbar

The mct-toolbar directive is used to generate toolbars using a declarative structure, and to gather back user input. It is applicable at the element level and supports the following attributes:

Toolbars support the same control options as forms.

Toolbar Structure

A toolbar's structure is defined similarly to forms, except instead of rows
there are items .

{ 
    "name": ... title to display for the form, as a string ..., 
    "sections": [ 
        { 
            "name": ... title to display for the section ..., 
            "items": [ 
                { 
                    "name": ... title to display for this row ..., 
                    "control": ... symbolic key for the control ..., 
                    "key": ... field name in ng-model ... 
                    "pattern": ... optional, reg exp to match against ... 
                    "required": ... optional boolean ... 
                    "options": [ 
                        "name": ... name to display (e.g. in a select) ..., 
                        "value": ... value to store in the model ... 
                    ], 
                    "disabled": ... true if control should be disabled ... 
                    "size": ... size of the control (for textfields) ... 
                    "click": ... function to invoke (for buttons) ... 
                    "glyph": ... glyph to display (for buttons) ... 
                    "text": ... text within control (for buttons) ... 
                }, 
                ... and other rows ... 
            ] 
        }, 
        ... and other sections ... 
    ] 
}

Table

The mct-table directive provides a generic table component, with optional sorting and filtering capabilities. The table can be pre-populated with data by setting the rows parameter, and it can be updated in real-time using the add:row and remove:row broadcast events. The table will expand to occupy 100% of the size of its containing element. The table is highly optimized for very large data sets.

Events

The table supports two events for notifying that the rows have changed. For performance reasons, the table does not monitor the content of rows constantly.

eg. The code below adds a new row, and alerts the table using the add:row event. Sorting and filtering will be applied automatically by the table component.

$scope.rows.push(newRow);
$scope.$broadcast('add:row', $scope.rows.length-1);

eg. The code below removes a row from the rows array, and then alerts the table to its removal.

$scope.rows.slice(5, 1);
$scope.$broadcast('remove:row', 5);

Parameters

Services

The Open MCT platform provides a variety of services which can be retrieved and utilized via dependency injection. These services fall into two categories:

Composite Type Services

This section describes the composite services exposed by Open MCT, specifically focusing on their interface and contract.

In many cases, the platform will include a provider for a service which consumes a specific extension category; for instance, the actionService depends on actions[] and will expose available actions based on the rules defined for that extension category.

In these cases, it will usually be simpler to add a new extension of a given category (e.g. of category actions) even when the same behavior could be introduced by a service component (e.g. an extension of category components where provides is actionService and type is provider.)

Occasionally, the extension category does not provide enough expressive power to achieve a desired result. For instance, the Create menu is populated with create actions, where one such action exists for each creatable type. Since the framework does not provide a declarative means to introduce a new action per type declaratively, the platform implements this explicitly in an actionService component of type provider. Plugins may use a similar approach when the normal extension mechanism is insufficient to achieve a desired result.

Action Service

The Action Service (actionService) provides Action instances which are applicable in specific contexts. See Core API for additional notes on the interface for actions. The actionService has the following interface:

Capability Service

The Capability Service (capabilityService) provides constructors for capabilities which will be exposed for a given domain object.

The capabilityService has the following interface:

Dialog Service

The dialogService provides a means for requesting user input via a modal dialog. It has the following interface:

Dialog Structure

The object passed as the dialogStructure to getUserChoice should have the following properties:

Domain Object Service

The Object Service (objectService) provides domain object instances. It has the following interface:

Gesture Service

The gestureService is used to attach gestures (see extension category gestures) to representations. It has the following interface:

Model Service

The Model Service (modelService) provides domain object models. It has the following interface:

Persistence Service

The Persistence Service (persistenceService) provides the ability to load/store JavaScript objects (presumably serializing/deserializing to JSON in the process.) This is used primarily to store domain object models. It has the following interface:

Policy Service

The Policy Service (policyService) may be used to determine whether or not certain behaviors are allowed within the application. It has the following interface:

Telemetry Service

The Telemetry Service (telemetryService) is used to acquire telemetry data. See the section on Telemetry in Core API for more information on how both the arguments and responses of this service are structured.

When acquiring telemetry for display, it is recommended that the telemetryHandler service be used instead of this service. The telemetryHandler has additional support for subscribing to and requesting telemetry data associated with domain objects or groups of domain objects. See the Other Services section for more information.

The telemetryService has the following interface:

Type Service

The Type Service (typeService) exposes domain object types. It has the following interface:

View Service

The View Service (viewService) exposes definitions for views of domain objects. It has the following interface:

Other Services

Drag and Drop

The dndService provides information about the content of an active drag-and-drop gesture within the application. It is intended to complement the DataTransfer API of HTML5 drag-and-drop, by providing access to non-serialized JavaScript objects being dragged, as well as by permitting inspection during drag (which is normally prohibited by browsers for security reasons.)

The dndService has the following methods:

Navigation

The Navigation service provides information about the current navigation state of the application; that is, which object is the user currently viewing? This service merely tracks this state and notifies listeners; it does not take immediate action when navigation changes, although its listeners might.

The navigationService has the following methods:

Now

The service now is a function which acts as a simple wrapper for Date.now(). It is present mainly so that this functionality may be more easily mocked in tests for scripts which use the current time.

Telemetry Formatter

The Telemetry Formatter is a utility for formatting domain and range values read from a telemetry series.

telemetryFormatter has the following methods:

Telemetry Handler

The Telemetry Handler is a utility for retrieving telemetry data associated with domain objects; it is particularly useful for dealing with cases where the telemetry capability is delegated to contained objects (as occurs in Telemetry Panels.)

The telemetryHandler has the following methods:

Telemetry Handle

A TelemetryHandle has the following methods:

Worker Service

The workerService may be used to run web workers defined via the workers extension category. It has the following method:

Models

Domain object models in Open MCT are JavaScript objects describing the persistent state of the domain objects they describe. Their contents include a mix of commonly understood metadata attributes; attributes which are recognized by and/or determine the applicability of specific extensions; and properties specific to given types.

General Metadata

Some properties of domain object models have a ubiquitous meaning through Open MCT Web and can be utilized directly:

Extension-specific Properties

Other properties of domain object models have specific meaning imposed by other extensions within the Open MCT platform.

Capability-specific Properties

Some properties either trigger the presence/absence of certain capabilities, or are managed by specific capabilities:

View Configurations

Persistent configurations for specific views of domain objects are stored in the domain object model under the property configurations . This is an object containing key-value pairs, where keys identify the view, and values are objects containing view-specific (and view-managed) configuration properties.

Modifying Models

When interacting with a domain object's model, it is possible to make modifications to it directly. Don't! These changes may not be properly detected by the platform, meaning that other representations of the domain object may not be updated, changes may not be saved at the expected times, and generally, that unexpected behavior may occur. Instead, use the mutation capability.

Capabilities

Dynamic behavior associated with a domain object is expressed as capabilities. A capability is a JavaScript object with an interface that is specific to the type of capability in use.

Often, there is a relationship between capabilities and services. For instance, there is an action capability and an actionService , and there is a telemetry
capability as well as a telemetryService. Typically, the pattern here is that the capability will utilize the service for the specific domain object.

When interacting with domain objects, it is generally preferable to use a capability instead of a service when the option is available. Capability interfaces are typically easier to use and/or more powerful in these situations. Additionally, this usage provides a more robust substitutability mechanism; for instance, one could configure a plugin such that it provided a totally new implementation of a given capability which might not invoke the underlying service, while user code which interacts with capabilities remains indifferent to this detail.

Action Capability

The action capability is present for all domain objects. It allows applicable Action instances to be retrieved and performed for specific domain objects.

For example: domainObject.getCapability("action").perform("navigate"); ...will initiate a navigate action upon the domain object, if an action with key "navigate" is defined.

This capability has the following interface:

Composition Capability

The composition capability provides access to domain objects that are contained by this domain object. While the composition property of a domain object's model describes these contents (by their identifiers), the
composition capability provides a means to load the corresponding DomainObject instances in the same order. The absence of this property in the model will result in the absence of this capability in the domain object.

This capability has the following interface:

Delegation Capability

The delegation capability is used to communicate the intent of a domain object to delegate responsibilities, which would normally handled by other capabilities, to the domain objects in its composition.

This capability has the following interface:

The platform implementation of the delegation capability inspects the domain object's type definition for a property delegates , whose value is an array of strings describing which capabilities domain objects of that type wish to delegate. If this property is not present, the delegation capability will not be present in domain objects of that type.

Editor Capability

The editor capability is meant primarily for internal use by Edit mode, and helps to manage the behavior associated with exiting Edit mode via Save or Cancel. Its interface is not intended for general use. However, domainObject.hasCapability(editor) is a useful way of determining whether or not we are looking at an object in Edit mode.

Mutation Capability

The mutation capability provides a means by which the contents of a domain object's model can be modified. This capability is provided by the platform for all domain objects, and has the following interface:

Changes to domain object models should only be made via the mutation capability; other platform behavior is likely to break (either by exhibiting undesired behavior, or failing to exhibit desired behavior) if models are modified by other means.

Mutator Function

The mutator argument above is a function which will receive a cloned copy of the domain object's model as a single argument. It may return:

Persistence Capability

The persistence capability provides a mean for interacting with the underlying persistence service which stores this domain object's model. It has the following interface:

Relationship Capability

The relationship capability provides a means for accessing other domain objects with which this domain object has some typed relationship. It has the following interface:

The platform implementation of the relationship capability is present for domain objects which has a relationships property in their model, whose value is an object containing key-value pairs, where keys are strings identifying relationship types, and values are arrays of domain object identifiers.

Status Capability

The status capability provides a way to flag domain objects as possessing certain states, represented as simple strings. These states, in turn, are reflected on mct-representation elements as classes (prefixed with s-status-.) The status capability has the following interface:

Plug-ins may add and/or recognize arbitrary status flags. Flags defined and/or supported by the platform are:

Status CSS Class Meaning
editing s-status-editing Domain object is being edited.
pending s-status-pending Domain object is partially loaded.

Telemetry Capability

The telemetry capability provides a means for accessing telemetry data associated with a domain object. It has the following interface:

The platform implementation of the telemetry capability is present for domain objects which has a telemetry property in their model and/or type definition; this object will serve as a template for telemetry requests made using this object, and will also be returned by getMetadata() above.

Type Capability

The type capability exposes information about the domain object's type. It has the same interface as Type; see Core API.

View Capability

The view capability exposes views which are applicable to a given domain object. It has the following interface:

Actions

Actions are reusable processes/behaviors performed by users within the system, typically upon domain objects.

Action Categories

The platform understands the following action categories (specifiable as the category parameter of an action's extension definition.)

Platform Actions

The platform defines certain actions which can be utilized by way of a domain object's action capability. Unless otherwise specified, these act upon (and modify) the object described by the domainObject property of the action's context.

Policies

Policies are consulted to determine when certain behavior in Open MCT is allowed. Policy questions are assigned to certain categories, which broadly describe the type of decision being made; within each category, policies have a candidate (the thing which may or may not be allowed) and, optionally, a context (describing, generally, the context in which the decision is occurring.)

The types of objects passed for 'candidate' and 'context' vary by category; these types are documented below.

Policy Categories

The platform understands the following policy categories (specifiable as the category parameter of an policy's extension definition.)

Build-Test-Deploy

Open MCT is designed to support a broad variety of build and deployment options. The sources can be deployed in the same directory structure used during development. A few utilities are included to support development processes.

Command-line Build

Open MCT is built using npm and gulp.

To install build dependencies (only needs to be run once):

npm install

To build:

npm run prepare

This will compile and minify JavaScript sources, as well as copy over assets. The contents of the dist folder will contain a runnable Open MCT instance (e.g. by starting an HTTP server in that directory), including:

Additional gulp tasks are defined in the gulpfile.

Note that an internet connection is required to run this build, in order to download build dependencies.

Test Suite

Open MCT uses Jasmine 1.3 and Karma for automated testing.

The test suite is configured to load any scripts ending with Spec.js found in the src hierarchy. Full configuration details are found in karma.conf.js. By convention, unit test scripts should be located alongside the units that they test; for example, src/foo/Bar.js would be tested by src/foo/BarSpec.js. (For legacy reasons, some existing tests may be located in separate test folders near the units they test, but the naming convention is otherwise the same.)

Tests are written as AMD modules which depend (at minimum) upon the unit under test. For example, src/foo/BarSpec.js could look like:

/*global define,Promise,describe,it,expect,beforeEach*/

define(
    ["./Bar"],
    function (Bar) {
        "use strict";

        describe("Bar", function () {
            it("does something", function () {
                var bar = new Bar();
                expect(controller.baz()).toEqual("foo");
            });
        });
    }
);

Code Coverage

In addition to running tests, the test runner will also capture code coverage information using Blanket.JS and display this at the bottom of the screen. Currently, only statement coverage is displayed.

Deployment

Open MCT is built to be flexible in terms of the deployment strategies it supports. In order to run in the browser, Open MCT needs:

  1. HTTP access to sources/resources for the framework, platform, and all active bundles.
  2. Access to any external services utilized by active bundles. (This means that external services need to support HTTP or some other web-accessible interface, like WebSockets.)

Any HTTP server capable of serving flat files is sufficient for the first point. The command-line build also packages Open MCT into a .war file for easier deployment on containers such as Apache Tomcat.

The second point may be less flexible, as it depends upon the specific services to be utilized by Open MCT. Because of this, it is often the set of external services (and the manner in which they are exposed) that determine how to deploy Open MCT.

One important constraint to consider in this context is the browser's same origin policy. If external services are not on the same apparent host and port as the client (from the perspective of the browser) then access may be disallowed. There are two workarounds if this occurs:

Examples of deployment strategies (and the conditions under which they make the most sense) include:

Another important consideration is authentication. By design, Open MCT does not handle user authentication. Instead, this should typically be treated as a deployment-time concern, where authentication is handled by the HTTP server which provides Open MCT, or an external access management system.

Configuration

In most of the deployment options above, some level of configuration is likely to be needed or desirable to make sure that bundles can reach the external services they need to reach. Most commonly this means providing the path or URL to an external service.

Configurable parameters within Open MCT are specified via constants (literally, as extensions of the constants category) and accessed via dependency injection by the scripts which need them. Reasonable defaults for these constants are provided in the bundle where they are used. Plugins are encouraged to follow the same pattern.

Constants may be specified in any bundle; if multiple constants are specified with the same key the highest-priority one will be used. This allows default values to be overridden by specifying constants with higher priority.

This permits at least three configuration approaches:

Configuration Constants

The following constants have global significance:

The following configuration constants are recognized by Open MCT bundles: