diff --git a/API.md b/API.md index b51d9038a6..619c1c6787 100644 --- a/API.md +++ b/API.md @@ -352,6 +352,59 @@ request object with a start and end time is included below: } ``` + +### Telemetry Formats + +Telemetry format objects define how to interpret and display telemetry data. +They have a simple structure: + +* `key`: A `string` that uniquely identifies this formatter. +* `format`: A `function` that takes a raw telemetry value, and returns a human-readable +`string` representation of that value. It has one required argument, and three +optional arguments that provide context and can be used for returning scaled +representations of a value. An example of this is representing time values in a +scale such as the time conductor scale. There are multiple ways of representing +a point in time, and by providing a minimum scale value, maximum scale value, +and a count, it's possible to provide more useful representations of time given +the provided limitations. + * `value`: The raw telemetry value in its native type. + * `minValue`: An __optional__ argument specifying the minimum displayed value. + * `maxValue`: An __optional__ argument specifying the maximum displayed value. + * `count`: An __optional__ argument specifying the number of displayed values. +* `parse`: A `function` that takes a `string` representation of a telemetry value, +and returns the value in its native type. It accepts one argument: + * `text`: A `string` representation of a telemetry value. +* `validate`: A `function` that takes a `string` representation of a telemetry +value, and returns a `boolean` value indicating whether the provided string can be +parsed. + +#### Registering Formats + +Formats are registered with the Telemetry API using the `addFormat` function. eg. + +``` javascript +openmct.telemetry.addFormat({ + key: 'number-to-string', + format: function (number) { + return number + ''; + }, + parse: function (text) { + return Number(text); + }, + validate: function (text) { + return !isNaN(text); + } +}); +``` + +#### Examples of Formats in Use +* The [NumberFormat](https://github.com/nasa/openmct/blob/time-api-redo/platform/features/conductor/core/src/ui/NumberFormat.js) +provides an example of a simple format available by default +in OpenMCT. +* The [UTCTimeFormat](https://github.com/nasa/openmct/blob/master/src/plugins/utcTimeSystem/UTCTimeFormat.js) +is a more complex implementation of a format that uses the optional context +arguments in `format` to provide scale-appropriate values. + ### Telemetry Data Telemetry data is provided to Open MCT by _[Telemetry Providers](#telemetry-providers)_ @@ -390,10 +443,390 @@ openmct.telemetry.addProvider({ }) ``` +## Time API +Open MCT provides API for managing the temporal state of the application. Central +to this is the concept of "time bounds". Views in Open MCT will typically show +telemetry data for some prescribed date range, and the Time API provides a way +to centrally manage these bounds. + +The Time API exposes a number of methods for querying and setting the temporal +state of the application, and emits events to inform listeners when the state changes. + +Because the data displayed tends to be time domain data, Open MCT must always +have at least one time system installed and activated. When you download Open MCT, +it will be pre-configured to use the UTC time system, which is installed and +activated, along with other default plugins, in `index.html`. Installing and +activating a time system is simple, and is covered +[in the next section](#defining-and-registering-time-systems). + +### Time Systems and Bounds +#### Defining and Registering Time Systems +The time bounds of an Open MCT application are defined as numbers, and a Time +System gives meaning and context to these numbers so that they can be correctly +interpreted. Time Systems are javscript objects that provide some information +about the current time reference frame. An example of defining and registering +a new time system is given below: + +``` javascript +openmct.time.addTimeSystem({ + key: 'utc', + name: 'UTC Time', + cssClass = 'icon-clock', + timeFormat = 'utc', + durationFormat = 'duration', + isUTCBased = true +}); +``` + +The example above defines a new utc based time system. In fact, this time system +is configured and activated by default from `index.html` in the default +installation of Open MCT if you download the source from GitHub. Some details of +each of the required properties is provided below. + +* `key`: A `string` that uniquely identifies this time system. +* `name`: A `string` providing a brief human readable label. If the [Time Conductor](#the-time-conductor) +plugin is enabled, this name will identify the time system in a dropdown menu. +* `cssClass`: A class name `string` that will be applied to the time system when +it appears in the UI. This will be used to represent the time system with an icon. +There are a number of built-in icon classes [available in Open MCT](https://github.com/nasa/openmct/blob/master/platform/commonUI/general/res/sass/_glyphs.scss), +or a custom class can be used here. +* `timeFormat`: A `string` corresponding to the key of a registered +[telemetry time format](#telemetry-formats). The format will be used for +displaying discrete timestamps from telemetry streams when this time system is +activated. If the [UTCTimeSystem](#included-plugins) is enabled, then the `utc` +format can be used if this is a utc-based time system +* `durationFormat`: A `string` corresponding to the key of a registered +[telemetry time format](#telemetry-formats). The format will be used for +displaying time ranges, for example `00:15:00` might be used to represent a time +period of fifteen minutes. These are used by the Time Conductor plugin to specify +relative time offsets. If the [UTCTimeSystem](#included-plugins) is enabled, +then the `duration` format can be used if this is a utc-based time system +* `isUTCBased`: A `boolean` that defines whether this time system represents +numbers in UTC terrestrial time. + +#### Getting and Setting the Active Time System + +Once registered, a time system can be activated using a key, or an instance of +the time system itself. + +```javascript +openmct.time.timeSystem('utc'); +``` + +A time system can be immediately activated upon registration: + +```javascript +var utcTimeSystem = { + key: 'utc', + name: 'UTC Time', + cssClass = 'icon-clock', + timeFormat = 'utc', + durationFormat = 'duration', + isUTCBased = true +}; +openmct.time.addTimeSystem(utcTimeSystem); +openmct.time.timeSystem(utcTimeSystem); +``` + +Setting the active time system will trigger a [time system event](#time-events). + +### Time Bounds + +The TimeAPI provides a getter/setter for querying and setting time bounds. Time +bounds are simply an object with a `start` and an end `end` attribute. + +* `start`: A `number` representing a moment in time in the active [Time System](#defining-and-registering-time-systems). +This will be used as the beginning of the time period displayed by time-responsive +telemetry views. +* `end`: A `number` representing a moment in time in the active [Time System](#defining-and-registering-time-systems). +This will be used as the end of the time period displayed by time-responsive +telemetry views. + +If invoked with bounds, it will set the new time bounds system-wide. If invoked +without any parameters, it will return the current application-wide time bounds. + +``` javascript +const ONE_HOUR = 60 * 60 * 1000; +let now = Date.now(); +openmct.time.bounds({start: now - ONE_HOUR, now); +``` + +To respond to bounds change events, simply register a callback against the `bounds` +event. For more information on the bounds event, please see the section on [Time Events](#time-events). + +## Clocks + +The Time API can be set to follow a clock source which will cause the bounds +to be updated automatically whenever the clock source "ticks". A clock is simply +an object that supports registration of listeners and periodically invokes its +listeners with a number. Open MCT supports registration of new clock sources that +tick on almost anything. A tick occurs when the clock invokes callback functions +registered by its listeners with a new time value. + +An example of a clock source is the [LocalClock](https://github.com/nasa/openmct/blob/master/src/plugins/utcTimeSystem/LocalClock.js) +which emits the current time in UTC every 100ms. Clocks can tick on anything. For +example, a clock could be defined to provide the timestamp of any new data +received via a telemetry subscription. This would have the effect of advancing +the bounds of views automatically whenever data is received. A clock could also +be defined to tick on some remote timing source. + +The values provided by clocks are simple `number`s, which are interpreted in the +context of the active [Time System](#defining-and-registering-time-systems). + +### Defining and registering clocks +A clock is an object that defines certain required metadata and functions: + +* `key`: A `string` uniquely identifying this clock. This can be used later to +reference the clock in places such as the [Time Conductor configuration](#time-conductor-configuration) +* `cssClass`: A `string` identifying a CSS class to apply to this clock when it's +displayed in the UI. This will be used to represent the time system with an icon. +There are a number of built-in icon classes [available in Open MCT](https://github.com/nasa/openmct/blob/master/platform/commonUI/general/res/sass/_glyphs.scss), +or a custom class can be used here. +* `name`: A `string` providing a human-readable identifier for the clock source. +This will be displayed in the clock selector menu in the Time Conductor UI +component, if active. +* `description`: An __optional__ `string` providing a longer description of the +clock. The description will be visible in the clock selection menu in the Time +Conductor plugin. +* `on`: A `function` supporting registration of a new callback that will be +invoked when the clock next ticks. It will be invoked with two arguments: + * `eventName`: A `string` specifying the event to listen on. For now, clocks + support one event - `tick`. + * `callback`: A `function` that will be invoked when this clock ticks. The + function must be invoked with one parameter - a `number` representing a valid + time in the current time system. +* `off`: A `function` that allows deregistration of a tick listener. It accepts +the same arguments as `on`. +* `currentValue`: A `function` that returns a `number` representing a point in +time in the active time system. It should be the last value provided by a tick, +or some default value if no ticking has yet occurred. + +A new clock can be registered using the `addClock` function exposed by the Time +API: + +```javascript +var someClock = { + key: 'someClock', + cssClass: 'icon-clock', + name: 'Some clock', + description: "Presumably does something useful", + on: function (event, callback) { + // Some function that registers listeners, and updates them on a tick + }, + off: function (event, callback) { + // Some function that unregisters listeners. + }, + currentValue: function () { + // A function that returns the last ticked value for the clock + } +} + +openmct.time.addClock(someClock); +``` + +An example clock implementation is provided in the form of the [LocalClock](https://github.com/nasa/openmct/blob/master/src/plugins/utcTimeSystem/LocalClock.js) + +#### Getting and setting active clock + +Once registered a clock can be activated by calling the `clock` function on the +Time API passing in the key or instance of a registered clock. Only one clock +may be active at once, so activating a clock will deactivate any currently +active clock. Setting the clock will also trigger a ['clock' event](#time-events). + +``` +openmct.time.clock(someClock); +``` + +Upon being activated, a clock's `on` function will be immediately called to subscribe +to `tick` events. + +The currently active clock (if any) can be retrieved by calling the same +function without any arguments. + +#### Stopping an active clock + +The `stopClock` method can be used to stop an active clock, and to clear it. It +will stop the clock from ticking, and set the active clock to `undefined`. + +``` javascript +openmct.time.stopClock(); +``` + +#### Clock Offsets + +When a clock is active, the time bounds of the application will be updated +automatically each time the clock "ticks". The bounds are calculated based on +the current value provided by the active clock (via its `tick` event, or its +`currentValue()` method). + +Unlike bounds, which represent absolute time values, clock offsets represent +relative time spans. Offsets are defined as an object with two properties: + +* `start`: A `number` that must be < 0 and which is used to calculate the start +bounds on each clock tick. The start offset will be calculated relative to the +value provided by a clock's tick callback, or its `currentValue()` function. +* `end`: A `number` that must be >=0 and which is used to calculate the end +bounds on each clock tick. + +The `clockOffsets` function can be used to get or set clock offsets. For example, +to show the last fifteen minutes in a ms-based time system: + +```javascript +var FIFTEEN_MINUTES = 15 * 60 * 1000; + +openmct.time.clockOffsets({ + start: -FIFTEEN_MINUTES, + end: 0 +}) +``` + +__Note:__ Setting the clock offsets will trigger an immediate bounds change, as +new bounds will be calculated based on the `currentValue()` of the active clock. +Clock offsets are only relevant when a clock source is active. + +## Time Events +The time API supports the registration of listeners that will be invoked when the +application's temporal state changes. Events listeners can be registered using +the `on` function. They can be deregistered using the `off` function. The arguments +accepted by the `on` and `off` functions are: + +* `event`: A `string` naming the event to subscribe to. Event names correspond to +the property of the Time API you're interested in. A [full list of time events](#list-of-time-events) +is provided later. + +As an example, the code to listen to bounds change events looks like: + +``` javascript +openmct.time.on('bounds', function callback (newBounds, tick) { + // Do something with new bounds +}); +``` + +#### List of Time Events +The events supported by the Time API are: + +* `bounds`: Listen for changes to current bounds. The callback will be invoked +with two arguments: + * `bounds`: A [bounds](#getting-and-setting-bounds) bounds object representing + a new time period bound by the specified start and send times. + * `tick`: A `boolean` indicating whether or not this bounds change is due to a + "tick" from a [clock source](#clocks). This information can be useful when + determining a strategy for fetching telemetry data in response to a bounds + change event. For example, if the bounds change was automatic, and is due + to a tick then it's unlikely that you would need to perform a historical + data query. It should be sufficient to just show any new telemetry received + via subscription since the last tick, and optionally to discard any older + data that now falls outside of the currently set bounds. If `tick` is false, + then the bounds change was not due to an automatic tick, and a query for + historical data may be necessary, depending on your data caching strategy, + and how significantly the start bound has changed. +* `timeSystem`: Listen for changes to the active [time system](#defining-and-registering-time-systems). +The callback will be invoked with a single argument - the newly active time system. + * `timeSystem`: The newly active [time system](#defining-and-registering-time-systems) object. +* `clock`: Listen for changes to the active clock. When invoked, the callback +will be provided with the new clock. + * `clock`: The newly active [clock](#clocks), or `undefined` if an active clock + has been deactivated. +* `clockOffsets`: Listen for changes to active clock offsets. When invoked the +callback will be provided with the new clock offsets. + * `clockOffsets`: A [clock offsets](#clock-offsets) object. + + +## The Time Conductor +The Time Conductor provides a user interface for managing time bounds in Open MCT. +It allows a user to select from configured time systems and clocks, and to set bounds +and clock offsets. + +If activated, the time conductor must be provided with configuration options, +detailed below. + +#### Time Conductor Configuration +The time conductor is configured by specifying the options that will be +available to the user from the menus in the time conductor. These will determine +the clocks available from the conductor, the time systems available for each +clock, and some default bounds and clock offsets for each combination of clock +and time system. By default, the conductor always supports a `fixed` mode where +no clock is active. To specify configuration for fixed mode, simply leave out a +`clock` attribute in the configuration entry object. + +Configuration is provided as an `array` of menu options. Each entry of the +array is an object with some properties specifying configuration. The configuration +options specified are slightly different depending on whether or not it is for +an active clock mode. + +__Configuration for Fixed Time Mode (no active clock)__ + +* `timeSystem`: A `string`, the key for the time system that this configuration +relates to. +* `bounds`: A [`Time Bounds`](#time-bounds) object. These bounds will be applied +when the user selects the time system specified in the previous `timeSystem` +property. +* `zoomOutLimit`: An __optional__ `number` specifying the longest period of time +that can be represented by the conductor when zooming. If a `zoomOutLimit` is +provided, then a `zoomInLimit` must also be provided. If provided, the zoom +slider will automatically become available in the Time Conductor UI. +* `zoomInLimit`: An __optional__ `number` specifying the shortest period of time +that can be represented by the conductor when zooming. If a `zoomInLimit` is +provided, then a `zoomOutLimit` must also be provided. If provided, the zoom +slider will automatically become available in the Time Conductor UI. + +__Configuration for Active Clock__ + +* `clock`: A `string`, the `key` of the clock that this configuration applies to. +* `timeSystem`: A `string`, the key for the time system that this configuration +relates to. Separate configuration must be provided for each time system that you +wish to be available to users when they select the specified clock. +* `clockOffsets`: A [`clockOffsets`](#clock-offsets) object that will be +automatically applied when the combination of clock and time system specified in +this configuration is selected from the UI. + +#### Example conductor configuration +An example time conductor configuration is provided below. It sets up some +default options for the [UTCTimeSystem](https://github.com/nasa/openmct/blob/master/src/plugins/utcTimeSystem/UTCTimeSystem.js) +and [LocalTimeSystem](https://github.com/nasa/openmct/blob/master/src/plugins/localTimeSystem/LocalTimeSystem.js), +in both fixed mode, and for the [LocalClock](https://github.com/nasa/openmct/blob/master/src/plugins/utcTimeSystem/LocalClock.js) +source. In this configutation, the local clock supports both the UTCTimeSystem +and LocalTimeSystem. Configuration for fixed bounds mode is specified by omitting +a clock key. + +``` javascript +const ONE_YEAR = 365 * 24 * 60 * 60 * 1000; +const ONE_MINUTE = 60 * 1000; + +openmct.install(openmct.plugins.Conductor({ + menuOptions: [ + // 'Fixed' bounds mode configuation for the UTCTimeSystem + { + timeSystem: 'utc', + bounds: {start: Date.now() - 30 * ONE_MINUTE, end: Date.now()}, + zoomOutLimit: ONE_YEAR, + zoomInLimit: ONE_MINUTE + }, + // Configuration for the LocalClock in the UTC time system + { + clock: 'local', + timeSystem: 'utc', + clockOffsets: {start: - 30 * ONE_MINUTE, end: 0}, + zoomOutLimit: ONE_YEAR, + zoomInLimit: ONE_MINUTE + }, + //Configuration for the LocaLClock in the Local time system + { + clock: 'local', + timeSystem: 'local', + clockOffsets: {start: - 15 * ONE_MINUTE, end: 0} + } + ] +})); +``` + ## Included Plugins Open MCT is packaged along with a few general-purpose plugins: +* `openmct.plugins.Conductor` provides a user interface for working with time +within the application. If activated, configuration must be provided. This is +detailed in the section on [Time Conductor Configuration](#time-conductor-configuration). * `openmct.plugins.CouchDB` is an adapter for using CouchDB for persistence of user-created objects. This is a constructor that takes the URL for the CouchDB database as a parameter, e.g. diff --git a/example/localTimeSystem/src/LocalTimeSystem.js b/example/localTimeSystem/src/LocalTimeSystem.js deleted file mode 100644 index ee309d09b0..0000000000 --- a/example/localTimeSystem/src/LocalTimeSystem.js +++ /dev/null @@ -1,79 +0,0 @@ -/***************************************************************************** - * Open MCT Web, Copyright (c) 2014-2015, 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 - * "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([ - '../../../platform/features/conductor/core/src/timeSystems/TimeSystem', - '../../../platform/features/conductor/core/src/timeSystems/LocalClock', - './LADTickSource' -], function (TimeSystem, LocalClock, LADTickSource) { - var THIRTY_MINUTES = 30 * 60 * 1000, - DEFAULT_PERIOD = 1000; - - /** - * This time system supports UTC dates and provides a ticking clock source. - * @implements TimeSystem - * @constructor - */ - function LocalTimeSystem ($timeout) { - TimeSystem.call(this); - - /** - * Some metadata, which will be used to identify the time system in - * the UI - * @type {{key: string, name: string, glyph: string}} - */ - this.metadata = { - 'key': 'local', - 'name': 'Local', - 'glyph': '\u0043' - }; - - this.fmts = ['local-format']; - this.sources = [new LocalClock($timeout, DEFAULT_PERIOD), new LADTickSource($timeout, DEFAULT_PERIOD)]; - } - - LocalTimeSystem.prototype = Object.create(TimeSystem.prototype); - - LocalTimeSystem.prototype.formats = function () { - return this.fmts; - }; - - LocalTimeSystem.prototype.deltaFormat = function () { - return 'duration'; - }; - - LocalTimeSystem.prototype.tickSources = function () { - return this.sources; - }; - - LocalTimeSystem.prototype.defaults = function (key) { - var now = Math.ceil(Date.now() / 1000) * 1000; - return { - key: 'local-default', - name: 'Local 12 hour time system defaults', - deltas: {start: THIRTY_MINUTES, end: 0}, - bounds: {start: now - THIRTY_MINUTES, end: now} - }; - }; - - return LocalTimeSystem; -}); diff --git a/example/msl/src/MSLDataDictionary.js b/example/msl/src/MSLDataDictionary.js index 9e04560d45..e6b6a08415 100644 --- a/example/msl/src/MSLDataDictionary.js +++ b/example/msl/src/MSLDataDictionary.js @@ -44,31 +44,31 @@ define( { "name": "Min. Air Temperature", "identifier": "min_temp", - "units": "degrees", + "units": "Degrees (C)", "type": "float" }, { "name": "Max. Air Temperature", "identifier": "max_temp", - "units": "degrees", + "units": "Degrees (C)", "type": "float" }, { "name": "Atmospheric Pressure", "identifier": "pressure", - "units": "pascals", + "units": "Millibars", "type": "float" }, { "name": "Min. Ground Temperature", "identifier": "min_gts_temp", - "units": "degrees", + "units": "Degrees (C)", "type": "float" }, { "name": "Max. Ground Temperature", "identifier": "max_gts_temp", - "units": "degrees", + "units": "Degrees (C)", "type": "float" } ] @@ -76,4 +76,4 @@ define( ] }; } -); +); \ No newline at end of file diff --git a/example/msl/src/RemsTelemetryServerAdapter.js b/example/msl/src/RemsTelemetryServerAdapter.js index ea6a05ac27..6fd05c2289 100644 --- a/example/msl/src/RemsTelemetryServerAdapter.js +++ b/example/msl/src/RemsTelemetryServerAdapter.js @@ -48,6 +48,13 @@ define( this.$http = $http; this.$log = $log; this.promise = undefined; + + this.dataTransforms = { + //Convert from pascals to millibars + 'pressure': function pascalsToMillibars(pascals) { + return pascals / 100; + } + }; } /** @@ -65,6 +72,8 @@ define( var self = this, id = request.key; + var dataTransforms = this.dataTransforms; + function processResponse(response){ var data = []; /* @@ -75,13 +84,14 @@ define( * Check that valid data exists */ if (!isNaN(solData[id])) { + var dataTransform = dataTransforms[id]; /* * Append each data point to the array of values * for this data point property (min. temp, etc). */ data.unshift({ date: Date.parse(solData[TERRESTRIAL_DATE]), - value: solData[id] + value: dataTransform ? dataTransform(solData[id]) : solData[id] }); } }); diff --git a/example/styleguide/bundle.js b/example/styleguide/bundle.js new file mode 100644 index 0000000000..43fa475a24 --- /dev/null +++ b/example/styleguide/bundle.js @@ -0,0 +1,98 @@ +define([ + "./src/ExampleStyleGuideModelProvider", + "./src/MCTExample", + 'legacyRegistry' +], function ( + ExampleStyleGuideModelProvider, + MCTExample, + legacyRegistry +) { + legacyRegistry.register("example/styleguide", { + "name": "Open MCT Style Guide", + "description": "Examples and documentation illustrating UI styles in use in Open MCT.", + "extensions": + { + "types": [ + { "key": "styleguide.intro", "name": "Introduction", "cssClass": "icon-page", "description": "Introduction and overview to the style guide" }, + { "key": "styleguide.standards", "name": "Standards", "cssClass": "icon-page", "description": "" }, + { "key": "styleguide.colors", "name": "Colors", "cssClass": "icon-page", "description": "" }, + { "key": "styleguide.glyphs", "name": "Glyphs", "cssClass": "icon-page", "description": "Glyphs overview" }, + { "key": "styleguide.controls", "name": "Controls", "cssClass": "icon-page", "description": "Buttons, selects, HTML controls" }, + { "key": "styleguide.input", "name": "Text Inputs", "cssClass": "icon-page", "description": "Various text inputs" }, + { "key": "styleguide.menus", "name": "Menus", "cssClass": "icon-page", "description": "Context menus, dropdowns" } + ], + "views": [ + { "key": "styleguide.intro", "type": "styleguide.intro", "templateUrl": "templates/intro.html", "editable": false }, + { "key": "styleguide.standards", "type": "styleguide.standards", "templateUrl": "templates/standards.html", "editable": false }, + { "key": "styleguide.colors", "type": "styleguide.colors", "templateUrl": "templates/colors.html", "editable": false }, + { "key": "styleguide.glyphs", "type": "styleguide.glyphs", "templateUrl": "templates/glyphs.html", "editable": false }, + { "key": "styleguide.controls", "type": "styleguide.controls", "templateUrl": "templates/controls.html", "editable": false }, + { "key": "styleguide.input", "type": "styleguide.input", "templateUrl": "templates/input.html", "editable": false }, + { "key": "styleguide.menus", "type": "styleguide.menus", "templateUrl": "templates/menus.html", "editable": false } + ], + "roots": [ + { + "id": "styleguide:home" + } + ], + "models": [ + { + "id": "styleguide:home", + "priority" : "preferred", + "model": { + "type": "folder", + "name": "Style Guide Home", + "location": "ROOT", + "composition": [ + "intro", + "standards", + "colors", + "glyphs", + "styleguide:ui-elements" + ] + } + }, + { + "id": "styleguide:ui-elements", + "priority" : "preferred", + "model": { + "type": "folder", + "name": "UI Elements", + "location": "styleguide:home", + "composition": [ + "controls", + "input", + "menus" + ] + } + } + ], + "directives": [ + { + "key": "mctExample", + "implementation": MCTExample + } + ], + "components": [ + { + "provides": "modelService", + "type": "provider", + "implementation": ExampleStyleGuideModelProvider, + "depends": [ + "$q" + ] + } + ], + "stylesheets": [ + { + "stylesheetUrl": "css/style-guide-espresso.css", + "theme": "espresso" + }, + { + "stylesheetUrl": "css/style-guide-snow.css", + "theme": "snow" + } + ] + } + }); +}); diff --git a/example/styleguide/res/images/diagram-containment.svg b/example/styleguide/res/images/diagram-containment.svg new file mode 100644 index 0000000000..a718ae33ac --- /dev/null +++ b/example/styleguide/res/images/diagram-containment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/example/styleguide/res/images/diagram-objects.svg b/example/styleguide/res/images/diagram-objects.svg new file mode 100644 index 0000000000..c457666dcf --- /dev/null +++ b/example/styleguide/res/images/diagram-objects.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/example/styleguide/res/images/diagram-views.svg b/example/styleguide/res/images/diagram-views.svg new file mode 100644 index 0000000000..c62a2fc3a7 --- /dev/null +++ b/example/styleguide/res/images/diagram-views.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/example/styleguide/res/sass/_style-guide-base.scss b/example/styleguide/res/sass/_style-guide-base.scss new file mode 100644 index 0000000000..c6a9c25b88 --- /dev/null +++ b/example/styleguide/res/sass/_style-guide-base.scss @@ -0,0 +1,199 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ +.l-style-guide { + font-size: 0.9em; + text-align: justify; + margin: auto 10%; + + a.link { + color: $colorKey; + } + + h1, h2 { + color: pullForward($colorBodyFg, 20%); + } + + h2 { + font-size: 1.25em; + } + + h3 { + font-size: 0.9em; + margin: $interiorMargin 0; + &:not(:first-child) { + margin-top: $interiorMarginLg * 2; + } + text-transform: uppercase; + } + + .w-markup { + //Wrap markup example "pre" element + background-color: $colorCode; + border-radius: $interiorMargin; + display: block; + padding: $interiorMarginLg $interiorMarginLg; + position: relative; + } + + code, + pre { + font-size: 0.8rem; + } + + code { + background-color: $colorCode; + border-radius: $controlCr; + display: inline-block; + padding: 1px $interiorMargin; + } + + pre { + display: block; + margin: 0; + max-height: 300px; + overflow: auto; + padding-bottom: $interiorMarginLg; + white-space: pre; + } + + table, ul { + margin-bottom: $interiorMarginLg; + width: auto; + } + + .themed { + display: none; // Each themed styleguide file will set this to block. + } + + .doc-title { + color: rgba(#fff, 0.3); + text-transform: uppercase; + } + + .l-section { + border-top: 1px solid rgba(#999, 0.3); + margin-top: 2em; + padding-top: 1em; + + .cols { + @include display(flex); + @include flex-direction(row); + + .col { + @include flex(1 1 auto); + &:not(:last-child) { + $v: $interiorMargin * 4; + border-right: 1px solid $colorInteriorBorder; + margin-right: $v; + padding-right: $v; + } + min-width: 300px; + img { + width: 100%; + } + } + + &.cols1-1 { + // 2 cols, equal width + .col { + width: 50%; + } + } + + &.cols1-2 { + // 3 cols, first is 1/3 of the width + .col:first-child { + width: 33%; + } + .col:last-child { + width: 66%; + } + } + + &.cols2-1 { + // 3 cols, first is 2/3 of the width + .col:first-child { + width: 66%; + } + .col:last-child { + width: 33%; + } + } + } + } + + // Example grid of glyphs + .items-holder.grid { + .item.glyph-item, + .item.swatch-item { + margin-bottom: 50px; + margin-right: 10px; + position: relative; + text-align: left; + .glyph { + color: $colorGlyphExample; + font-size: 5em; + margin: $interiorMarginLg 0; + text-align: center; + } + + table.details td { + font-size: inherit; + &.label { + color: pushBack($colorBodyFg, 10%); + text-transform: uppercase; + white-space: nowrap; + } + } + } + + .item.glyph-item { + width: 225px; + height: 200px; + } + + .item.swatch-item { + $h: 150px; + $d: 75px; + width: 200px; + height: $h; + .glyph { + text-shadow: 0px 1px 10px rgba(black, 0.3); + } + + .h-swatch { + position: relative; + height: $d + $interiorMarginLg; + } + + .swatch { + height: $d; width: $d; + border: 1px solid $colorInteriorBorder; + border-radius: 15%; + position: absolute; + left: 50%; + @include transform(translateX(-50%)); + } + } + } +} + diff --git a/example/styleguide/res/sass/style-guide-espresso.scss b/example/styleguide/res/sass/style-guide-espresso.scss new file mode 100644 index 0000000000..a3b8dcb9ac --- /dev/null +++ b/example/styleguide/res/sass/style-guide-espresso.scss @@ -0,0 +1,37 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2015, 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. + *****************************************************************************/ +@import "bourbon"; +@import "../../../../platform/commonUI/general/res/sass/constants"; +@import "../../../../platform/commonUI/general/res/sass/mixins"; +@import "../../../../platform/commonUI/themes/espresso/res/sass/constants"; +@import "../../../../platform/commonUI/themes/espresso/res/sass/mixins"; +@import "../../../../platform/commonUI/general/res/sass/glyphs"; +@import "../../../../platform/commonUI/general/res/sass/icons"; + +// Thematic constants +$colorCode: rgba(black, 0.2); +$colorGlyphExample: #fff; + +@import "style-guide-base"; + +div.themed.espresso { display: block; } +span.themed.espresso { display: inline; } diff --git a/example/styleguide/res/sass/style-guide-snow.scss b/example/styleguide/res/sass/style-guide-snow.scss new file mode 100644 index 0000000000..a48aec3756 --- /dev/null +++ b/example/styleguide/res/sass/style-guide-snow.scss @@ -0,0 +1,37 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2015, 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. + *****************************************************************************/ +@import "bourbon"; +@import "../../../../platform/commonUI/general/res/sass/constants"; +@import "../../../../platform/commonUI/general/res/sass/mixins"; +@import "../../../../platform/commonUI/themes/snow/res/sass/constants"; +@import "../../../../platform/commonUI/themes/snow/res/sass/mixins"; +@import "../../../../platform/commonUI/general/res/sass/glyphs"; +@import "../../../../platform/commonUI/general/res/sass/icons"; + +// Thematic constants +$colorCode: rgba(black, 0.1); +$colorGlyphExample: darken($colorBodyBg, 30%); + +@import "style-guide-base"; + +div.themed.snow { display: block; } +span.themed.snow { display: inline; } \ No newline at end of file diff --git a/example/styleguide/res/templates/colors.html b/example/styleguide/res/templates/colors.html new file mode 100644 index 0000000000..47631b0cff --- /dev/null +++ b/example/styleguide/res/templates/colors.html @@ -0,0 +1,84 @@ + +
+ + + +Open MCT Style Guide
+In mission operations, color is used to convey meaning. Alerts, warnings and status conditions are by convention communicated with colors in the green, yellow and red families. Colors must also be reserved for use in plots. As a result, Open MCT uses color selectively and sparingly. Follow these guidelines:
+{{ colorSet.description }}
+| Name | {{color.name}} |
| SASS | {{color.constant}} |
| Value | + {{color.valEspresso}} + {{color.valSnow}} + |
Open MCT Style Guide
+Use a standard button in locations where there's sufficient room and you must make it clear that the element is an interactive button element. Buttons can be displayed with only an icon, only text, or with icon and text combined.
+Use an icon whenever possible to aid the user's recognition and recall. If both and icon and text are to be used, the text must be within a span with class .title-label.
Use button sets to connect buttons that have related purpose or functionality. Buttons in a set round the outer corners of only the first and last buttons, any other buttons in the middle simply get division spacers.
+To use, simply wrap two or more .s-button elements within .l-btn-set.
When a button is presented within another control it may be advantageous to avoid visual clutter by using an icon-only button. These type of controls present an icon without the "base" of standard buttons. Icon-only buttons should only be used in a context where they are clearly an interactive element and not an object-type identifier, and should not be used with text.
+Checkboxes use a combination of minimal additional markup with CSS to present a custom and common look-and-feel across platforms.
+The basic structure is a label with a checkbox-type input and an em element inside. The em is needed as the holder of the custom element; the input itself is hidden. Putting everything inside the label allows the label itself to act as a clickable element.
Radio buttons use the same technique as checkboxes above.
+Similar to checkboxes and radio buttons, selects use a combination of minimal additional markup with CSS to present a custom and common look-and-feel across platforms. The select element is wrapped by another element, such as a div, which acts as the main display element for the styling. The select provides the click and select functionality, while having all of its native look-and-feel suppressed.
Local controls are typically buttons and selects that provide local control to an individual element. Typically, these controls are hidden in order to not block data display until the user hovers their cursor over an element, when the controls are displayed using a transition fade. Mousing out of the element fades the controls from view.
+Open MCT Style Guide
+Symbolic glyphs are used extensively in Open MCT to call attention to interactive elements, identify objects, and aid in visual recall. Glyphs are made available in a custom symbols font, and have associated CSS classes for their usage. Using a font in this way (versus using images or sprites) has advantages in that each symbol is in effect a scalable vector that can be sized up or down as needed. Color can also quite easily be applied via CSS.
+New glyphs can be added if needed. Take care to observe the following guidelines: +
The easiest way to use a glyph is to include its CSS class in element. The CSS adds a psuedo :before HTML element to whatever element it's attached to that makes proper use of the symbols font.
Alternately, you can use the .ui-symbol class in an object that contains encoded HTML entities. This method is only recommended if you cannot use the aforementioned CSS class approach for some reason.
Glyphs suitable for denoting general user interface verbs and nouns.
+| Meaning | {{glyph.meaning}} |
| Class | .{{glyph.cssClass}} |
| CSS Content | \{{glyph.cssContent}} |
| HTML Entity | {{glyph.htmlEntity}} |
Glyphs created for use in various controls.
+| Meaning | {{glyph.meaning}} |
| Class | .{{glyph.cssClass}} |
| CSS Content | \{{glyph.cssContent}} |
| HTML Entity | {{glyph.htmlEntity}} |
These glyphs are reserved exclusively to denote types of objects in the application. Only use them if you are referring to a pre-existing object type.
+| Meaning | {{glyph.meaning}} |
| Class | .{{glyph.cssClass}} |
| CSS Content | \{{glyph.cssContent}} |
| HTML Entity | {{glyph.htmlEntity}} |
Open MCT Style Guide
+Text inputs and textareas have a consistent look-and-feel across the application. The input's placeholder attribute is styled to appear visually different from an entered value.
Use a text input where the user should enter relatively short text entries.
+A variety of size styles are available: .lg, .med and .sm. .lg text inputs dynamically scale their width to 100% of their container's width. Numeric inputs that benefit from right-alignment can be styled by adding .numeric.
Use a textarea where the user should enter relatively longer or multi-line text entries.
+By default, textareas are styled to expand to 100% of the width and height of their container; additionally there are three size styles available that control the height of the element: .lg, .med and .sm.
Open MCT Style Guide
+Open MCT is a robust, extensible telemetry monitoring and situational awareness system that provides a framework supporting fast and efficient multi-mission deployment. This guide will explore the major concepts and design elements of Open MCT. Its overall goal is to guide you in creating new features and plugins that seamlessly integrate with the base application.
+First and foremost, Open MCT uses a “object-oriented” approach: everything in the system is an object. Objects come in different types, and some objects can contain other objects of given types. This is similar to how the file management system of all modern computers works: a folder object can contain any other type of object, a presentation file can contain an image. This is conceptually the same in Open MCT.
+As you develop plugins for Open MCT, consider how a generalized component might be combined with others when designing to create a rich and powerful larger object, rather than adding a single monolithic, non-modular plugin. To solve a particular problem or allow a new feature in Open MCT, you may need to introduce more than just one new object type.
+In the same way that different types of files might be opened and edited by different applications, objects in Open MCT also have different types. For example, a Display Layout provides a way that other objects that display information can be combined and laid out in a canvas area to create a recallable display that suits the needs of the user that created it. A Telemetry Panel allows a user to collect together Telemetry Points and visualize them as a plot or a table.
+Object types provide a containment model that guides the user in their choices while creating a new object, and allows view normalization when flipping between different views. When a given object may only contain other objects of certain types, advantages emerge: the result of adding new objects is more predictable, more alternate views can be provided because the similarities between the contained objects is close, and we can provide more helpful and pointed guidance to the user because we know what types of objects they might be working with at a given time.
+The types of objects that a container can hold should be based on the purpose of the container and the views that it affords. For example, a Folder’s purpose is to allow a user to conceptually organize objects of all other types; a Folder must therefore be able to contain an object of any type.
+Views are simply different ways to view the content of a given object. For example, telemetry data could be viewed as a plot or a table. A clock can display its time in analog fashion or with digital numbers. In each view, all of the content is present; it’s just represented differently. When providing views for an object, all the content of the object should be present in each view.
+Open MCT Style Guide
+Context menus are used extensively in Open MCT. They are created dynamically upon a contextual click and positioned at the user's cursor position coincident with the element that invoked them. Context menus must use absolute position and utilize a z-index that places them above other in-page elements.
+See User Interface Standards for more details on z-indexing in Open MCT. Context menus should be destroyed if the user clicks outside the menu element.
+Dropdown menus are a dedicated, more discoverable context menu for a given object. Like context menus, dropdown menus are used extensively in Open MCT, and are most often associated with object header elements. They visually manifest as a downward pointing arrow associated with an element, and when clicked displays a context menu at that location. See guidelines above about context menus in regards to z-indexing and element lifecycle.
+Use a dropdown menu to encapsulate important the actions of an object in the object's header, or in a place that you'd use a context menu, but want to make the availability of the menu more apparent.
+Checkbox menus add checkbox options to each item of a dropdown menu. Use this to
+Use a dropdown menu to encapsulate important the actions of an object in the object's header, or in a place that you'd use a context menu, but want to make the availability of the menu more apparent.
+Use a palette to provide color choices. Similar to context menus and dropdowns, palettes should be dismissed when a choice is made within them, or if the user clicks outside one.
+Note that while this example uses static markup for illustrative purposes, don't do this - use a front-end framework with repeaters to build the color choices.
+Open MCT Style Guide
+Absolute positioning is used in Open MCT in the main envelope interface to handle layout and draggable pane splitters, for elements that must be dynamically created and positioned (like context menus) and for buttons that are placed over other elements, such as a plot's zoom/pan history and reset buttons. When using absolute positioning, follow these guidelines:
+| Type | Description | Z-index Range |
| Base interface items | Base level elements | 0 - 1 |
| Primary pane | Elements in the primary "view area" pane | 2 |
| Inspector pane, splitters | Elements in the Inspector, and splitters themselves | 3 |
| More base interface stuff | Base level elements | 4 - 9 |
| Treeview | Lefthand treeview elements | 30 - 39 |
| Help bubbles, rollover hints | Infobubbles, and similar | 50 - 59 |
| Context, button and dropdown menus | Context menus, button menus, etc. that must overlay other elements | 70 - 79 |
| Overlays | Modal overlay displays | 100 - 109 |
| Event messages | Alerts, event dialogs | 1000 |