Compare commits
13 Commits
vue-table-
...
style-guid
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91263b0f6d | ||
|
|
c458666173 | ||
|
|
e21906d1fd | ||
|
|
f2193495ec | ||
|
|
dd05f29210 | ||
|
|
b35be0c559 | ||
|
|
9e6a2de585 | ||
|
|
c7392db6f5 | ||
|
|
6ee4740f5f | ||
|
|
74401ed2de | ||
|
|
c4fd3bc997 | ||
|
|
55bac65cad | ||
|
|
ed327f5211 |
108
API.md
108
API.md
@@ -567,7 +567,7 @@ openmct.time.timeSystem(utcTimeSystem, bounds);
|
||||
Setting the active time system will trigger a [`'timeSystem'`](#time-events)
|
||||
event. If you supplied bounds, a [`'bounds'`](#time-events) event will be triggered afterwards with your newly supplied bounds.
|
||||
|
||||
### Time Bounds
|
||||
#### 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.
|
||||
@@ -591,7 +591,7 @@ openmct.time.bounds({start: now - ONE_HOUR, now);
|
||||
To respond to bounds change events, listen for the [`'bounds'`](#time-events)
|
||||
event.
|
||||
|
||||
## Clocks
|
||||
### 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
|
||||
@@ -610,7 +610,7 @@ 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
|
||||
#### Defining and registering clocks
|
||||
|
||||
A clock is an object that defines certain required metadata and functions:
|
||||
|
||||
@@ -724,7 +724,7 @@ __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
|
||||
### Time Events
|
||||
|
||||
The Time API is a standard event emitter; you can register callbacks for events using the `on` method and remove callbacks for events with the `off` method.
|
||||
|
||||
@@ -766,7 +766,7 @@ The events emitted by the Time API are:
|
||||
* `clockOffsets`: The new [clock offsets](#clock-offsets).
|
||||
|
||||
|
||||
## The Time Conductor
|
||||
### 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.
|
||||
@@ -856,6 +856,90 @@ openmct.install(openmct.plugins.Conductor({
|
||||
}));
|
||||
```
|
||||
|
||||
## Indicators
|
||||
|
||||
Indicators are small widgets that reside at the bottom of the screen and are visible from
|
||||
every screen in Open MCT. They can be used to convey system state using an icon and text.
|
||||
Indicators tend to be collapsed to an icon by default (though this behavior can be customized
|
||||
by defining a [custom indicator](#custom-indicators)), and hovering over them will reveal
|
||||
text providing more information.
|
||||
|
||||
### The URL Status Indicator
|
||||
|
||||
A common use case for indicators is to convey the state of some external system such as a
|
||||
persistence backend or HTTP server. So long as this system is accessible via http request,
|
||||
Open MCT provides a general purpose indicator to show whether the server is available and
|
||||
returing a 2xx status code. The URL Status Indicator is made available as a default plugin. See
|
||||
[Included Plugins](#included-plugins) below for details on how to install and configure the
|
||||
URL Status Indicator.
|
||||
|
||||
### Creating a New Indicator
|
||||
|
||||
A new indicator can be created with a simple API call, eg.
|
||||
|
||||
``` javascript
|
||||
var myIndicator = openmct.indicators.create();
|
||||
myIndicator.text("Hello World!");
|
||||
```
|
||||
|
||||
This will create a new indicator and add it to the bottom of the screen in Open MCT.
|
||||
By default, the indicator will appear as an information icon. Hovering over the icon will
|
||||
reveal the text set via the call to `.text()`. The Indicator object returned by the API
|
||||
call exposes a number of functions for customizing the content and appearance of the indicator:
|
||||
|
||||
* `.text([text])`: Gets or sets the text shown when the user hovers over the indicator.
|
||||
Accepts an __optional__ `string` argument that, if provided, will be used to set the text.
|
||||
Hovering over the indicator will expand it to its full size, revealing this text alongside
|
||||
the icon. Returns the currently set text as a `string`.
|
||||
* `.description([description])`: Gets or sets the indicator's description. Accepts an
|
||||
__optional__ `string` argument that, if provided, will be used to set the text. The description
|
||||
allows for more detail to be provided in a tooltip when the user hovers over the indicator.
|
||||
Returns the currently set text as a `string`.
|
||||
* `.iconClass([className])`: Gets or sets the CSS class used to define the icon. Accepts an __optional__
|
||||
`string` parameter to be used to set the class applied to the indicator. Any of
|
||||
[the built-in glyphs](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home/glyphs?view=styleguide.glyphs)
|
||||
may be used here, or a custom CSS class can be provided. Returns the currently defined CSS
|
||||
class as a `string`.
|
||||
* `.statusClass([className])`: Gets or sets the CSS class used to determine status. Accepts an __optional __
|
||||
`string` parameter to be used to set a status class applied to the indicator. May be used to apply
|
||||
different colors to indicate status.
|
||||
|
||||
### Custom Indicators
|
||||
|
||||
A completely custom indicator can be added by registering a factory function that produces
|
||||
a DOM element for your custom indicator. eg.
|
||||
|
||||
``` javascript
|
||||
openmct.indicators.create(function () {
|
||||
var domNode = document.createElement('div');
|
||||
domNode.innerText = new Date().toString();
|
||||
setInterval(function () {
|
||||
domNode.innerText = new Date().toString();
|
||||
}, 1000);
|
||||
return domNode;
|
||||
});
|
||||
```
|
||||
|
||||
### Priority
|
||||
|
||||
When creating a new indicator or defining a custom indicator, a `number` can optionally be
|
||||
provided that will determine the order that the indicator appears on the screen. An indicator
|
||||
with a higher `priority` number will be shown to the left of indicators with lower
|
||||
priority numbers. The lowest possible `priority` (and the default value if no `priority` is specified)
|
||||
is `Number.NEGATIVE_INFINTY`, and the highest possible priority is `Number.POSITIVE_INFINITY`.
|
||||
|
||||
eg.
|
||||
``` javascript
|
||||
var myIndicator = openmct.indicators.create(1);
|
||||
myIndicator.text("I'm on the left!");
|
||||
|
||||
openmct.indicators.create(0, function () {
|
||||
var domNode = document.createElement('div');
|
||||
domNode.innerText = "I'm on the right!";
|
||||
return domNode;
|
||||
});
|
||||
```
|
||||
|
||||
## Included Plugins
|
||||
|
||||
Open MCT is packaged along with a few general-purpose plugins:
|
||||
@@ -879,18 +963,18 @@ openmct.install(openmct.plugins.CouchDB('http://localhost:9200'))
|
||||
* `openmct.plugins.Espresso` and `openmct.plugins.Snow` are two different
|
||||
themes (dark and light) available for Open MCT. Note that at least one
|
||||
of these themes must be installed for Open MCT to appear correctly.
|
||||
* `openmct.plugins.URLIndicatorPlugin` adds an indicator which shows the
|
||||
* `openmct.plugins.URLIndicator` adds an indicator which shows the
|
||||
availability of a URL with the following options:
|
||||
- `url` : URL to indicate the status of
|
||||
- `cssClass`: Icon to show in the status bar, defaults to `icon-database`, [list of all icons](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home?view=items)
|
||||
- `iconClass`: Icon to show in the status bar, defaults to `icon-database`, [list of all icons](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home?view=items)
|
||||
- `interval`: Interval between checking the connection, defaults to `10000`
|
||||
- `label` Name showing up as text in the status bar, defaults to url
|
||||
```javascript
|
||||
openmct.install(openmct.plugins.URLIndicatorPlugin({
|
||||
url: 'http://google.com',
|
||||
cssClass: 'check',
|
||||
interval: 10000,
|
||||
label: 'Google'
|
||||
openmct.install(openmct.plugins.URLIndicator({
|
||||
url: 'http://localhost:8080',
|
||||
iconClass: 'check',
|
||||
interval: 10000,
|
||||
label: 'Localhost'
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
@@ -38,7 +38,8 @@ define([
|
||||
"provides": "identityService",
|
||||
"type": "provider",
|
||||
"depends": [
|
||||
"dialogService"
|
||||
"dialogService",
|
||||
"$q"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<span class="status block" ng-controller="DialogLaunchController">
|
||||
<span class="l-indicator s-indicator icon-box-with-arrow" ng-controller="DialogLaunchController">
|
||||
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
|
||||
<span class="status-indicator icon-box-with-arrow"></span><span class="label">
|
||||
<span class="label">
|
||||
<a ng-click="launchProgress(true)">Known</a> |
|
||||
<a ng-click="launchProgress(false)">Unknown</a> |
|
||||
<a ng-click="launchError()">Error</a> |
|
||||
<a ng-click="launchInfo()">Info</a>
|
||||
</span><span class="count"></span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<span class="status block" ng-controller="NotificationLaunchController">
|
||||
<span class="l-indicator s-indicator icon-bell" ng-controller="NotificationLaunchController">
|
||||
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
|
||||
<span class="status-indicator icon-bell"></span><span class="label">
|
||||
<span class="label">
|
||||
<a ng-click="newInfo()">Success</a> |
|
||||
<a ng-click="newError()">Error</a> |
|
||||
<a ng-click="newAlert()">Alert</a> |
|
||||
<a ng-click="newProgress()">Progress</a>
|
||||
</span><span class="count"></span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -129,6 +129,44 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="l-section">
|
||||
<h2>Status Bar Indicators</h2>
|
||||
<div class="cols cols1-1">
|
||||
<div class="col">
|
||||
<p>Indicators content goes here.</p>
|
||||
</div>
|
||||
<mct-example><div class="status-holder s-status-bar">
|
||||
<span class="status-block-holder">
|
||||
<span class="l-indicator s-indicator">
|
||||
<span class="status-indicator icon-bell"></span>
|
||||
<span class="label">Collapsible Indicator</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="status-block-holder no-collapse caution">
|
||||
<span class="l-indicator s-indicator">
|
||||
<span class="status-indicator icon-bell"></span>
|
||||
<span class="label">No collapse</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="status-holder s-status-bar">
|
||||
<span class="status-block-holder">
|
||||
<span class="l-indicator s-indicator">
|
||||
<span class="status-indicator icon-bell"></span>
|
||||
<span class="label">Collapsible Indicator</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="status-block-holder">
|
||||
<span class="status block s-status-info icon-info">
|
||||
<span class="label">No collapse</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</mct-example>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="l-section">
|
||||
<h2>Synchronization</h2>
|
||||
<div class="cols cols1-1">
|
||||
|
||||
@@ -54,7 +54,7 @@ define(
|
||||
return "icon-object-unknown";
|
||||
},
|
||||
getText: function () {
|
||||
return latest;
|
||||
return "" + latest;
|
||||
},
|
||||
getDescription: function () {
|
||||
return "";
|
||||
|
||||
@@ -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,11 +48,12 @@ 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",
|
||||
"text!./res/templates/controls/input-filter.html",
|
||||
"text!./res/templates/indicator.html",
|
||||
"text!./res/templates/angular-indicator.html",
|
||||
"text!./res/templates/message-banner.html",
|
||||
"text!./res/templates/progress-bar.html",
|
||||
"text!./res/templates/controls/time-controller.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": [
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
@import "controls/lists";
|
||||
@import "controls/menus";
|
||||
@import "controls/messages";
|
||||
@import "controls/indicators";
|
||||
@import "mobile/controls/menus";
|
||||
|
||||
/********************************* FORMS */
|
||||
|
||||
@@ -20,13 +20,15 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*************************************************** MIXINS */
|
||||
@mixin formulateStatusColors($c) {
|
||||
@mixin elementStatusColors($c) {
|
||||
// Sets bg and icon colors for elements
|
||||
background: rgba($c, 0.4) !important;
|
||||
&:before { color: $c !important; }
|
||||
}
|
||||
|
||||
|
||||
@mixin indicatorStatusColors($c) {
|
||||
&:before, .count { color: $c; }
|
||||
}
|
||||
|
||||
/*************************************************** GENERAL */
|
||||
.s-limit-yellow,
|
||||
@@ -54,14 +56,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************** LIMITS */
|
||||
.s-limit-yellow, .s-limit-yellow-icon {
|
||||
@include formulateStatusColors($colorWarningLo);
|
||||
@include elementStatusColors($colorWarningLo);
|
||||
}
|
||||
|
||||
.s-limit-red, .s-limit-red-icon {
|
||||
@include formulateStatusColors($colorWarningHi);
|
||||
@include elementStatusColors($colorWarningHi);
|
||||
}
|
||||
|
||||
.s-limit-upr:before { content: $glyph-icon-arrow-double-up; }
|
||||
@@ -70,11 +71,11 @@
|
||||
.s-limit-red-icon:before { content: $glyph-icon-alert-triangle; }
|
||||
|
||||
/*************************************************** STATUS */
|
||||
.s-status-warning-hi, .s-status-warning-hi-icon { @include formulateStatusColors($colorWarningHi); }
|
||||
.s-status-warning-lo, .s-status-warning-lo-icon { @include formulateStatusColors($colorWarningLo); }
|
||||
.s-status-diagnostic, .s-status-diagnostic-icon { @include formulateStatusColors($colorDiagnostic); }
|
||||
.s-status-info, .s-status-info-icon { @include formulateStatusColors($colorInfo); }
|
||||
.s-status-ok, .s-status-ok-icon { @include formulateStatusColors($colorOk); }
|
||||
.s-status-warning-hi, .s-status-warning-hi-icon { @include elementStatusColors($colorWarningHi); }
|
||||
.s-status-warning-lo, .s-status-warning-lo-icon { @include elementStatusColors($colorWarningLo); }
|
||||
.s-status-diagnostic, .s-status-diagnostic-icon { @include elementStatusColors($colorDiagnostic); }
|
||||
.s-status-info, .s-status-info-icon { @include elementStatusColors($colorInfo); }
|
||||
.s-status-ok, .s-status-ok-icon { @include elementStatusColors($colorOk); }
|
||||
|
||||
.s-status-warning-hi-icon:before { content: $glyph-icon-alert-triangle; }
|
||||
.s-status-warning-lo-icon:before { content: $glyph-icon-alert-rect; }
|
||||
@@ -82,4 +83,25 @@
|
||||
.s-status-info-icon:before { content: $glyph-icon-info; }
|
||||
.s-status-ok-icon:before { content: $glyph-icon-check; }
|
||||
|
||||
/*************************************************** INDICATORS */
|
||||
.s-indicator-status-info {
|
||||
@include indicatorStatusColors($colorInfo);
|
||||
}
|
||||
.s-indicator-status-ok {
|
||||
@include indicatorStatusColors($colorOk);
|
||||
}
|
||||
.s-indicator-status-caution, .s-indicator-status-warning, .s-indicator-status-alert {
|
||||
@include indicatorStatusColors($colorStatusAlert);
|
||||
}
|
||||
.s-indicator-status-error, .s-indicator-status-err {
|
||||
@include indicatorStatusColors($colorStatusError);
|
||||
}
|
||||
.s-indicator-status-available {
|
||||
@include indicatorStatusColors($colorStatusAvailable);
|
||||
}
|
||||
.s-indicator-status-subdued {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
99
platform/commonUI/general/res/sass/controls/_indicators.scss
Normal file
99
platform/commonUI/general/res/sass/controls/_indicators.scss
Normal file
@@ -0,0 +1,99 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Indicators are generally only displayed in the ue-bottom-bar element of the main interface */
|
||||
|
||||
.l-indicator {
|
||||
$transDelayHover: 1.5s;
|
||||
$transDelayWhileExpanded: 2.5s;
|
||||
$transSpeed: .25s;
|
||||
display: inline-block;
|
||||
margin-right: $interiorMarginSm;
|
||||
|
||||
&:before {
|
||||
// Icon
|
||||
display: inline-block;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.label,
|
||||
.count {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
&.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
&.no-icon {
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.no-collapse) {
|
||||
.label {
|
||||
// Max-width silliness is necessary for width transition
|
||||
@include trans-prop-nice((max-width, margin-right), $transSpeed, $transDelayWhileExpanded);
|
||||
overflow: hidden;
|
||||
margin-right: 0;
|
||||
max-width: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
&:hover {
|
||||
&:before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.label {
|
||||
@include trans-prop-nice((max-width, margin-right), 0s);
|
||||
margin-right: $interiorMargin;
|
||||
max-width: 600px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.count {
|
||||
@include trans-prop-nice(max-width, 0s);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.count {
|
||||
@include trans-prop-nice(opacity, $transSpeed, $transDelayWhileExpanded);
|
||||
font-weight: bold;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.s-button {
|
||||
background: $colorStatusBtnBg;
|
||||
padding: 0 $interiorMargin;
|
||||
height: auto;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.s-indicator {
|
||||
color: $colorStatusDefault;
|
||||
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/******************************************************************* STATUS BLOCK ELEMS */
|
||||
|
||||
@mixin statusBannerColors($bg, $fg: $colorStatusFg) {
|
||||
$bgPb: 30%;
|
||||
$bgPbD: 10%;
|
||||
@@ -36,110 +36,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Status coloring
|
||||
.ok, .info {
|
||||
.status-indicator {
|
||||
color: $colorInfo;
|
||||
}
|
||||
}
|
||||
|
||||
.alert, .caution, .warning {
|
||||
.status-indicator, .count {
|
||||
color: $colorStatusAlert;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.error, .err {
|
||||
.status-indicator, .count {
|
||||
color: $colorStatusError;
|
||||
}
|
||||
}
|
||||
|
||||
.available {
|
||||
.status-indicator, .count {
|
||||
color: $colorStatusAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
.subdued {
|
||||
.status-indicator {
|
||||
color: pullForward($colorStatusBarBg, 40%);
|
||||
}
|
||||
}
|
||||
|
||||
.status-block-holder {
|
||||
// Applied to mct-include element
|
||||
// Contains status.block elements
|
||||
$transDelay: 1.5s;
|
||||
$transSpeed: .25s;
|
||||
display: inline-block;
|
||||
&.clickable { cursor: pointer; }
|
||||
&:not(.clickable) { cursor: default; }
|
||||
&.no-icon .status.block {
|
||||
.status-indicator {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.float-right {
|
||||
float: right;
|
||||
}
|
||||
&:not(.no-collapse) .status.block {
|
||||
.label {
|
||||
// Max-width silliness is necessary for width transition
|
||||
@include trans-prop-nice(max-width, $transSpeed, $transDelay);
|
||||
overflow: hidden;
|
||||
max-width: 0px;
|
||||
}
|
||||
&:hover {
|
||||
.label {
|
||||
@include trans-prop-nice(max-width, $transSpeed, 0s);
|
||||
max-width: 600px;
|
||||
width: auto;
|
||||
}
|
||||
.count {
|
||||
@include trans-prop-nice(max-width, $transSpeed, 0s);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.status.block {
|
||||
$transDelay: 1.5s;
|
||||
$transSpeed: .25s;
|
||||
color: $colorStatusDefault;
|
||||
display: inline-block;
|
||||
margin-right: $interiorMargin;
|
||||
.status-indicator,
|
||||
.label,
|
||||
.count {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
background: none !important;
|
||||
margin-right: $interiorMarginSm;
|
||||
&[class*='s-status']:before {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.count {
|
||||
@include trans-prop-nice(opacity, $transSpeed, $transDelay);
|
||||
font-weight: bold;
|
||||
opacity: 1;
|
||||
}
|
||||
.s-button {
|
||||
background: $colorStatusBtnBg;
|
||||
padding: 0 $interiorMargin;
|
||||
height: auto;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************* MESSAGE BANNERS */
|
||||
.message {
|
||||
&.block {
|
||||
|
||||
@@ -81,16 +81,14 @@
|
||||
@include absPosDefault(0);// New status bar design
|
||||
top: auto;
|
||||
height: $ueFooterH;
|
||||
line-height: $ueFooterH - ($interiorMargin * 2);
|
||||
background: $colorStatusBarBg;
|
||||
color: lighten($colorBodyBg, 30%);
|
||||
font-size: .7rem;
|
||||
.status-holder {
|
||||
|
||||
mct-indicators { display: block; }
|
||||
|
||||
.indicator-holder {
|
||||
box-sizing: border-box;
|
||||
@include absPosDefault($interiorMargin);
|
||||
@include ellipsize();
|
||||
right: 120px;
|
||||
text-transform: uppercase;
|
||||
z-index: 1;
|
||||
}
|
||||
.app-logo {
|
||||
@@ -105,6 +103,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.s-status-bar {
|
||||
background: $colorStatusBarBg;
|
||||
color: lighten($colorBodyBg, 30%);
|
||||
font-size: .7rem;
|
||||
line-height: $ueFooterH - ($interiorMargin * 2);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.edit-mode {
|
||||
// Old edit mode
|
||||
.split-layout {
|
||||
|
||||
@@ -20,14 +20,12 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
|
||||
<div class='status block'
|
||||
<div class='l-indicator s-indicator s-indicator-status-{{ngModel.getGlyphClass()}}'
|
||||
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()'>
|
||||
ng-show="ngModel.getText().length > 0"
|
||||
ng-class="ngModel.getCssClass()">
|
||||
<span class="label" ng-class='ngModel.getTextClass()'>
|
||||
{{ngModel.getText()}}
|
||||
<a class="s-button icon-gear" ng-if="ngModel.configure"></a>
|
||||
</span><span class="count">
|
||||
</span>
|
||||
</div>
|
||||
@@ -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 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>
|
||||
<div class='abs bottom-bar ue-bottom-bar s-status-bar mobile-disable-select'>
|
||||
<div id='status' class='indicator-holder'>
|
||||
<mct-indicators></mct-indicators>
|
||||
</div>
|
||||
<mct-include key="'message-banner'"></mct-include>
|
||||
<mct-include key="'about-logo'"></mct-include>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@@ -23,37 +23,20 @@
|
||||
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) {
|
||||
openmct.indicators.allIndicatorElements().then(function (elements) {
|
||||
elements.forEach(function (indicatorElement) {
|
||||
element.append(indicatorElement);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
);
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,9 +1,7 @@
|
||||
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
|
||||
<a ng-click="showNotificationsList()" ng-show="notifications.length > 0" class="status block"
|
||||
ng-class="highest.severity"
|
||||
<a ng-click="showNotificationsList()" ng-show="notifications.length > 0" class="l-indicator s-indicator s-indicator-status-{{highest.severity}} icon-bell"
|
||||
ng-controller="NotificationIndicatorController">
|
||||
<span class="status-indicator icon-bell"></span><span class="label">
|
||||
{{notifications.length}} Notifications
|
||||
<span class="label">
|
||||
{{notifications.length}} Notification<span ng-show="notifications.length > 1">s</span>
|
||||
</span><span class="count">{{notifications.length}}</span>
|
||||
|
||||
</a>
|
||||
|
||||
@@ -55,7 +55,7 @@ $colorTransLucBg: #666; // Used as a visual blocking element over variable backg
|
||||
|
||||
// Foundation Colors
|
||||
$colorAlt1: #ffc700;
|
||||
$colorAlert: #ff3c00;
|
||||
$colorAlert: #ff6600;
|
||||
$colorWarningHi: #cc0000;
|
||||
$colorWarningLo: #ff9900;
|
||||
$colorDiagnostic: #a4b442;
|
||||
@@ -114,10 +114,10 @@ $colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
|
||||
|
||||
// Status colors, mainly used for messaging and item ancillary symbols
|
||||
$colorStatusFg: #ccc;
|
||||
$colorStatusDefault: #ccc;
|
||||
$colorStatusDefault: #999;
|
||||
$colorStatusInfo: $colorInfo;
|
||||
$colorStatusAlert: $colorAlert;
|
||||
$colorStatusError: #d4585c;
|
||||
$colorStatusError: #ff3300;
|
||||
$colorStatusAvailable: $colorKey;
|
||||
$colorStatusBtnBg: $colorBtnBg;
|
||||
$colorProgressBarOuter: rgba(#000, 0.1);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -45,11 +45,11 @@ define(
|
||||
}
|
||||
|
||||
ClockIndicator.prototype.getGlyphClass = function () {
|
||||
return "no-collapse float-right subdued";
|
||||
return "subdued";
|
||||
};
|
||||
|
||||
ClockIndicator.prototype.getCssClass = function () {
|
||||
return "icon-clock";
|
||||
return "icon-clock no-collapse float-right";
|
||||
};
|
||||
|
||||
ClockIndicator.prototype.getText = function () {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, United States Government
|
||||
* Open MCT, Copyright (c) 2009-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@@ -20,38 +20,32 @@
|
||||
* 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;
|
||||
/**
|
||||
* 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.simpleIndicator();
|
||||
var timer = timerService.getTimer();
|
||||
setIndicatorStatus(timer);
|
||||
|
||||
function setIndicatorStatus(newTimer) {
|
||||
if (newTimer !== undefined) {
|
||||
indicator.iconClass('icon-timer');
|
||||
indicator.statusClass('s-status-ok');
|
||||
indicator.text('Following timer ' + newTimer.name);
|
||||
} else {
|
||||
indicator.iconClass('icon-timer');
|
||||
indicator.statusClass('');
|
||||
indicator.text('No timer being followed');
|
||||
}
|
||||
}
|
||||
|
||||
FollowIndicator.prototype.getGlyphClass = function () {
|
||||
return "";
|
||||
};
|
||||
timerService.on('change', setIndicatorStatus);
|
||||
|
||||
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;
|
||||
}
|
||||
);
|
||||
openmct.indicators.add(indicator);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, United States Government
|
||||
* Open MCT, Copyright (c) 2009-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@@ -20,39 +20,77 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(["../../src/indicators/FollowIndicator"], function (FollowIndicator) {
|
||||
var TIMER_SERVICE_METHODS =
|
||||
['setTimer', 'getTimer', 'clearTimer', 'on', 'off'];
|
||||
|
||||
define([
|
||||
"../../src/indicators/FollowIndicator",
|
||||
"../../src/services/TimerService",
|
||||
"../../../../../src/MCT",
|
||||
'zepto'
|
||||
], function (
|
||||
FollowIndicator,
|
||||
TimerService,
|
||||
MCT,
|
||||
$
|
||||
) {
|
||||
describe("The timer-following indicator", function () {
|
||||
var mockTimerService;
|
||||
var indicator;
|
||||
var timerService;
|
||||
var openmct;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimerService =
|
||||
jasmine.createSpyObj('timerService', TIMER_SERVICE_METHODS);
|
||||
indicator = new FollowIndicator(mockTimerService);
|
||||
openmct = new MCT();
|
||||
timerService = new TimerService(openmct);
|
||||
spyOn(openmct.indicators, "add");
|
||||
});
|
||||
|
||||
it("implements the Indicator interface", function () {
|
||||
expect(indicator.getGlyphClass()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getCssClass()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getText()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getDescription()).toEqual(jasmine.any(String));
|
||||
it("adds an indicator when installed", function () {
|
||||
FollowIndicator(openmct, timerService);
|
||||
expect(openmct.indicators.add).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("indicates that no timer is being followed", function () {
|
||||
FollowIndicator(openmct, timerService);
|
||||
var simpleIndicator = openmct.indicators.add.mostRecentCall.args[0];
|
||||
var element = simpleIndicator.element;
|
||||
var text = $('.indicator-text', element).text().trim();
|
||||
expect(text).toEqual('No timer being followed');
|
||||
});
|
||||
|
||||
describe("when a timer is set", function () {
|
||||
var testObject;
|
||||
var simpleIndicator;
|
||||
|
||||
beforeEach(function () {
|
||||
testObject = { name: "some timer!" };
|
||||
mockTimerService.getTimer.andReturn(testObject);
|
||||
testObject = {
|
||||
identifier: {
|
||||
namespace: 'namespace',
|
||||
key: 'key'
|
||||
},
|
||||
name: "some timer!"
|
||||
};
|
||||
timerService.setTimer(testObject);
|
||||
FollowIndicator(openmct, timerService);
|
||||
simpleIndicator = openmct.indicators.add.mostRecentCall.args[0];
|
||||
});
|
||||
|
||||
it("displays the timer's name", function () {
|
||||
expect(indicator.getText().indexOf(testObject.name))
|
||||
.not.toEqual(-1);
|
||||
var element = simpleIndicator.element;
|
||||
var text = $('.indicator-text', element).text().trim();
|
||||
expect(text).toEqual('Following timer ' + testObject.name);
|
||||
});
|
||||
|
||||
it("displays the timer's name when it changes", function () {
|
||||
var secondTimer = {
|
||||
identifier: {
|
||||
namespace: 'namespace',
|
||||
key: 'key2'
|
||||
},
|
||||
name: "Some other timer"
|
||||
};
|
||||
var element = simpleIndicator.element;
|
||||
timerService.setTimer(secondTimer);
|
||||
var text = $('.indicator-text', element).text().trim();
|
||||
expect(text).toEqual('Following timer ' + secondTimer.name);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
11
src/MCT.js
11
src/MCT.js
@@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@@ -194,6 +194,15 @@ define([
|
||||
*/
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
});
|
||||
|
||||
129
src/api/indicators/IndicatorAPI.js
Normal file
129
src/api/indicators/IndicatorAPI.js
Normal file
@@ -0,0 +1,129 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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([
|
||||
'./SimpleIndicator',
|
||||
'../../../platform/framework/src/Constants',
|
||||
'lodash'
|
||||
], function (
|
||||
SimpleIndicator,
|
||||
Constants,
|
||||
_
|
||||
) {
|
||||
/* jshint validthis: true */
|
||||
var LEGACY_INDICATOR_TEMPLATE =
|
||||
'<mct-include ' +
|
||||
' ng-model="indicator" ' +
|
||||
' key="template" ' +
|
||||
' </mct-include>';
|
||||
|
||||
function IndicatorAPI(openmct) {
|
||||
this.openmct = openmct;
|
||||
this.indicatorElements = [];
|
||||
this.promiseForAllElements =
|
||||
fetchLegacyIndicators.call(this)
|
||||
.then(addLegacyIndicators.bind(this))
|
||||
.then(resolveWithAllIndicatorElements.bind(this));
|
||||
}
|
||||
|
||||
IndicatorAPI.prototype.simpleIndicator = function () {
|
||||
return new SimpleIndicator(this.openmct);
|
||||
};
|
||||
|
||||
/**
|
||||
* Accepts an indicator object, which is a simple object
|
||||
* with a single attribute, 'element' which has an HTMLElement
|
||||
* as its value.
|
||||
*
|
||||
* We provide .simpleIndicator() as a convenience function
|
||||
* which will create a default Open MCT indicator that can
|
||||
* be passed to .add(indicator). This indicator also exposes
|
||||
* functions for changing its appearance to support customization
|
||||
* and dynamic behavior.
|
||||
*
|
||||
* Eg.
|
||||
* var myIndicator = openmct.indicators.simpleIndicator();
|
||||
* openmct.indicators.add(myIndicator);
|
||||
*
|
||||
* myIndicator.text("Hello World!");
|
||||
* myIndicator.iconClass("icon-info");
|
||||
*
|
||||
*/
|
||||
IndicatorAPI.prototype.add = function (indicator) {
|
||||
// So that we can consistently position indicator elements,
|
||||
// guarantee that they are wrapped in an element we control
|
||||
var wrapperNode = document.createElement('div');
|
||||
wrapperNode.className = 'l-indicator s-indicator';
|
||||
wrapperNode.appendChild(indicator.element);
|
||||
this.indicatorElements.push(wrapperNode);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
IndicatorAPI.prototype.allIndicatorElements = function () {
|
||||
return this.promiseForAllElements;
|
||||
};
|
||||
|
||||
function fetchLegacyIndicators() {
|
||||
return new Promise(function (resolve) {
|
||||
this.openmct.legacyExtension('runs', {
|
||||
depends: ['indicators[]'],
|
||||
implementation: resolve
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
function addLegacyIndicators(legacyIndicators) {
|
||||
legacyIndicators.forEach(function (legacyIndicatorDef) {
|
||||
var legacyIndicator = initializeIfNeeded(legacyIndicatorDef);
|
||||
var legacyIndicatorElement = buildLegacyIndicator(this.openmct, legacyIndicator, legacyIndicatorDef.template);
|
||||
this.indicatorElements.push(legacyIndicatorElement);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
function initializeIfNeeded(LegacyIndicatorDef) {
|
||||
var legacyIndicator;
|
||||
if (typeof LegacyIndicatorDef === 'function') {
|
||||
legacyIndicator = new LegacyIndicatorDef();
|
||||
} else {
|
||||
legacyIndicator = LegacyIndicatorDef;
|
||||
}
|
||||
return legacyIndicator;
|
||||
}
|
||||
|
||||
function buildLegacyIndicator(openmct, legacyIndicator, template) {
|
||||
var $compile = openmct.$injector.get('$compile');
|
||||
var $rootScope = openmct.$injector.get('$rootScope');
|
||||
var scope = $rootScope.$new(true);
|
||||
scope.indicator = legacyIndicator;
|
||||
scope.template = template || 'indicator';
|
||||
|
||||
return $compile(LEGACY_INDICATOR_TEMPLATE)(scope)[0];
|
||||
}
|
||||
|
||||
function resolveWithAllIndicatorElements() {
|
||||
return this.indicatorElements;
|
||||
}
|
||||
|
||||
return IndicatorAPI;
|
||||
|
||||
});
|
||||
214
src/api/indicators/IndicatorAPISpec.js
Normal file
214
src/api/indicators/IndicatorAPISpec.js
Normal file
@@ -0,0 +1,214 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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(
|
||||
[
|
||||
"../../MCT",
|
||||
"../../../platform/commonUI/general/src/directives/MCTIndicators",
|
||||
"zepto"
|
||||
],
|
||||
function (
|
||||
MCT,
|
||||
MCTIndicators,
|
||||
$
|
||||
) {
|
||||
describe("The Indicator API", function () {
|
||||
var openmct;
|
||||
var directive;
|
||||
var holderElement;
|
||||
var legacyExtensionFunction = MCT.prototype.legacyExtension;
|
||||
var legacyIndicatorsResolved = false;
|
||||
var legacyIndicatorsCallback;
|
||||
|
||||
beforeEach(function () {
|
||||
mockLegacyExtensionFunction();
|
||||
|
||||
openmct = new MCT();
|
||||
directive = new MCTIndicators(openmct);
|
||||
holderElement = document.createElement('div');
|
||||
|
||||
mockAngularComponents();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
MCT.prototype.legacyExtension = legacyExtensionFunction;
|
||||
});
|
||||
|
||||
it("Displays any legacy indicators ", function () {
|
||||
var legacyIndicators = [{},{},{},{}];
|
||||
|
||||
mockLegacyIndicatorsWith(legacyIndicators);
|
||||
|
||||
renderIndicators();
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve, 1000);
|
||||
runs(function () {
|
||||
expectIndicatorsShownToBe(legacyIndicators.length);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("If legacy indicator is defined as a constructor function, executes function ", function () {
|
||||
var mockConstructorFunction = jasmine.createSpy('mockIndicatorConstructor');
|
||||
var legacyIndicators = [{}, mockConstructorFunction];
|
||||
|
||||
mockConstructorFunction.andReturn({});
|
||||
mockLegacyIndicatorsWith(legacyIndicators);
|
||||
renderIndicators();
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve, 1000);
|
||||
runs(function () {
|
||||
expectIndicatorsShownToBe(legacyIndicators.length);
|
||||
expect(mockConstructorFunction).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("The simple indicator", function () {
|
||||
var simpleIndicator;
|
||||
|
||||
beforeEach(function () {
|
||||
simpleIndicator = openmct.indicators.simpleIndicator();
|
||||
mockLegacyIndicatorsWith([]);
|
||||
openmct.indicators.add(simpleIndicator);
|
||||
renderIndicators();
|
||||
});
|
||||
it("applies the set icon class", function () {
|
||||
simpleIndicator.iconClass('testIconClass');
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve);
|
||||
runs(function () {
|
||||
expect(getIconElement().hasClass('testIconClass')).toBe(true);
|
||||
});
|
||||
});
|
||||
it("applies the set status class", function () {
|
||||
simpleIndicator.statusClass('testStatusClass');
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve);
|
||||
runs(function () {
|
||||
expect(getIconElement().hasClass('testStatusClass')).toBe(true);
|
||||
});
|
||||
});
|
||||
it("displays the set text", function () {
|
||||
simpleIndicator.text('some test text');
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve);
|
||||
runs(function () {
|
||||
expect(getTextElement().text().trim()).toEqual('some test text');
|
||||
});
|
||||
});
|
||||
it("sets the indicator's title", function () {
|
||||
simpleIndicator.description('a test description');
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve);
|
||||
runs(function () {
|
||||
expect(getIndicatorElement().attr('title')).toEqual('a test description');
|
||||
});
|
||||
});
|
||||
|
||||
it("Hides indicator text if no text is set", function () {
|
||||
simpleIndicator.text('');
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve);
|
||||
runs(function () {
|
||||
expect(getIndicatorElement().hasClass('hidden')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Supports registration of a completely custom indicator", function () {
|
||||
var customIndicator = $('<div class="customIndicator">A custom indicator</div>')[0];
|
||||
mockLegacyIndicatorsWith([]);
|
||||
openmct.indicators.add({element: customIndicator});
|
||||
renderIndicators();
|
||||
|
||||
waitsFor(legacyIndicatorsToResolve);
|
||||
runs(function () {
|
||||
expect($('.customIndicator', holderElement).text().trim()).toEqual('A custom indicator');
|
||||
});
|
||||
});
|
||||
|
||||
function mockLegacyExtensionFunction() {
|
||||
spyOn(MCT.prototype, "legacyExtension");
|
||||
MCT.prototype.legacyExtension.andCallFake(function (extensionName, definition) {
|
||||
if (extensionName === 'runs') {
|
||||
legacyIndicatorsCallback = definition.implementation;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function mockAngularComponents() {
|
||||
var mockInjector = jasmine.createSpyObj('$injector', ['get']);
|
||||
var mockCompile = jasmine.createSpy('$compile');
|
||||
var mockRootScope = jasmine.createSpyObj('rootScope', ['$new']);
|
||||
var mockScope = {};
|
||||
|
||||
mockRootScope.$new.andReturn(mockScope);
|
||||
mockInjector.get.andCallFake(function (service) {
|
||||
return {
|
||||
'$compile': mockCompile,
|
||||
'$rootScope': mockRootScope
|
||||
}[service];
|
||||
});
|
||||
openmct.$injector = mockInjector;
|
||||
mockCompile.andCallFake(function () {
|
||||
return function () {
|
||||
return $('<div></div>');
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function renderIndicators() {
|
||||
directive.link({}, holderElement);
|
||||
}
|
||||
|
||||
function mockLegacyIndicatorsWith(legacyIndicators) {
|
||||
legacyIndicatorsResolved = false;
|
||||
|
||||
openmct.indicators.allIndicatorElements().then(function () {
|
||||
legacyIndicatorsResolved = true;
|
||||
});
|
||||
|
||||
legacyIndicatorsCallback(legacyIndicators);
|
||||
}
|
||||
|
||||
function legacyIndicatorsToResolve() {
|
||||
return legacyIndicatorsResolved;
|
||||
}
|
||||
|
||||
function expectIndicatorsShownToBe(number) {
|
||||
expect(holderElement.children.length).toBe(number);
|
||||
}
|
||||
|
||||
function getIconElement() {
|
||||
return $('.indicator-icon', holderElement);
|
||||
}
|
||||
|
||||
function getIndicatorElement() {
|
||||
return $('.status', holderElement);
|
||||
}
|
||||
|
||||
function getTextElement() {
|
||||
return $('.indicator-text', holderElement);
|
||||
}
|
||||
});
|
||||
});
|
||||
100
src/api/indicators/SimpleIndicator.js
Normal file
100
src/api/indicators/SimpleIndicator.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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) {
|
||||
var DEFAULT_ICON_CLASS = 'icon-info';
|
||||
|
||||
function SimpleIndicator(openmct) {
|
||||
this.openmct = openmct;
|
||||
this.textValue = 'New Indicator';
|
||||
this.descriptionValue = 'A simple indicator';
|
||||
this.iconClassValue = DEFAULT_ICON_CLASS;
|
||||
this.statusClassValue = '';
|
||||
|
||||
// We need to remove this element
|
||||
this.element = document.createElement('div');
|
||||
this.element.className = 'status-block-holder';
|
||||
|
||||
SimpleIndicator.defaultDisplayFunction.call(this);
|
||||
}
|
||||
|
||||
SimpleIndicator.prototype.text = function (text) {
|
||||
if (text !== undefined && text !== this.textValue) {
|
||||
this.textValue = text;
|
||||
SimpleIndicator.defaultDisplayFunction.call(this);
|
||||
}
|
||||
|
||||
return this.textValue;
|
||||
};
|
||||
|
||||
SimpleIndicator.prototype.description = function (description) {
|
||||
if (description !== undefined && description !== this.descriptionValue) {
|
||||
this.descriptionValue = description;
|
||||
SimpleIndicator.defaultDisplayFunction.call(this);
|
||||
}
|
||||
|
||||
return this.descriptionValue;
|
||||
};
|
||||
|
||||
SimpleIndicator.prototype.iconClass = function (iconClass) {
|
||||
if (iconClass !== undefined && iconClass !== this.iconClassValue) {
|
||||
this.iconClassValue = iconClass;
|
||||
SimpleIndicator.defaultDisplayFunction.call(this);
|
||||
}
|
||||
|
||||
return this.iconClassValue;
|
||||
};
|
||||
|
||||
SimpleIndicator.prototype.statusClass = function (statusClass) {
|
||||
if (statusClass !== undefined && statusClass !== this.statusClassValue) {
|
||||
this.statusClassValue = statusClass;
|
||||
SimpleIndicator.defaultDisplayFunction.call(this);
|
||||
}
|
||||
|
||||
return this.statusClassValue;
|
||||
};
|
||||
|
||||
function hideOrShowText(text) {
|
||||
if (text && text.length > 0) {
|
||||
return '';
|
||||
} else {
|
||||
return 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
SimpleIndicator.defaultDisplayFunction = function () {
|
||||
var html = indicatorTemplate
|
||||
.replace('{{indicator.text}}', this.text())
|
||||
.replace('{{indicator.iconClass}}', this.iconClass())
|
||||
.replace('{{indicator.statusClass}}', this.statusClass())
|
||||
.replace('{{indicator.description}}', this.description())
|
||||
.replace('{{hideOrShowText}}', hideOrShowText(this.text()));
|
||||
|
||||
this.element.innerHTML = html;
|
||||
|
||||
return this.element;
|
||||
};
|
||||
|
||||
return SimpleIndicator;
|
||||
}
|
||||
);
|
||||
24
src/api/indicators/res/indicator-template.html
Normal file
24
src/api/indicators/res/indicator-template.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, 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.
|
||||
-->
|
||||
<span class="{{hideOrShowText}} {{indicator.iconClass}} {{indicator.statusClass}}" title="{{indicator.description}}">
|
||||
<span class="label indicator-text">{{indicator.text}}</span>
|
||||
</span>
|
||||
@@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@@ -21,8 +21,8 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
['zepto'],
|
||||
function ($) {
|
||||
|
||||
// Set of connection states; changing among these states will be
|
||||
// reflected in the indicator's appearance.
|
||||
@@ -30,68 +30,86 @@ define(
|
||||
// DISCONNECTED: HTTP failed; maybe misconfigured, disconnected.
|
||||
// PENDING: Still trying to connect, and haven't failed yet.
|
||||
var CONNECTED = {
|
||||
glyphClass: "ok"
|
||||
statusClass: "s-status-ok"
|
||||
},
|
||||
PENDING = {
|
||||
glyphClass: 'caution'
|
||||
statusClass: "s-status-warning-lo"
|
||||
},
|
||||
DISCONNECTED = {
|
||||
glyphClass: "err"
|
||||
statusClass: "s-status-warning-hi"
|
||||
};
|
||||
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, simpleIndicator) {
|
||||
this.bindMethods();
|
||||
this.count = 0;
|
||||
|
||||
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 = simpleIndicator;
|
||||
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.statusClass(state.statusClass);
|
||||
};
|
||||
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
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
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.interval || 10000;
|
||||
this.indicator.iconClass(options.iconClass || 'icon-connectivity');
|
||||
};
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
@@ -1,20 +1,35 @@
|
||||
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"]
|
||||
});
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, 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(['./URLIndicator'],
|
||||
function URLIndicatorPlugin(URLIndicator) {
|
||||
return function (opts) {
|
||||
return function install(openmct) {
|
||||
var simpleIndicator = openmct.indicators.simpleIndicator();
|
||||
var urlIndicator = new URLIndicator(opts, openmct, simpleIndicator);
|
||||
|
||||
openmct.indicators.add(simpleIndicator);
|
||||
|
||||
return urlIndicator;
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@@ -21,138 +21,167 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["./URLIndicator"],
|
||||
function (URLIndicator) {
|
||||
|
||||
[
|
||||
"./URLIndicator",
|
||||
"./URLIndicatorPlugin",
|
||||
"../../MCT",
|
||||
"zepto"
|
||||
],
|
||||
function (
|
||||
URLIndicator,
|
||||
URLIndicatorPlugin,
|
||||
MCT,
|
||||
$
|
||||
) {
|
||||
var defaultPrototypeFunction = URLIndicator.prototype.get;
|
||||
describe("The URLIndicator", function () {
|
||||
var mockHttp,
|
||||
mockInterval,
|
||||
mockPromise,
|
||||
opts,
|
||||
Indicator,
|
||||
indicatorWrapper;
|
||||
var openmct;
|
||||
var indicatorElement;
|
||||
var urlIndicator;
|
||||
var mockHttpRequestFunction;
|
||||
var returned;
|
||||
var options;
|
||||
|
||||
beforeEach(function () {
|
||||
mockHttp = jasmine.createSpyObj("$http", ["get"]);
|
||||
mockInterval = jasmine.createSpy("$interval");
|
||||
mockPromise = jasmine.createSpyObj("promise", ["then"]);
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
interval: 1337 //some number
|
||||
};
|
||||
mockHttp.get.andReturn(mockPromise);
|
||||
Indicator = function () {
|
||||
this.options = opts;
|
||||
URLIndicator.call(this, mockHttp, mockInterval);
|
||||
};
|
||||
Indicator.prototype = Object.create(URLIndicator.prototype);
|
||||
indicatorWrapper = new Indicator();
|
||||
});
|
||||
it("polls for changes", function () {
|
||||
expect(mockInterval).toHaveBeenCalledWith(
|
||||
jasmine.any(Function),
|
||||
opts.interval,
|
||||
0,
|
||||
false
|
||||
);
|
||||
returned = false;
|
||||
jasmine.Clock.useMock();
|
||||
openmct = new MCT();
|
||||
spyOn(openmct.indicators, 'add');
|
||||
|
||||
mockHttpRequest();
|
||||
});
|
||||
|
||||
it("has a database cssClass as default", function () {
|
||||
expect(indicatorWrapper.getCssClass()).toEqual("icon-database");
|
||||
afterEach(function () {
|
||||
URLIndicator.prototype.get = defaultPrototypeFunction;
|
||||
jasmine.Clock.reset();
|
||||
});
|
||||
|
||||
it("consults the url with the path supplied", function () {
|
||||
expect(mockHttp.get).toHaveBeenCalledWith(opts.url);
|
||||
describe("on initialization", function () {
|
||||
describe("with default options", function () {
|
||||
beforeEach(function () {
|
||||
options = {
|
||||
url: "someURL"
|
||||
};
|
||||
urlIndicator = URLIndicatorPlugin(options)(openmct);
|
||||
indicatorElement = openmct.indicators.add.mostRecentCall.args[0].element;
|
||||
});
|
||||
|
||||
it("has a default icon class if none supplied", function () {
|
||||
var iconElement = getIconElement();
|
||||
expect(iconElement.hasClass('icon-connectivity')).toBe(true);
|
||||
});
|
||||
|
||||
it("defaults to the URL if no label supplied", function () {
|
||||
var textElement = getTextElement();
|
||||
expect(textElement.text().indexOf(options.url) >= 0).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with custom options", function () {
|
||||
beforeEach(function () {
|
||||
options = {
|
||||
url: "customURL",
|
||||
interval: 1814,
|
||||
iconClass: "iconClass-checked",
|
||||
label: "custom label"
|
||||
};
|
||||
urlIndicator = URLIndicatorPlugin(options)(openmct);
|
||||
indicatorElement = openmct.indicators.add.mostRecentCall.args[0].element;
|
||||
});
|
||||
|
||||
it("uses the custom iconClass", function () {
|
||||
var iconElement = getIconElement();
|
||||
expect(iconElement.hasClass('iconClass-checked')).toBe(true);
|
||||
});
|
||||
it("uses custom interval", function () {
|
||||
expect(mockHttpRequestFunction.calls.length).toEqual(1);
|
||||
jasmine.Clock.tick(1);
|
||||
expect(mockHttpRequestFunction.calls.length).toEqual(1);
|
||||
mockInterval(options.interval + 1);
|
||||
expect(mockHttpRequestFunction.calls.length).toEqual(2);
|
||||
});
|
||||
it("uses custom label if supplied in initialization", function () {
|
||||
var textElement = getTextElement();
|
||||
expect(textElement.text().indexOf(options.label) >= 0).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("changes when the database connection is nominal", function () {
|
||||
var initialText = indicatorWrapper.getText(),
|
||||
initialDescrption = indicatorWrapper.getDescription(),
|
||||
initialGlyphClass = indicatorWrapper.getGlyphClass();
|
||||
describe("when running", function () {
|
||||
beforeEach(function () {
|
||||
options = {
|
||||
url: "someURL",
|
||||
interval: 100
|
||||
};
|
||||
urlIndicator = URLIndicatorPlugin(options)(openmct);
|
||||
indicatorElement = openmct.indicators.add.mostRecentCall.args[0].element;
|
||||
});
|
||||
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
||||
it("requests the provided URL", function () {
|
||||
mockInterval(options.interval + 1);
|
||||
expect(mockHttpRequestFunction).toHaveBeenCalledWith(options.url);
|
||||
});
|
||||
|
||||
// Verify that these values changed;
|
||||
// don't test for specific text.
|
||||
expect(indicatorWrapper.getText()).not.toEqual(initialText);
|
||||
expect(indicatorWrapper.getGlyphClass()).not.toEqual(initialGlyphClass);
|
||||
expect(indicatorWrapper.getDescription()).not.toEqual(initialDescrption);
|
||||
it("indicates success if connection is nominal", function () {
|
||||
mockSuccess();
|
||||
mockInterval(options.interval + 1);
|
||||
|
||||
// Do check for specific class
|
||||
expect(indicatorWrapper.getGlyphClass()).toEqual("ok");
|
||||
waitsFor(httpRequestReturned);
|
||||
runs(function () {
|
||||
var iconElement = getIconElement();
|
||||
expect(iconElement.hasClass('s-status-ok')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("indicates an error when the server cannot be reached", function () {
|
||||
mockError();
|
||||
mockInterval(options.interval + 1);
|
||||
|
||||
waitsFor(httpRequestReturned);
|
||||
runs(function () {
|
||||
var iconElement = getIconElement();
|
||||
expect(iconElement.hasClass('s-status-warning-hi')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("changes when the server cannot be reached", function () {
|
||||
var initialText = indicatorWrapper.getText(),
|
||||
initialDescrption = indicatorWrapper.getDescription(),
|
||||
initialGlyphClass = indicatorWrapper.getGlyphClass();
|
||||
function mockHttpRequest() {
|
||||
mockHttpRequestFunction = jasmine.createSpy('get');
|
||||
URLIndicator.prototype.get = mockHttpRequestFunction;
|
||||
mockSuccess();
|
||||
}
|
||||
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
||||
function mockSuccess() {
|
||||
mockHttpRequestFunction
|
||||
.andReturn(Promise.resolve().then(function () {
|
||||
returned = true;
|
||||
}));
|
||||
}
|
||||
|
||||
// Verify that these values changed;
|
||||
// don't test for specific text.
|
||||
expect(indicatorWrapper.getText()).not.toEqual(initialText);
|
||||
expect(indicatorWrapper.getGlyphClass()).not.toEqual(initialGlyphClass);
|
||||
expect(indicatorWrapper.getDescription()).not.toEqual(initialDescrption);
|
||||
function mockError() {
|
||||
mockHttpRequestFunction
|
||||
.andReturn(Promise.reject().then(function () {
|
||||
returned = true;
|
||||
//Throw error to ensure chained catch is invoked
|
||||
throw undefined;
|
||||
}));
|
||||
}
|
||||
|
||||
// Do check for specific class
|
||||
expect(indicatorWrapper.getGlyphClass()).toEqual("err");
|
||||
});
|
||||
it("has a customized cssClass if supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
cssClass: "cssClass-checked",
|
||||
interval: 10000
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(indicatorWrapper.getCssClass()).toEqual("cssClass-checked");
|
||||
});
|
||||
it("has a customized interval if supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
interval: 1814
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(mockInterval).toHaveBeenCalledWith(
|
||||
jasmine.any(Function),
|
||||
1814,
|
||||
0,
|
||||
false
|
||||
);
|
||||
});
|
||||
it("has a custom label if supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
label: "Localhost"
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(indicatorWrapper.getText()).toEqual("Checking status of Localhost please stand by...");
|
||||
});
|
||||
it("has a default label if not supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080"
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(indicatorWrapper.getText()).toEqual(
|
||||
"Checking status of http://localhost:8080 please stand by..."
|
||||
);
|
||||
});
|
||||
it("has a default interval if not supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080"
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(mockInterval).toHaveBeenCalledWith(
|
||||
jasmine.any(Function),
|
||||
10000,
|
||||
0,
|
||||
false
|
||||
);
|
||||
});
|
||||
function httpRequestReturned() {
|
||||
return returned;
|
||||
}
|
||||
|
||||
function mockInterval(interval) {
|
||||
jasmine.Clock.tick(interval);
|
||||
}
|
||||
|
||||
function getIconElement() {
|
||||
return $('.indicator-icon', indicatorElement);
|
||||
}
|
||||
|
||||
function getTextElement() {
|
||||
return $('.indicator-text', indicatorElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -128,7 +128,7 @@ define([
|
||||
plugins.ExampleImagery = ExampleImagery;
|
||||
plugins.SummaryWidget = SummaryWidget;
|
||||
plugins.TelemetryMean = TelemetryMean;
|
||||
plugins.URLIndicatorPlugin = URLIndicatorPlugin;
|
||||
plugins.URLIndicator = URLIndicatorPlugin;
|
||||
|
||||
return plugins;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user