Compare commits

..

9 Commits

Author SHA1 Message Date
Henry
7e3ade81e3 WIP 2017-12-11 12:31:47 -08:00
Henry
05ed6597e8 [Examples] Return fibonacci number as text 2017-12-11 12:31:03 -08:00
Henry
638651a0ad [Examples] Return example user on demand instead of on service construction 2017-12-11 12:31:03 -08:00
Henry
dbae627ad9 WIP 2017-12-11 12:31:03 -08:00
Henry
a6e93f7ad0 [API] Some refactoring of the Indicator API 2017-12-11 12:31:03 -08:00
Henry
0dc75b2ace [Indicators] Support legacy indicators with new API 2017-12-11 12:31:03 -08:00
Henry
96e11c4f1b [Indicators] Initial integration of new Indicator API with existing indicators 2017-12-11 12:31:03 -08:00
Henry
6cc7f23786 [API] Initial implementation of Indicator API 2017-12-11 12:31:03 -08:00
Henry
ce11d48d25 WIP 2017-12-11 12:31:03 -08:00
34 changed files with 481 additions and 620 deletions

View File

@@ -38,7 +38,8 @@ define([
"provides": "identityService",
"type": "provider",
"depends": [
"dialogService"
"dialogService",
"$q"
]
}
]

View File

@@ -55,21 +55,37 @@ define(
* @implements {IdentityService}
* @memberof platform/identity
*/
function ExampleIdentityProvider(dialogService) {
// Handle rejected dialog messages by treating the
// current user as undefined.
function echo(v) { return v; }
function giveUndefined() { return undefined; }
function ExampleIdentityProvider(dialogService, $q) {
this.dialogService = dialogService;
this.$q = $q;
this.userPromise =
dialogService.getUserInput(DIALOG_STRUCTURE, DEFAULT_IDENTITY)
.then(echo, giveUndefined);
this.returnUser = this.returnUser.bind(this);
this.returnUndefined = this.returnUndefined.bind(this);
}
ExampleIdentityProvider.prototype.getUser = function () {
return this.userPromise;
if (this.user) {
return this.$q.when(this.user);
} else {
return this.dialogService.getUserInput(DIALOG_STRUCTURE, DEFAULT_IDENTITY)
.then(this.returnUser, this.returnUndefined);
}
};
/**
* @private
*/
ExampleIdentityProvider.prototype.returnUser = function (user) {
return this.user = user;
}
/**
* @private
*/
ExampleIdentityProvider.prototype.returnUndefined = function () {
return undefined;
}
return ExampleIdentityProvider;
}
);

View File

@@ -54,7 +54,7 @@ define(
return "icon-object-unknown";
},
getText: function () {
return latest;
return "" + latest;
},
getDescription: function () {
return "";

View File

@@ -68,7 +68,6 @@
]
}));
openmct.install(openmct.plugins.SummaryWidget());
openmct.install(openmct.plugins.ActivityModes());
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
openmct.time.timeSystem('utc');
openmct.start();

View File

@@ -49,8 +49,7 @@ requirejs.config({
"d3-format": "node_modules/d3-format/build/d3-format.min",
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
"d3-time": "node_modules/d3-time/build/d3-time.min",
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min",
"d3-dsv": "node_modules/d3-dsv/build/d3-dsv.min"
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
},
"shim": {
"angular": {

View File

@@ -7,7 +7,6 @@
"d3-axis": "^1.0.4",
"d3-collection": "^1.0.2",
"d3-color": "^1.0.2",
"d3-dsv": "^1.0.8",
"d3-format": "^1.0.2",
"d3-interpolate": "^1.1.3",
"d3-scale": "^1.0.4",

View File

@@ -34,7 +34,6 @@ define([
"./src/controllers/ContextMenuController",
"./src/controllers/ClickAwayController",
"./src/controllers/ViewSwitcherController",
"./src/controllers/BottomBarController",
"./src/controllers/GetterSetterController",
"./src/controllers/SelectorController",
"./src/controllers/ObjectInspectorController",
@@ -49,6 +48,7 @@ define([
"./src/directives/MCTSplitPane",
"./src/directives/MCTSplitter",
"./src/directives/MCTTree",
"./src/directives/MCTIndicators",
"./src/filters/ReverseFilter",
"text!./res/templates/bottombar.html",
"text!./res/templates/controls/action-button.html",
@@ -84,7 +84,6 @@ define([
ContextMenuController,
ClickAwayController,
ViewSwitcherController,
BottomBarController,
GetterSetterController,
SelectorController,
ObjectInspectorController,
@@ -99,6 +98,7 @@ define([
MCTSplitPane,
MCTSplitter,
MCTTree,
MCTIndicators,
ReverseFilter,
bottombarTemplate,
actionButtonTemplate,
@@ -275,13 +275,6 @@ define([
"$timeout"
]
},
{
"key": "BottomBarController",
"implementation": BottomBarController,
"depends": [
"indicators[]"
]
},
{
"key": "GetterSetterController",
"implementation": GetterSetterController,
@@ -395,6 +388,11 @@ define([
"key": "mctTree",
"implementation": MCTTree,
"depends": ['gestureService']
},
{
"key": "mctIndicators",
"implementation": MCTIndicators,
"depends": ['openmct']
}
],
"constants": [

View File

@@ -19,14 +19,9 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class='abs bottom-bar ue-bottom-bar mobile-disable-select' ng-controller="BottomBarController as bar">
<div class='abs bottom-bar ue-bottom-bar mobile-disable-select'>
<div id='status' class='status-holder'>
<mct-include ng-repeat="indicator in bar.getIndicators()"
ng-model="indicator.ngModel"
key="indicator.template"
class="status-block-holder"
ng-class='indicator.ngModel.getGlyphClass()'>
</mct-include>
<mct-indicators></mct-indicators>
</div>
<mct-include key="'message-banner'"></mct-include>
<mct-include key="'about-logo'"></mct-include>

View File

@@ -21,13 +21,11 @@
-->
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<div class='status block'
title="{{ngModel.getDescription()}}"
ng-click='ngModel.configure()'
ng-show="ngModel.getText().length > 0">
<span class="status-indicator {{ngModel.getCssClass()}}"></span><span class="label"
ng-class='ngModel.getTextClass()'>
{{ngModel.getText()}}
<a class="s-button icon-gear" ng-if="ngModel.configure"></a>
title="{{ngModel.description()}}"
ng-show="ngModel.text().length > 0">
<span class="status-indicator {{ngModel.cssClass()}}"></span><span class="label"
ng-class='ngModel.textClass()'>
{{ngModel.text()}}
</span><span class="count">
</span>
</div>

View File

@@ -23,37 +23,21 @@
define(
[],
function () {
/**
* Controller for the bottombar template. Exposes
* available indicators (of extension category "indicators")
* @memberof platform/commonUI/general
* @constructor
*/
function BottomBarController(indicators) {
// Utility function used to make indicators presentable
// for display.
function present(Indicator) {
return {
template: Indicator.template || "indicator",
ngModel: typeof Indicator === 'function' ?
new Indicator() : Indicator
};
}
this.indicators = indicators.map(present);
function MCTIndicators(openmct) {
return {
restrict: "E",
link: function link(scope, element, attrs) {
openmct.indicators.displayFunctions().then(function (displayFunctions){
displayFunctions.forEach(function (displayFunction){
var displayElement = displayFunction();
element.append(displayElement);
});
})
}
};
}
/**
* Get all indicators to display.
* @returns {Indicator[]} all indicators
* to display in the bottom bar.
* @memberof platform/commonUI/general.BottomBarController#
*/
BottomBarController.prototype.getIndicators = function () {
return this.indicators;
};
return MCTIndicators;
return BottomBarController;
}
);

View File

@@ -1,76 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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(
["../../src/controllers/BottomBarController"],
function (BottomBarController) {
describe("The bottom bar controller", function () {
var testIndicators,
testIndicatorA,
testIndicatorB,
testIndicatorC,
mockIndicator,
controller;
beforeEach(function () {
mockIndicator = jasmine.createSpyObj(
"indicator",
["getGlyph", "getCssClass", "getText"]
);
testIndicatorA = {};
testIndicatorB = function () {
return mockIndicator;
};
testIndicatorC = { template: "someTemplate" };
testIndicators = [
testIndicatorA,
testIndicatorB,
testIndicatorC
];
controller = new BottomBarController(testIndicators);
});
it("exposes one indicator description per extension", function () {
expect(controller.getIndicators().length)
.toEqual(testIndicators.length);
});
it("uses template field provided, or its own default", function () {
// "indicator" is the default;
// only testIndicatorC overrides this.
var indicators = controller.getIndicators();
expect(indicators[0].template).toEqual("indicator");
expect(indicators[1].template).toEqual("indicator");
expect(indicators[2].template).toEqual("someTemplate");
});
it("instantiates indicators given as constructors", function () {
// testIndicatorB constructs to mockIndicator
expect(controller.getIndicators()[1].ngModel).toBe(mockIndicator);
});
});
}
);

View File

@@ -55,7 +55,6 @@ define([
timerTemplate,
legacyRegistry
) {
legacyRegistry.register("platform/features/clock", {
"name": "Clocks/Timers",
"descriptions": "Domain objects for displaying current & relative times.",
@@ -86,11 +85,6 @@ define([
"CLOCK_INDICATOR_FORMAT"
],
"priority": "preferred"
},
{
"implementation": FollowIndicator,
"depends": ["timerService"],
"priority": "fallback"
}
],
"services": [
@@ -305,6 +299,10 @@ define([
}
}
],
"runs": [{
"implementation": FollowIndicator,
"depends": ["openmct", "timerService"]
}],
"licenses": [
{
"name": "moment-duration-format",

View File

@@ -20,38 +20,29 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
['moment'],
function (moment) {
var NO_TIMER = "No timer being followed";
define([],function () {
/**
* Indicator that displays the active timer, as well as its
* current state.
* @implements {Indicator}
* @memberof platform/features/clock
*/
function FollowIndicator(timerService) {
this.timerService = timerService;
function setIndicatorStatus(indicator, timer) {
if (timer !== undefined) {
indicator.cssClass('icon-timer s-status-ok');
indicator.text('Following timer ' + timer.name);
} else {
indicator.cssClass('icon-timer');
indicator.text('No timer being followed.');
}
FollowIndicator.prototype.getGlyphClass = function () {
return "";
};
FollowIndicator.prototype.getCssClass = function () {
return (this.timerService.getTimer()) ? "icon-timer s-status-ok" : "icon-timer";
};
FollowIndicator.prototype.getText = function () {
var timer = this.timerService.getTimer();
return timer ? ('Following timer ' + timer.name) : NO_TIMER;
};
FollowIndicator.prototype.getDescription = function () {
return "";
};
return FollowIndicator;
}
);
/**
* Indicator that displays the active timer, as well as its
* current state.
* @memberof platform/features/clock
*/
return function installFollowIndicator(openmct, timerService) {
var indicator = openmct.indicators.create();
var timer = timerService.getTimer();
var setIndicatorStatusFromTimer = setIndicatorStatus.bind(this, indicator);
setIndicatorStatusFromTimer(timer);
timerService.on('change', setIndicatorStatusFromTimer);
};
});

View File

@@ -44,7 +44,7 @@ define(['EventEmitter'], function (EventEmitter) {
*/
TimerService.prototype.setTimer = function (timer) {
this.timer = timer;
this.emit('change');
this.emit('change', timer);
if (this.stopObserving) {
this.stopObserving();

View File

@@ -42,15 +42,18 @@ define(["../../src/indicators/FollowIndicator"], function (FollowIndicator) {
});
describe("when a timer is set", function () {
var testObject;
var testModel;
var mockDomainObject;
beforeEach(function () {
testObject = { name: "some timer!" };
mockTimerService.getTimer.andReturn(testObject);
testModel = { name: "some timer!" };
mockDomainObject = jasmine.createSpyObj('timer', ['getModel']);
mockDomainObject.getModel.andReturn(testModel);
mockTimerService.getTimer.andReturn(mockDomainObject);
});
it("displays the timer's name", function () {
expect(indicator.getText().indexOf(testObject.name))
expect(indicator.getText().indexOf(testModel.name))
.not.toEqual(-1);
});
});

View File

@@ -32,7 +32,6 @@ define([
"./src/controllers/TimelineTOIController",
"./src/controllers/ActivityModeValuesController",
"./src/capabilities/ActivityTimespanCapability",
"./src/capabilities/ActivityValueCapability",
"./src/capabilities/TimelineTimespanCapability",
"./src/capabilities/UtilizationCapability",
"./src/capabilities/GraphCapability",
@@ -43,7 +42,6 @@ define([
"./src/services/ObjectLoader",
"./src/chart/MCTTimelineChart",
"text!./res/templates/values.html",
"text!./res/templates/activity-view.html",
"text!./res/templates/timeline.html",
"text!./res/templates/activity-gantt.html",
"text!./res/templates/tabular-swimlane-cols-tree.html",
@@ -66,7 +64,6 @@ define([
TimelineTOIController,
ActivityModeValuesController,
ActivityTimespanCapability,
ActivityValueCapability,
TimelineTimespanCapability,
UtilizationCapability,
GraphCapability,
@@ -77,7 +74,6 @@ define([
ObjectLoader,
MCTTimelineChart,
valuesTemplate,
activityTemplate,
timelineTemplate,
activityGanttTemplate,
tabularSwimlaneColsTreeTemplate,
@@ -208,9 +204,7 @@ define([
"composition": [],
"start": {
"timestamp": 0
},
"activityStart": {},
"activityDuration": {}
}
}
},
{
@@ -310,17 +304,6 @@ define([
],
"editable": false
},
{
"key": "activityValues",
"name": "Activity Values",
"cssClass": "icon-activity",
"template": activityTemplate,
"type": "activity",
"uses": [
"activityValue"
],
"editable": false
},
{
"key": "timeline",
"name": "Timeline",
@@ -572,10 +555,6 @@ define([
{
"key": "cost",
"implementation": CostCapability
},
{
"key": "activityValue",
"implementation": ActivityValueCapability
}
],
"directives": [

View File

@@ -1,27 +0,0 @@
<!--
Open MCT, Copyright (c) 2009-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.
-->
<ul ng-controller="ActivityModeValuesController as controller" class="cols cols-2-ff properties">
<li ng-repeat="(key, value) in activityValue" class="l-row s-row">
<span class="col col-100px s-title"></span>
<span class="col s-value">{{value}}</span>
</li>
</ul>

View File

@@ -20,7 +20,6 @@
at runtime from the About dialog for additional information.
-->
<div class="s-timeline l-timeline-holder split-layout vertical splitter-sm"
ng-click="$event.stopPropagation()"
ng-controller="TimelineController as timelineController">
<mct-split-pane anchor="left" class="abs" position="pane.x">

View File

@@ -21,48 +21,27 @@
*****************************************************************************/
define(
['EventEmitter'],
function (EventEmitter) {
[],
function () {
/**
* Describes the time span of an activity object.
* @param model the activity's object model
*/
function ActivityTimespan(model, mutation, parentTimeline) {
var parentTimelineModel = parentTimeline.getModel(),
parentMutation = parentTimeline.getCapability('mutation');
function getTimelineActivityStart (domainObjectModel) {
if (domainObjectModel.activityStart && domainObjectModel.activityStart[model.id]) {
return domainObjectModel.activityStart[model.id];
} else {
return model.start.timestamp;
}
}
function getTimelineActivityDuration (domainObjectModel) {
if (domainObjectModel.activityDuration && domainObjectModel.activityDuration[model.id]) {
return domainObjectModel.activityDuration[model.id];
} else {
return model.duration.timestamp;
}
}
function ActivityTimespan(model, mutation) {
// Get the start time for this timeline
function getStart() {
return getTimelineActivityStart(parentTimelineModel);
return model.start.timestamp;
}
// Get the end time for this timeline
function getEnd() {
var start = getTimelineActivityStart(parentTimelineModel),
duration = getTimelineActivityDuration(parentTimelineModel);
return start + duration;
return model.start.timestamp + model.duration.timestamp;
}
// Get the duration of this timeline
function getDuration() {
return getTimelineActivityDuration(parentTimelineModel);
return model.duration.timestamp;
}
// Get the epoch used by this timeline
@@ -73,41 +52,26 @@ define(
// Set the start time associated with this object
function setStart(value) {
var end = getEnd();
parentMutation.mutate(function (m) {
m.activityStart[model.id] = Math.max(value,0);
m.activityDuration[model.id] = Math.max(end - value, 0);
});
// mutation.mutate(function (m) {
// m.start.timestamp = Math.max(value, 0);
// // Update duration to keep end time
// m.duration.timestamp = Math.max(end - value, 0);
// }, model.modified);
mutation.mutate(function (m) {
m.start.timestamp = Math.max(value, 0);
// Update duration to keep end time
m.duration.timestamp = Math.max(end - value, 0);
}, model.modified);
}
// Set the duration associated with this object
function setDuration(value) {
parentMutation.mutate(function (m) {
m.activityDuration[model.id] = Math.max(value, 0);
});
// mutation.mutate(function (m) {
// m.duration.timestamp = Math.max(value, 0);
// }, model.modified);
mutation.mutate(function (m) {
m.duration.timestamp = Math.max(value, 0);
}, model.modified);
}
// Set the end time associated with this object
function setEnd(value) {
var start = getStart();
parentMutation.mutate(function (m) {
m.activityDuration[model.id] = Math.max(value - start, 0);
});
// mutation.mutate(function (m) {
// m.duration.timestamp = Math.max(value - start, 0);
// }, model.modified);
mutation.mutate(function (m) {
m.duration.timestamp = Math.max(value - start, 0);
}, model.modified);
}
return {

View File

@@ -32,26 +32,11 @@ define(
* @param {DomainObject} domainObject the Activity
*/
function ActivityTimespanCapability($q, domainObject) {
function findTimeline (object) {
var parent = domainObject.getCapability('context').parentObject;
while (parent.getModel().type !== 'timeline') {
parent = parent.getCapability('context').parentObject;
findTimeline(parent);
}
return parent;
}
var parent = findTimeline(domainObject);
// Promise time span
function promiseTimeSpan() {
return $q.when(new ActivityTimespan(
domainObject.getModel(),
domainObject.getCapability('mutation'),
parent
domainObject.getCapability('mutation')
));
}

View File

@@ -1,75 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2009-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 () {
/**
* Exposes costs associated with a subsystem mode.
* @constructor
*/
function ActivityValueCapability(domainObject) {
var model = domainObject.getModel();
return {
/**
* Get a list of resource types which have associated
* costs for this object. Returned values are machine-readable
* keys, and should be paired with external metadata for
* presentation (see category of extension `resources`).
* @returns {string[]} resource types
*/
resources: function () {
return Object.keys(model.resources || {}).sort();
},
/**
* Get the cost associated with a resource of an identified
* type (typically, one of the types reported from a
* `resources` call.)
* @param {string} key the resource type
* @returns {number} the associated cost
*/
cost: function (key) {
return (model.resources || {})[key] || 0;
},
/**
* Get an object containing key-value pairs describing
* resource utilization as described by this object.
* Keys are resource types; values are levels of associated
* resource utilization.
* @returns {object} resource utilizations
*/
invoke: function () {
return {key: 'deep is the best'};
}
};
}
// Only applies to subsystem modes.
ActivityValueCapability.appliesTo = function (model) {
return (model || {}).type === 'activity';
};
return ActivityValueCapability;
}
);

View File

@@ -30,7 +30,7 @@ define(
*/
function CostCapability(domainObject) {
var model = domainObject.getModel();
return {
/**
* Get a list of resource types which have associated

View File

@@ -193,6 +193,15 @@ define([
* @name telemetry
*/
this.telemetry = new api.TelemetryAPI(this);
/**
* An interface for creating new indicators and changing them dynamically.
*
* @type {module:openmct.IndicatorAPI}
* @memberof module:openmct.MCT#
* @name indicators
*/
this.indicators = new api.IndicatorAPI(this);
this.Dialog = api.Dialog;

View File

@@ -27,7 +27,8 @@ define([
'./types/TypeRegistry',
'./ui/Dialog',
'./ui/GestureAPI',
'./telemetry/TelemetryAPI'
'./telemetry/TelemetryAPI',
'./indicators/IndicatorAPI'
], function (
TimeAPI,
ObjectAPI,
@@ -35,7 +36,8 @@ define([
TypeRegistry,
Dialog,
GestureAPI,
TelemetryAPI
TelemetryAPI,
IndicatorAPI
) {
return {
TimeAPI: TimeAPI,
@@ -44,6 +46,7 @@ define([
Dialog: Dialog,
TypeRegistry: TypeRegistry,
GestureAPI: GestureAPI,
TelemetryAPI: TelemetryAPI
TelemetryAPI: TelemetryAPI,
IndicatorAPI: IndicatorAPI
};
});

View File

@@ -0,0 +1,111 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'text!./res/indicator-template.html'
], function (
indicatorTemplate
) {
function Indicator(openmct) {
this.openmct = openmct;
this.textValue = '';
this.descriptionValue = '';
this.cssClassValue = '';
this.iconClassValue = '';
this.textClassValue = '';
this.glyphClassValue = '';
this.node = undefined;
}
Indicator.prototype.text = function (text) {
if (text !== undefined && text !== this.textValue) {
this.textValue = text;
Indicator.defaultDisplayFunction.call(this);
}
return this.textValue;
}
Indicator.prototype.description = function (description) {
if (description !== undefined && description !== this.descriptionValue) {
this.descriptionValue = description;
Indicator.defaultDisplayFunction.call(this);
}
return this.descriptionValue;
}
Indicator.prototype.iconClass = function (iconClass) {
if (iconClass !== undefined && iconClass !== this.iconClassValue) {
this.iconClassValue = iconClass;
Indicator.defaultDisplayFunction.call(this);
}
return this.iconClassValue;
}
Indicator.prototype.cssClass = function (cssClass) {
if (cssClass !== undefined && cssClass !== this.cssClassValue) {
this.cssClassValue = cssClass;
Indicator.defaultDisplayFunction.call(this);
}
return this.cssClassValue;
}
Indicator.prototype.glyphClass = function (glyphClass) {
if (glyphClass !== undefined && glyphClass !== this.glyphClassValue) {
this.glyphClassValue = glyphClass;
Indicator.defaultDisplayFunction.call(this);
}
return this.glyphClassValue;
}
Indicator.prototype.textClass = function (textClass) {
if (textClass !== undefined && textClass !== this.textClassValue) {
this.textClassValue = textClass;
Indicator.defaultDisplayFunction.call(this);
}
return this.textClassValue;
}
Indicator.defaultDisplayFunction = function () {
var html = indicatorTemplate.replace('{{indicator.text}}', this.text())
.replace('{{indicator.textClass}}', this.textClass())
.replace('{{indicator.cssClass}}', this.cssClass())
.replace('{{indicator.glyphClass}}', this.glyphClass())
.replace('{{indicator.description}}', this.description());
if (!this.node){
this.node = document.createElement('div');
this.node.className = 'status-block-holder';
}
this.node.innerHTML = html;
return this.node;
}
return Indicator;
});

View File

@@ -0,0 +1,85 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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([
'./Indicator',
'./LegacyIndicator'
], function (
Indicator,
LegacyIndicator
) {
function IndicatorAPI(openmct) {
this.openmct = openmct;
this.indicators = [];
this.legacyIndicatorsPromise = new Promise(function (resolve) {
this.resolveWithIndicators = resolve;
onStartWrapLegacyIndicators.call(this);
}.bind(this));
}
IndicatorAPI.prototype.create = function (displayFunction) {
if (displayFunction !== undefined) {
this.indicators.push(displayFunction);
} else {
var indicator = new Indicator(this.openmct);
this.indicators.push(Indicator.defaultDisplayFunction.bind(indicator));
return indicator;
}
}
/**
* @private
*/
IndicatorAPI.prototype.displayFunctions = function () {
return this.legacyIndicatorsPromise.then(function (legacyIndicators) {
var wrappedLegacyIndicators = wrapAllLegacyIndicators.call(this, legacyIndicators);
return this.indicators.concat(wrappedLegacyIndicators);
}.bind(this));
}
function onStartWrapLegacyIndicators() {
this.openmct.legacyExtension('runs', {
depends: ['indicators[]'],
implementation: this.resolveWithIndicators
});
}
function wrapAllLegacyIndicators(legacyIndicators) {
return legacyIndicators.map(convertToNewIndicator.bind(this));
}
function convertToNewIndicator(legacyIndicatorDef) {
var legacyIndicator;
if (typeof legacyIndicatorDef === 'function') {
legacyIndicator = new legacyIndicatorDef();
} else {
legacyIndicator = legacyIndicatorDef;
}
var newStyleIndicator = new LegacyIndicator(this.openmct, legacyIndicator, legacyIndicatorDef.template);
return LegacyIndicator.displayFunction.bind(newStyleIndicator);
}
return IndicatorAPI;
});

View File

@@ -0,0 +1,81 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'zepto',
'./Indicator'
], function ($, Indicator) {
var TEMPLATE =
'<mct-include ' +
' ng-model="indicator" ' +
' key="template" ' +
' class="status-block-holder" ' +
' ng-class="indicator.glyphClass()"> ' +
' </mct-include>';
function LegacyIndicator(openmct, legacyIndicator, template) {
this.openmct = openmct;
this.legacyIndicator = legacyIndicator;
this.template = template;
}
LegacyIndicator.prototype.display = function () {
return legacyDisplayFunction.bind(this);
}
LegacyIndicator.prototype.text = function () {
return this.legacyIndicator.getText &&
this.legacyIndicator.getText();
}
LegacyIndicator.prototype.description = function () {
return this.legacyIndicator.getDescription &&
this.legacyIndicator.getDescription();
}
LegacyIndicator.prototype.cssClass = function () {
return this.legacyIndicator.getCssClass &&
this.legacyIndicator.getCssClass();
}
LegacyIndicator.prototype.glyphClass = function () {
return this.legacyIndicator.getGlyphClass &&
this.legacyIndicator.getGlyphClass();
}
LegacyIndicator.prototype.textClass = function () {
return this.legacyIndicator.getTextClass &&
this.legacyIndicator.getTextClass();
}
LegacyIndicator.displayFunction = function () {
var $compile = this.openmct.$injector.get('$compile');
var $rootScope = this.openmct.$injector.get('$rootScope');
var scope = $rootScope.$new(true);
scope.indicator = this;
scope.template = this.template || 'indicator';
return $compile(TEMPLATE)(scope)[0];
}
return LegacyIndicator;
});

View File

@@ -0,0 +1,7 @@
<div class="{{indicator.glyphClass}}">
<div class="status block" title="{{indicator.description}}" ng-show="ngModel.text().length > 0">
<span class="status-indicator {{indicator.cssClass}}"></span><span class="label" class='{{indicator.textClass}}'>
{{indicator.text}}
</span><span class="count"></span>
</div>
</div>

View File

@@ -21,8 +21,8 @@
*****************************************************************************/
define(
[],
function () {
['zepto'],
function ($) {
// Set of connection states; changing among these states will be
// reflected in the indicator's appearance.
@@ -33,65 +33,81 @@ define(
glyphClass: "ok"
},
PENDING = {
glyphClass: 'caution'
glyphClass: "caution"
},
DISCONNECTED = {
glyphClass: "err"
};
function URLIndicator($http, $interval) {
var self = this;
this.cssClass = this.options.cssClass ? this.options.cssClass : "icon-database";
this.URLpath = this.options.url;
this.label = this.options.label ? this.options.label : this.options.url;
this.interval = this.options.interval || 10000;
this.state = PENDING;
function URLIndicator(options, openmct) {
this.bindMethods();
function handleError(e) {
self.state = DISCONNECTED;
}
function handleResponse() {
self.state = CONNECTED;
}
function updateIndicator() {
$http.get(self.URLpath).then(handleResponse, handleError);
}
updateIndicator();
$interval(updateIndicator, self.interval, 0, false);
this.indicator = openmct.indicators.create();
this.setDefaultsFromOptions(options);
this.setIndicatorToState(PENDING);
this.fetchUrl();
setInterval(this.fetchUrl, this.interval);
}
URLIndicator.prototype.getCssClass = function () {
return this.cssClass;
};
URLIndicator.prototype.getGlyphClass = function () {
return this.state.glyphClass;
};
URLIndicator.prototype.getText = function () {
switch (this.state) {
URLIndicator.prototype.setIndicatorToState = function (state) {
switch (state) {
case CONNECTED: {
return this.label + " is connected";
this.indicator.text(this.label + " is connected");
this.indicator.description(this.label + " is online, checking status every " + this.interval + " milliseconds.");
break;
}
case PENDING: {
return "Checking status of " + this.label + " please stand by...";
this.indicator.text("Checking status of " + this.label + " please stand by...");
this.indicator.description("Checking status of " + this.label + " please stand by...");
break;
}
case DISCONNECTED: {
return this.label + " is offline";
this.indicator.text(this.label + " is offline");
this.indicator.description(this.label + " is offline, checking status every " + this.interval + " milliseconds");
break;
}
}
};
this.indicator.glyphClass(state.glyphClass);
};
URLIndicator.prototype.getDescription = function () {
switch (this.state) {
case CONNECTED: {
return this.label + " is online, checking status every " +
this.interval + " milliseconds.";
}
case PENDING: {
return "Checking status of " + this.label + " please stand by...";
}
case DISCONNECTED: {
return this.label + " is offline, checking status every " +
this.interval + " milliseconds";
}
}
URLIndicator.prototype.fetchUrl = function () {
this.get(this.URLpath)
.then(this.handleSuccess)
.catch(this.handleError);
};
URLIndicator.prototype.get = function (url) {
return new Promise(function(resolve, reject){
$.ajax({
type: 'GET',
url: url,
success: resolve,
error: reject
});
}.bind(this));
};
URLIndicator.prototype.handleError = function (e) {
this.setIndicatorToState(DISCONNECTED);
};
URLIndicator.prototype.handleSuccess = function () {
this.setIndicatorToState(CONNECTED);
}
URLIndicator.prototype.setDefaultsFromOptions = function (options) {
this.URLpath = options.url;
this.label = options.label || options.url;
this.interval = options.inverval || 10000;
this.indicator.cssClass(options.cssClass || 'icon-database');
}
URLIndicator.prototype.bindMethods = function () {
this.fetchUrl = this.fetchUrl.bind(this);
this.handleSuccess = this.handleSuccess.bind(this);
this.handleError = this.handleError.bind(this);
this.setIndicatorToState = this.setIndicatorToState.bind(this);
}
return URLIndicator;
});

View File

@@ -3,18 +3,10 @@ define(
'./URLIndicator'
],
function URLIndicatorPlugin(URLIndicator) {
return function (opts) {
// Wrap the plugin in a function so we can apply the arguments.
function URLIndicatorWrapper() {
this.options = opts;
URLIndicator.apply(this, arguments);
}
URLIndicatorWrapper.prototype = Object.create(URLIndicator.prototype);
return function install(openmct) {
openmct.legacyExtension('indicators', {
"implementation": URLIndicatorWrapper,
"depends": ["$http", "$interval"]
});
return new URLIndicator(opts, openmct);
};
};
});

View File

@@ -1,47 +0,0 @@
define(['./src/actions/activityModesImportAction'], function (ActivityModes) {
function plugin() {
return function install(openmct) {
openmct.legacyRegistry.register("src/plugins/activityModes", {
"name": "Activity Import",
"description": "Defines a root named My Items",
"extensions": {
"roots": [
{
"id": "activity-import"
}
],
"models": [
{
"id": "activity-import",
"model": {
"name": "Activity Import",
"type": "folder",
"composition": [],
"location": "ROOT"
}
}
]
}
});
openmct.legacyRegistry.enable("src/plugins/activityModes");
openmct.legacyExtension('actions', {
key: "import-csv",
category: ["contextual"],
implementation: ActivityModes,
cssClass: "major icon-import",
name: "Import Activity Definitions from CSV",
description: "Import activities from a CSV file",
depends: [
"dialogService",
"openmct"
]
});
};
}
return plugin;
});

View File

@@ -1,127 +0,0 @@
define(['d3-dsv'], function (d3Dsv) {
function ActivityModesImportAction(dialogService, openmct, context) {
this.dialogService = dialogService;
this.openmct = openmct;
this.context = context;
this.parent = this.context.domainObject;
this.instantiate = this.openmct.$injector.get("instantiate");
this.instantiateActivities = this.instantiateActivities.bind(this);
}
ActivityModesImportAction.prototype.perform = function () {
this.dialogService.getUserInput(this.getFormModel(), function () {})
.then(function (form) {
if(form.selectFile.name.slice(-3) !== 'csv'){
this.displayError();
}
this.csvParse(form.selectFile.body).then(this.instantiateActivities);
}.bind(this));
};
ActivityModesImportAction.prototype.csvParse = function (csvString) {
return new Promise(function (resolve, reject) {
var parsedObject = d3Dsv.csvParse(csvString);
return parsedObject ? resolve(parsedObject) : reject('Could not parse provided file');
});
};
ActivityModesImportAction.prototype.instantiateActivities = function (csvObjects) {
var parent = this.context.domainObject,
parentId = parent.getId(),
parentComposition = parent.getCapability("composition"),
activitiesObjects = [],
activityModesObjects = [];
csvObjects.forEach(function (activity) {
var newActivity = {},
newActivityMode = {};
newActivity.name = activity.name;
newActivity.start = {timestamp: 0, epoch: "SET"};
newActivity.duration = {timestamp: Number(activity.duration), epoch: "SET"};
newActivity.type = "activity";
newActivity.relationships = {modes: []};
activitiesObjects.push(newActivity);
newActivityMode.name = activity.name + ' Resources';
newActivityMode.resources = {comms: Number(activity.comms), power: Number(activity.power)};
newActivityMode.type = 'mode';
activityModesObjects.push(newActivityMode);
});
var folderComposition = this.createActivityModesFolder().getCapability('composition');
activityModesObjects.forEach(function (activityMode, index) {
var newActivityModeInstance = this.instantiate(activityMode, 'activity-mode-' + index);
newActivityModeInstance.getCapability('location').setPrimaryLocation('activity-modes-folder');
folderComposition.add(newActivityModeInstance);
}.bind(this));
activitiesObjects.forEach(function (activity, index) {
activity.relationships.modes.push('activity-mode-' + index);
activity.id = 'activity-' + index;
var newActivityInstance = this.instantiate(activity, 'activity-' + index);
newActivityInstance.getCapability('location').setPrimaryLocation(parentId);
parentComposition.add(newActivityInstance);
}.bind(this));
};
ActivityModesImportAction.prototype.createActivityModesFolder = function () {
var folderInstance = this.instantiate({name: 'Activity-Modes', type: 'folder', composition: []}, 'activity-modes-folder');
folderInstance.getCapability('location').setPrimaryLocation(this.parent.getId());
this.parent.getCapability('composition').add(folderInstance);
return folderInstance;
};
ActivityModesImportAction.prototype.displayError = function () {
var dialog,
perform = this.perform.bind(this),
model = {
title: "Invalid File",
actionText: "The selected file was not a valid CSV file",
severity: "error",
options: [
{
label: "Ok",
callback: function () {
dialog.dismiss();
perform();
}
}
]
};
dialog = this.dialogService.showBlockingMessage(model);
};
ActivityModesImportAction.prototype.getFormModel = function () {
return {
name: 'Import activities from CSV',
sections: [
{
name: 'Import A File',
rows: [
{
name: 'Select File',
key: 'selectFile',
control: 'file-input',
required: true,
text: 'Select File'
}
]
}
]
};
};
return ActivityModesImportAction;
});

View File

@@ -35,6 +35,10 @@ define([
key: 'local-format',
implementation: LocalTimeFormat
});
var indicator = openmct.indicators.create();
indicator.cssClass('something');
indicator.show(function showIndicator(element) {});
};
};
});

View File

@@ -30,7 +30,6 @@ define([
'../../platform/import-export/bundle',
'./summaryWidget/plugin',
'./URLIndicatorPlugin/URLIndicatorPlugin',
'./activityModes/plugin',
'./telemetryMean/plugin'
], function (
_,
@@ -42,7 +41,6 @@ define([
ImportExport,
SummaryWidget,
URLIndicatorPlugin,
ActivityModes,
TelemetryMean
) {
var bundleMap = {
@@ -130,8 +128,7 @@ define([
plugins.ExampleImagery = ExampleImagery;
plugins.SummaryWidget = SummaryWidget;
plugins.TelemetryMean = TelemetryMean;
plugins.URLIndicatorPlugin = URLIndicatorPlugin;
plugins.ActivityModes = ActivityModes;
plugins.URLIndicator = URLIndicatorPlugin;
return plugins;
});