Compare commits

...

8 Commits

Author SHA1 Message Date
fd309bc435 renamed offsets to deltas for consistency with internal API 2017-03-31 15:17:56 -07:00
1a0fe932fe [Conductor] Implemented UTCTimeSystem as new style time system 2017-03-09 18:52:33 +00:00
869323d41f [Conductor] Renamed options to configuration
Conflicts:
	src/plugins/plugins.js
2017-03-09 17:48:57 +00:00
e3cca0f789 [Conductor] Renaming and refactoring
Conflicts:
	index.html
	src/api/api.js
	src/plugins/conductor/TimeConductorService.js
2017-03-09 17:37:56 +00:00
d7e6402dc0 [Conductor] Added support for new style registration of formats tolegacy services 2017-03-09 17:08:32 +00:00
83eaec07af [Conductor] Added 'addFormat' function to telemetry API
Conflicts:
	src/api/telemetry/TelemetryAPI.js
2017-03-09 17:07:58 +00:00
505bdf5386 [Conductor] Added new methods to Time Conductor public API 2017-03-09 17:06:33 +00:00
59afbb9996 Added new methods to TimeConductor 2017-03-07 17:06:16 +00:00
11 changed files with 494 additions and 112 deletions

View File

@ -28,7 +28,13 @@
<script src="bower_components/requirejs/require.js">
</script>
<script>
require(['openmct'], function (openmct) {
require([
'openmct',
'src/plugins/conductor/plugin'
], function (
openmct,
ConductorService
) {
[
'example/imagery',
'example/eventGenerator'
@ -40,6 +46,26 @@
openmct.install(openmct.plugins.Espresso());
openmct.install(openmct.plugins.Generator());
openmct.install(openmct.plugins.UTCTimeSystem());
/*
Will be installed by default...somehow
*/
//openmct.install(ConductorService());
var ONE_MINUTE = 60 * 1000;
var ONE_YEAR = 365 * 24 * 60 * 60 * 1000;
// Will also provide a default configuration based on enabled time
// systems and tick sources.
openmct.install(openmct.plugins.Conductor({
menuOptions: [
// Default 'fixed' configuration shows last 30 mins of data. May also provide specific bounds.
{timeSystems: ['utc'], defaultDeltas: {start: 30 * ONE_MINUTE, end: 0}, zoomOutLimit: ONE_YEAR, zoomInLimit: ONE_MINUTE},
// Some tick source driven menu options
{tickSource: 'localClock', timeSystems: ['utc'], defaultDeltas: {start: 15 * ONE_MINUTE, end: 0}, zoomOutLimit: ONE_YEAR, zoomInLimit: ONE_MINUTE},
{tickSource: 'latestAvailable', timeSystems: ['utc'], defaultDeltas: {start: 15 * 60 * 1000, end: 0}}
]
}));
openmct.start();
});
</script>

View File

@ -83,7 +83,7 @@ define([
* @memberof module:openmct.MCT#
* @name conductor
*/
this.conductor = new api.TimeConductor();
this.time = new api.Time();
/**
* An interface for interacting with the composition of domain objects.

View File

@ -21,7 +21,7 @@
*****************************************************************************/
define([
'./TimeConductor',
'./time/TimeAPI',
'./objects/ObjectAPI',
'./composition/CompositionAPI',
'./types/TypeRegistry',
@ -29,7 +29,7 @@ define([
'./ui/GestureAPI',
'./telemetry/TelemetryAPI'
], function (
TimeConductor,
TimeAPI,
ObjectAPI,
CompositionAPI,
TypeRegistry,
@ -38,7 +38,7 @@ define([
TelemetryAPI
) {
return {
TimeConductor: TimeConductor,
Time: TimeAPI,
ObjectAPI: ObjectAPI,
CompositionAPI: CompositionAPI,
Dialog: Dialog,

View File

@ -121,7 +121,7 @@ define([
* @memberof module:openmct.TelemetryAPI~
*/
var cachedFormatService;
/**
* An interface for retrieving telemetry data associated with a domain
@ -138,6 +138,7 @@ define([
this.metadataCache = new WeakMap();
this.formatMapCache = new WeakMap();
this.valueFormatterCache = new WeakMap();
this.formatMap = {};
}
/**
@ -281,6 +282,13 @@ define([
return _.sortByAll(options, sortKeys);
};
function getFormatService() {
if (cachedFormatService === undefined) {
cachedFormatService = this.MCT.$injector.get('formatService');
}
return cachedFormatService;
}
/**
* Get a value formatter for a given valueMetadata.
*
@ -288,12 +296,10 @@ define([
*/
TelemetryAPI.prototype.getValueFormatter = function (valueMetadata) {
if (!this.valueFormatterCache.has(valueMetadata)) {
if (!this.formatService) {
this.formatService = this.MCT.$injector.get('formatService');
}
var formatService = getFormatService.call(this);
this.valueFormatterCache.set(
valueMetadata,
new TelemetryValueFormatter(valueMetadata, this.formatService)
new TelemetryValueFormatter(valueMetadata, formatService)
);
}
return this.valueFormatterCache.get(valueMetadata);
@ -334,5 +340,17 @@ define([
return this.legacyProvider.limitEvaluator.apply(this.legacyProvider, arguments);
};
TelemetryAPI.prototype.getFormat = function (formatKey) {
return this.formatMap[formatKey];
};
/**
* Register a new formatter
* @param {Format} formatter
*/
TelemetryAPI.prototype.addFormat = function (format) {
this.formatMap[format.key] = format;
};
return TelemetryAPI;
});

View File

@ -35,7 +35,7 @@ define(['EventEmitter'], function (EventEmitter) {
* @interface
* @memberof module:openmct
*/
function TimeConductor() {
function TimeAPI() {
EventEmitter.call(this);
//The Time System
@ -50,19 +50,30 @@ define(['EventEmitter'], function (EventEmitter) {
//Default to fixed mode
this.followMode = false;
this.timeSystems = {};
this.tickSources = {};
}
TimeConductor.prototype = Object.create(EventEmitter.prototype);
TimeAPI.prototype = Object.create(EventEmitter.prototype);
TimeAPI.prototype.addTimeSystem = function (timeSystem) {
this.timeSystems[timeSystem.key] = timeSystem;
};
TimeAPI.prototype.addTickSource = function (tickSource) {
this.tickSources[tickSource.key] = tickSource;
};
/**
* Validate the given bounds. This can be used for pre-validation of
* bounds, for example by views validating user inputs.
* @param bounds The start and end time of the conductor.
* @returns {string | true} A validation error, or true if valid
* @memberof module:openmct.TimeConductor#
* @memberof module:openmct.TimeAPI#
* @method validateBounds
*/
TimeConductor.prototype.validateBounds = function (bounds) {
TimeAPI.prototype.validateBounds = function (bounds) {
if ((bounds.start === undefined) ||
(bounds.end === undefined) ||
isNaN(bounds.start) ||
@ -75,51 +86,25 @@ define(['EventEmitter'], function (EventEmitter) {
return true;
};
/**
* Get or set the follow mode of the time conductor. In follow mode the
* time conductor ticks, regularly updating the bounds from a timing
* source appropriate to the selected time system and mode of the time
* conductor.
* @fires module:openmct.TimeConductor~follow
* @param {boolean} followMode
* @returns {boolean}
* @memberof module:openmct.TimeConductor#
* @method follow
*/
TimeConductor.prototype.follow = function (followMode) {
if (arguments.length > 0) {
this.followMode = followMode;
/**
* The TimeConductor has toggled into or out of follow mode.
* @event follow
* @memberof module:openmct.TimeConductor~
* @property {boolean} followMode true if follow mode is
* enabled, otherwise false.
*/
this.emit('follow', this.followMode);
}
return this.followMode;
};
/**
* @typedef {Object} TimeConductorBounds
* @property {number} start The start time displayed by the time conductor in ms since epoch. Epoch determined by current time system
* @property {number} end The end time displayed by the time conductor in ms since epoch.
* @memberof module:openmct.TimeConductor~
* @memberof module:openmct.TimeAPI~
*/
/**
* Get or set the start and end time of the time conductor. Basic validation
* of bounds is performed.
*
* @param {module:openmct.TimeConductorBounds~TimeConductorBounds} newBounds
* @param {module:openmct.TimeAPI~TimeConductorBounds} newBounds
* @throws {Error} Validation error
* @fires module:openmct.TimeConductor~bounds
* @returns {module:openmct.TimeConductorBounds~TimeConductorBounds}
* @memberof module:openmct.TimeConductor#
* @fires module:openmct.TimeAPI~bounds
* @returns {module:openmct.TimeAPI~TimeConductorBounds}
* @memberof module:openmct.TimeAPI#
* @method bounds
*/
TimeConductor.prototype.bounds = function (newBounds) {
TimeAPI.prototype.bounds = function (newBounds) {
if (arguments.length > 0) {
var validationResult = this.validateBounds(newBounds);
if (validationResult !== true) {
@ -130,10 +115,12 @@ define(['EventEmitter'], function (EventEmitter) {
/**
* The start time, end time, or both have been updated.
* @event bounds
* @memberof module:openmct.TimeConductor~
* @property {TimeConductorBounds} bounds
* @memberof module:openmct.TimeAPI~
* @property {TimeConductorBounds} bounds The newly updated bounds
* @property {boolean} [tick] `true` if the bounds update was due to
* a "tick" event (ie. was an automatic update), false otherwise.
*/
this.emit('bounds', this.boundsVal);
this.emit('bounds', this.boundsVal, false);
// If a bounds change results in a TOI outside of the current
// bounds, unset it
@ -146,17 +133,17 @@ define(['EventEmitter'], function (EventEmitter) {
};
/**
* Get or set the time system of the TimeConductor. Time systems determine
* Get or set the time system of the TimeAPI. Time systems determine
* units, epoch, and other aspects of time representation. When changing
* the time system in use, new valid bounds must also be provided.
* @param {TimeSystem} newTimeSystem
* @param {module:openmct.TimeConductor~TimeConductorBounds} bounds
* @fires module:openmct.TimeConductor~timeSystem
* @param {module:openmct.TimeAPI~TimeConductorBounds} bounds
* @fires module:openmct.TimeAPI~timeSystem
* @returns {TimeSystem} The currently applied time system
* @memberof module:openmct.TimeConductor#
* @memberof module:openmct.TimeAPI#
* @method timeSystem
*/
TimeConductor.prototype.timeSystem = function (newTimeSystem, bounds) {
TimeAPI.prototype.timeSystem = function (newTimeSystem, bounds) {
if (arguments.length >= 2) {
this.system = newTimeSystem;
/**
@ -164,7 +151,7 @@ define(['EventEmitter'], function (EventEmitter) {
* conductor has changed. A change in Time System will always be
* followed by a bounds event specifying new query bounds.
*
* @event module:openmct.TimeConductor~timeSystem
* @event module:openmct.TimeAPI~timeSystem
* @property {TimeSystem} The value of the currently applied
* Time System
* */
@ -181,19 +168,19 @@ define(['EventEmitter'], function (EventEmitter) {
* focus of the current view. It can be manipulated by the user from the
* time conductor or from other views.The time of interest can
* effectively be unset by assigning a value of 'undefined'.
* @fires module:openmct.TimeConductor~timeOfInterest
* @fires module:openmct.TimeAPI~timeOfInterest
* @param newTOI
* @returns {number} the current time of interest
* @memberof module:openmct.TimeConductor#
* @memberof module:openmct.TimeAPI#
* @method timeOfInterest
*/
TimeConductor.prototype.timeOfInterest = function (newTOI) {
TimeAPI.prototype.timeOfInterest = function (newTOI) {
if (arguments.length > 0) {
this.toi = newTOI;
/**
* The Time of Interest has moved.
* @event timeOfInterest
* @memberof module:openmct.TimeConductor~
* @memberof module:openmct.TimeAPI~
* @property {number} Current time of interest
*/
this.emit('timeOfInterest', this.toi);
@ -201,5 +188,14 @@ define(['EventEmitter'], function (EventEmitter) {
return this.toi;
};
return TimeConductor;
/**
* Return the follow state of the Conductor.
* @returns {boolean} `true` if conductor is currently following a tick source.
* `false` otherwise.
*/
TimeAPI.prototype.follow = function () {
return this.followMode;
};
return TimeAPI;
});

View File

@ -0,0 +1,170 @@
/*****************************************************************************
* 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(
[
'EventEmitter'
],
function (EventEmitter) {
/**
* A class representing the state of the time conductor view. This
* exposes details of the UI that are not represented on the
* TimeConductor API itself such as modes and deltas.
*
* @memberof platform.features.conductor
* @param conductor
* @param timeSystems
* @constructor
*/
function TimeConductorService(openmct) {
EventEmitter.call(this);
this.timeAPI = openmct.time;
}
TimeConductorService.prototype = Object.create(EventEmitter.prototype);
/**
* @private
* @param {number} time some value that is valid in the current TimeSystem
*/
TimeConductorService.prototype.tick = function (time) {
var deltas = this.deltas();
var startTime = time;
var endTime = time;
if (deltas) {
startTime = time - deltas.start;
endTime = time + deltas.end;
}
var newBounds = {
start: startTime,
end: endTime
};
this.timeAPI.boundsVal = newBounds;
this.timeAPI.emit('bounds', true);
// If a bounds change results in a TOI outside of the current
// bounds, unset it
if (this.timeAPI.toi < newBounds.start || this.timeAPI.toi > newBounds.end) {
this.timeAPI.timeOfInterest(undefined);
}
};
TimeConductorService.prototype.configuration = function (config) {
this.config = config;
};
TimeConductorService.prototype.activeTickSource = function (key) {
if (arguments.length > 0) {
if (this.activeTickSource !== undefined) {
this.activeTickSource.off('tick', this.tick);
}
var newTickSource = this.timeAPI.tickSource[key];
if (newTickSource) {
this.activeTickSource.on('tick', this.tick);
this.activeTickSource = newTickSource;
}
}
return this.activeTickSource;
};
/**
* @typedef {object} TimeConductorDeltas
* @property {number} start Used to set the start bound of the
* TimeConductor on tick. A positive value that will be subtracted
* from the value provided by a tick source to determine the start
* bound.
* @property {number} end Used to set the end bound of the
* TimeConductor on tick. A positive value that will be added
* from the value provided by a tick source to determine the start
* bound.
*/
/**
* Deltas define the offset from the latest time value provided by
* the current tick source. Deltas are only valid in realtime or LAD
* modes.
*
* Realtime mode:
* - start: A time in ms before now which will be used to
* determine the 'start' bound on tick
* - end: A time in ms after now which will be used to determine
* the 'end' bound on tick
*
* LAD mode:
* - start: A time in ms before the timestamp of the last data
* received which will be used to determine the 'start' bound on
* tick
* - end: A time in ms after the timestamp of the last data received
* which will be used to determine the 'end' bound on tick
* @returns {TimeConductorDeltas} current value of the deltas
*/
TimeConductorService.prototype.deltas = function () {
// Get / Set deltas
};
/**
* Availability of modes depends on the time systems and tick
* sources available. For example, Latest Available Data mode will
* not be available if there are no time systems and tick sources
* that support LAD mode.
* @returns {ModeMetadata[]}
*/
TimeConductorService.prototype.availableTickSources = function () {
var timeAPI = this.timeAPI;
//Return all tick sources
return _.uniq(this.config.map(function (option) {
return option.tickSource && timeAPI.tickSources(option.tickSource);
}.bind(this)));
};
TimeConductorService.prototype.availableTimeSystems = function () {
return Object.values(this.timeAPI.timeSystems);
};
/**
* An event to indicate that zooming is taking place
* @event platform.features.conductor.TimeConductorService~zoom
* @property {ZoomLevel} zoom the new zoom level.
*/
/**
* Zoom to given time span. Will fire a zoom event with new zoom
* bounds. Zoom bounds emitted in this way are considered ephemeral
* and should be overridden by any time conductor bounds events. Does
* not set bounds globally.
* @param {number} zoom A time duration in ms
* @fires platform.features.conductor.TimeConductorService~zoom
* @see module:openmct.TimeConductor#bounds
*/
TimeConductorService.prototype.zoom = function (timeSpan) {
var zoom = this.currentMode.calculateZoom(timeSpan);
this.emit("zoom", zoom);
return zoom;
};
return TimeConductorService;
}
);

View File

@ -22,7 +22,7 @@
define([
'lodash',
'../../platform/features/conductor/utcTimeSystem/src/UTCTimeSystem',
'./utcTimeSystem/plugin',
'../../example/generator/plugin'
], function (
_,
@ -46,65 +46,20 @@ define([
};
});
plugins.UTCTimeSystem = function () {
return function (openmct) {
openmct.legacyExtension("timeSystems", {
"implementation": UTCTimeSystem,
"depends": ["$timeout"]
});
};
};
var conductorInstalled = false;
plugins.UTCTimeSystem = UTCTimeSystem;
plugins.Conductor = function (options) {
if (!options) {
options = {};
}
function applyDefaults(openmct, timeConductorViewService) {
var defaults = {};
var timeSystem = timeConductorViewService.systems.find(function (ts) {
return ts.metadata.key === options.defaultTimeSystem;
});
if (timeSystem !== undefined) {
defaults = timeSystem.defaults();
if (options.defaultTimespan !== undefined) {
defaults.deltas.start = options.defaultTimespan;
defaults.bounds.start = defaults.bounds.end - options.defaultTimespan;
timeSystem.defaults(defaults);
}
openmct.conductor.timeSystem(timeSystem, defaults.bounds);
}
}
return function (openmct) {
openmct.legacyExtension('constants', {
key: 'DEFAULT_TIMECONDUCTOR_MODE',
value: options.showConductor ? 'fixed' : 'realtime',
priority: conductorInstalled ? 'mandatory' : 'fallback'
openmct.legacyExtension('runs', {
implementation: function applyDefaults(timeConductorService) {
timeConductorService.configuration(options.menuOptions);
},
depends: ["timeConductorService"]
});
if (options.showConductor !== undefined) {
openmct.legacyExtension('constants', {
key: 'SHOW_TIMECONDUCTOR',
value: options.showConductor,
priority: conductorInstalled ? 'mandatory' : 'fallback'
});
}
if (options.defaultTimeSystem !== undefined || options.defaultTimespan !== undefined) {
openmct.legacyExtension('runs', {
implementation: applyDefaults,
depends: ["openmct", "timeConductorViewService"]
});
}
if (!conductorInstalled) {
openmct.legacyRegistry.enable('platform/features/conductor/core');
openmct.legacyRegistry.enable('platform/features/conductor/compatibility');
}
conductorInstalled = true;
};
};

View File

@ -0,0 +1,65 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([], function () {
function LocalClock(tickPeriod) {
//Metadata
this.key = 'localClock';
this.name = 'A local time source';
this.cssClass = 'icon-clock';
//Members
this.listeners = {};
this.tickPeriod = tickPeriod;
this.tick = this.tick.bind(this);
}
LocalClock.prototype.tick = function () {
this.listeners['tick'].forEach(Date.now());
this.timeout = setTimeout(this.tick, this.tickPeriod);
};
LocalClock.prototype.on = function (event, listener) {
this.listeners[event] = this.listeners[event] || [];
this.listeners[event].push(listener);
if (timeout === undefined) {
setTimeout(this.tick, this.tickPeriod);
}
};
LocalClock.prototype.off = function (event, listener) {
if (this.listeners[event]) {
this.listeners[event] = this.listeners[event].filter(function (l) {
return l === listener;
});
var isEmpty = Object.keys(this.listeners).all(function (key){
return this.listeners[key] === undefined || this.listeners[key].length === 0
});
if (isEmpty) {
clearTimeout(this.timeout);
}
}
};
return LocalClock;
});

View File

@ -0,0 +1,131 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'moment'
], function (
moment
) {
var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss.SSS",
DATE_FORMATS = [
DATE_FORMAT,
"YYYY-MM-DD HH:mm:ss",
"YYYY-MM-DD HH:mm",
"YYYY-MM-DD"
];
/**
* @typedef Scale
* @property {number} min the minimum scale value, in ms
* @property {number} max the maximum scale value, in ms
*/
/**
* Formatter for UTC timestamps. Interprets numeric values as
* milliseconds since the start of 1970.
*
* @implements {Format}
* @constructor
* @memberof platform/commonUI/formats
*/
function UTCTimeFormat() {
}
/**
* Returns an appropriate time format based on the provided value and
* the threshold required.
* @private
*/
function getScaledFormat(d) {
var momentified = moment.utc(d);
/**
* Uses logic from d3 Time-Scales, v3 of the API. See
* https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Scales.md
*
* Licensed
*/
var format = [
[".SSS", function (m) {
return m.milliseconds();
}],
[":ss", function (m) {
return m.seconds();
}],
["HH:mm", function (m) {
return m.minutes();
}],
["HH", function (m) {
return m.hours();
}],
["ddd DD", function (m) {
return m.days() &&
m.date() !== 1;
}],
["MMM DD", function (m) {
return m.date() !== 1;
}],
["MMMM", function (m) {
return m.month();
}],
["YYYY", function () {
return true;
}]
].filter(function (row) {
return row[1](momentified);
})[0][0];
if (format !== undefined) {
return moment.utc(value).format(scaledFormat);
}
}
/**
* @param {number} value The value to format.
* @param {number} [minValue] Contextual information for scaled formatting used in linear scales such as conductor
* and plot axes. Specifies the smallest number on the scale.
* @param {number} [maxValue] Contextual information for scaled formatting used in linear scales such as conductor
* and plot axes. Specifies the largest number on the scale
* @param {number} [count] Contextual information for scaled formatting used in linear scales such as conductor
* and plot axes. The number of labels on the scale.
* @returns {string} the formatted date(s). If multiple values were requested, then an array of
* formatted values will be returned. Where a value could not be formatted, `undefined` will be returned at its position
* in the array.
*/
UTCTimeFormat.prototype.format = function (value, minValue, maxValue, count) {
if (arguments.length > 1) {
return values.map(getScaledFormat);
} else {
return moment.utc(value).format(DATE_FORMAT) + "Z";
}
};
UTCTimeFormat.prototype.parse = function (text) {
return moment.utc(text, DATE_FORMATS).valueOf();
};
UTCTimeFormat.prototype.validate = function (text) {
return moment.utc(text, DATE_FORMATS).isValid();
};
return UTCTimeFormat;
});

View File

@ -0,0 +1,21 @@
define([
'./UTCTimeFormat',
'./LocalClock'
], function (
UtcTimeFormat,
LocalClock
) {
return function UtcTimeSystemPlugin(options) {
return function install(openmct) {
openmct.telemetry.addFormat(new UtcTimeFormat());
openmct.conductor.addTimeSystem({
key: 'utc',
name: 'UTC',
timeFormat: 'utc',
durationFormat: 'duration',
utcBased: true
});
openmct.conductor.addTickSource(new LocalClock());
}
}
});