Compare commits

...

16 Commits

Author SHA1 Message Date
Victor Woeltjen
d75058d5bd [Slideshow] Add slideshow type
Candidate for EOFY17 demo
2017-09-28 13:00:53 -07:00
Victor Woeltjen
bfa3bbcdc7 Merge pull request #1735 from nasa/import-export-1695
Review and integrate usage of new Import/Export glyphs
2017-09-25 16:50:11 -07:00
Victor Woeltjen
2baf3f8bb0 Merge pull request #1733 from nasa/create-menu-1729
Review and integrate super-menu fixes and enhancements
2017-09-25 16:29:54 -07:00
Charles Hacskaylo
10ac13ac5c [Front-end] Updated to use new glyphs
Fixes #1695
2017-09-25 15:22:35 -07:00
Charles Hacskaylo
138cb199bb [Front-end] Markup and CSS refinements
Fixes #1729
Internal markup and CSS now sets heights
internally - menu height will now not be smaller
than the list of menu items OR the description
area;
2017-09-25 14:59:12 -07:00
Victor Woeltjen
374c363a78 [Plot] Handle telemetry panels from plot policy (#1732)
* [Plot] Check for telemetry panels

...from plot view policy, and don't try to interrogate them
for telemetry metadata that they will not have.

Fixes #1728

* [Plot] Update test case for policy

...to provide an adapted object with expected properties

* [Plot] Add tests to very plot policy for panels

...to verify fix for #1728
2017-09-25 14:27:32 -07:00
Charles Hacskaylo
e9cb5cd639 [Front-end] Scrollbar-related color and padding
Fixes #1729
2017-09-25 12:08:59 -07:00
Charles Hacskaylo
bc7d92ee0d [Front-end] Menu tweaks
Fixes #1729
Mini super-menu and related description text
2017-09-25 12:08:04 -07:00
Charles Hacskaylo
78f49784a0 [Front-end] Tweaks
Fixes #1729
CSS and markup mods to convert
to flex from abs pos;
2017-09-25 11:10:58 -07:00
Victor Woeltjen
8754c438cc Merge pull request #1725 from nasa/legacy-telem-source-mapping
[Telemetry] Legacy adapter handles source remap
2017-09-21 11:47:07 -07:00
Pegah Sarram
1419c75503 Inline edit object names (#1700)
* Inline edit object name.

Change the title-label span to a conteneditable span to allow editing object names inline. Implement a controller to handle updaing the name. Add tests.

Fixes #1679

[Front-end] Add span contenteditable to input styling
[Front-end] Styling for contenteditable span
styling for span[contenteditable].s-status-editing in _controls.scss;
removed s-filter class;
[Front-end] min-width added to .s-inline-edit

* [Frontend] Style tweaks, cleanup and simplification

Fixes #1679

Style sanding on .s-inline-edit; added
:focus outline:0 to select in _controls.scss;

New .s-input-inline class; removed ng-class from object-header.html,
uses :focus instead; refactoring of input-related mixins;

Bring Time Conductor real-time inputs into parity

Apply .s-input-inline to TC inputs; finesse .s-input-inline selector;

Prevent nested inline inputs from editing

Fixed nested editing prevention selector

* Create an object header template for objects inside a frame.

Fix code review requests.

Fixes 1679
2017-09-21 11:16:04 -07:00
Pete Richards
ca8cad0a74 [Telemetry] Legacy adapter handles source remap
Update the Legacy Telemetry Adapter to handle source remapping
for telemetry which has it.

fixes https://github.com/nasa/openmct/issues/1724
2017-09-21 10:51:16 -07:00
Victor Woeltjen
a3a55d3b48 [Build] Modify version info injection to fix sourcemaps (#1708)
* [Build] Preserve comments instead of adding header

...to avoid disrupting sourcemaps. Fixes #1707

[Build] Remove extraneous horizontal rule from header

[Build] Remove obsolete header-handling

...as this is handled by the replace task after fix for #1707

[Build] Move version headers into start.frag

...so that UMD boilerplate does not wrap it.

[Build] Handle version info entirely in start.frag

[Build] Replace build variables in start.frag explicitly

[Build] Inject build info dynamically

[Build] Test MCT.specifyBuildInfo

[Build] Mark BUILD_CONSTANTS as global for jshint

[Build] Give names to version line items

[Build] Fix specifyBuildInfo test case

* [Build] Update fix to sourcemaps for code review feedback

https://github.com/nasa/openmct/pull/1708

[Build] Move build info registration to plugin

https://github.com/nasa/openmct/pull/1708#discussion_r138999027

[Build] Use build info plugin

...instead of specifyBuildInfo

[Build] Revert changes to MCT, per code review
2017-09-20 11:50:17 -07:00
Victor Woeltjen
e66f818996 Merge pull request #1714 from nasa/plot-telem-fixes
Plot telem fixes
2017-09-18 15:54:52 -07:00
Pete Richards
ae5ef33487 [Plot] Update policy to detect any range
Update policy to detect any range.  As a simple way to prevent
detecting messages, it will not apply when every range is a string
format.

fixes https://github.com/nasa/openmct/issues/1713
2017-09-16 09:58:58 -07:00
Pete Richards
59c5430579 [Generator] API Compatibility
The telemetry API does not pass request options for subscriptions, updated
generator provider to match this API.

fixes https://github.com/nasa/openmct/issues/1705
2017-09-16 09:37:48 -07:00
42 changed files with 955 additions and 357 deletions

View File

@@ -78,8 +78,8 @@ define([
return this.workerInterface.request(workerRequest);
};
GeneratorProvider.prototype.subscribe = function (domainObject, callback, request) {
var workerRequest = this.makeWorkerRequest(domainObject, request);
GeneratorProvider.prototype.subscribe = function (domainObject, callback) {
var workerRequest = this.makeWorkerRequest(domainObject, {});
return this.workerInterface.subscribe(workerRequest, callback);
};

View File

@@ -46,9 +46,22 @@ var gulp = require('gulp'),
name: 'bower_components/almond/almond.js',
include: paths.main.replace('.js', ''),
wrap: {
startFile: "src/start.frag",
start: (function () {
var buildVariables = {
version: project.version,
timestamp: moment.utc(Date.now()).format(),
revision: fs.existsSync('.git') ? git.long() : 'Unknown',
branch: fs.existsSync('.git') ? git.branch() : 'Unknown'
};
return fs.readFileSync("src/start.frag", 'utf-8')
.replace(/@@(\w+)/g, function (match, key) {
return buildVariables[key];
});;
}()),
endFile: "src/end.frag"
},
optimize: 'uglify2',
uglify2: { output: { comments: /@preserve/ } },
mainConfigFile: paths.main,
wrapShim: true
},
@@ -58,14 +71,6 @@ var gulp = require('gulp'),
},
sass: {
sourceComments: true
},
replace: {
variables: {
version: project.version,
timestamp: moment.utc(Date.now()).format(),
revision: fs.existsSync('.git') ? git.long() : 'Unknown',
branch: fs.existsSync('.git') ? git.branch() : 'Unknown'
}
}
};
@@ -76,16 +81,11 @@ if (process.env.NODE_ENV === 'development') {
gulp.task('scripts', function () {
var requirejsOptimize = require('gulp-requirejs-optimize');
var replace = require('gulp-replace-task');
var header = require('gulp-header');
var comment = fs.readFileSync('src/about.frag');
return gulp.src(paths.main)
.pipe(sourcemaps.init())
.pipe(requirejsOptimize(options.requirejsOptimize))
.pipe(sourcemaps.write('.'))
.pipe(replace(options.replace))
.pipe(header(comment, options.replace.variables))
.pipe(gulp.dest(paths.dist));
});

View File

@@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global requirejs*/
/*global requirejs,BUILD_CONSTANTS*/
requirejs.config({
"paths": {
@@ -91,12 +91,17 @@ requirejs.config({
define([
'./platform/framework/src/Main',
'./src/defaultRegistry',
'./src/MCT'
], function (Main, defaultRegistry, MCT) {
'./src/MCT',
'./src/plugins/buildInfo/plugin'
], function (Main, defaultRegistry, MCT, buildInfo) {
var openmct = new MCT();
openmct.legacyRegistry = defaultRegistry;
if (typeof BUILD_CONSTANTS !== 'undefined') {
openmct.install(buildInfo(BUILD_CONSTANTS));
}
openmct.on('start', function () {
return new Main().run(defaultRegistry);
});

View File

@@ -22,12 +22,10 @@
"git-rev-sync": "^1.4.0",
"glob": ">= 3.0.0",
"gulp": "^3.9.1",
"gulp-header": "^1.8.8",
"gulp-jscs": "^3.0.2",
"gulp-jshint": "^2.0.0",
"gulp-jshint-html-reporter": "^0.1.3",
"gulp-rename": "^1.2.2",
"gulp-replace-task": "^0.11.0",
"gulp-requirejs-optimize": "^0.3.1",
"gulp-sass": "^2.2.0",
"gulp-sourcemaps": "^1.6.0",

View File

@@ -26,6 +26,7 @@ define([
"./src/InspectorPaneController",
"./src/BrowseObjectController",
"./src/MenuArrowController",
"./src/ObjectHeaderController",
"./src/navigation/NavigationService",
"./src/navigation/NavigateAction",
"./src/navigation/OrphanNavigationHandler",
@@ -36,6 +37,7 @@ define([
"text!./res/templates/browse-object.html",
"text!./res/templates/items/grid-item.html",
"text!./res/templates/browse/object-header.html",
"text!./res/templates/browse/object-header-frame.html",
"text!./res/templates/menu-arrow.html",
"text!./res/templates/back-arrow.html",
"text!./res/templates/items/items.html",
@@ -48,6 +50,7 @@ define([
InspectorPaneController,
BrowseObjectController,
MenuArrowController,
ObjectHeaderController,
NavigationService,
NavigateAction,
OrphanNavigationHandler,
@@ -58,6 +61,7 @@ define([
browseObjectTemplate,
gridItemTemplate,
objectHeaderTemplate,
objectHeaderFrameTemplate,
menuArrowTemplate,
backArrowTemplate,
itemsTemplate,
@@ -140,6 +144,13 @@ define([
"$location",
"$attrs"
]
},
{
"key": "ObjectHeaderController",
"implementation": ObjectHeaderController,
"depends": [
"$scope"
]
}
],
"representations": [
@@ -173,6 +184,13 @@ define([
"type"
]
},
{
"key": "object-header-frame",
"template": objectHeaderFrameTemplate,
"uses": [
"type"
]
},
{
"key": "menu-arrow",
"template": menuArrowTemplate,

View File

@@ -0,0 +1,31 @@
<!--
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.
-->
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
<span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller">
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
<span class='title-label flex-elem holder flex-can-shrink s-input-inline'>{{model.name}}</span>
<span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span>
<mct-representation
key="'menu-arrow'"
mct-object='domainObject'
class="flex-elem context-available-w"></mct-representation>
</span>

View File

@@ -20,9 +20,13 @@
at runtime from the About dialog for additional information.
-->
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
<span class="l-elem-wrapper l-flex-row flex-elem grows">
<span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller">
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
<span class='title-label flex-elem holder flex-can-shrink'>{{model.name}}</span>
<span contenteditable="true"
class='title-label flex-elem holder flex-can-shrink s-input-inline'
ng-click="controller.edit()"
ng-blur="controller.updateName($event)"
ng-keypress="controller.updateName($event)">{{model.name}}</span>
<span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span>
<mct-representation
key="'menu-arrow'"

View File

@@ -0,0 +1,75 @@
/*****************************************************************************
* 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(
[],
function () {
/**
* Controller to provide the ability to inline edit an object name.
*
* @constructor
* @memberof platform/commonUI/browse
*/
function ObjectHeaderController($scope) {
this.$scope = $scope;
$scope.editing = false;
}
/**
* Updates the object name on blur and enter keypress events.
*
* @param event the mouse event
*/
ObjectHeaderController.prototype.updateName = function (event) {
if (event && (event.type === 'blur' || event.which === 13)) {
var name = event.currentTarget.innerHTML;
if (name.length === 0) {
name = "Unnamed " + this.$scope.domainObject.getCapability("type").typeDef.name;
event.currentTarget.innerHTML = name;
}
if (name !== this.$scope.domainObject.model.name) {
this.$scope.domainObject.getCapability('mutation').mutate(function (model) {
model.name = name;
});
}
this.$scope.editing = false;
if (event.which === 13) {
event.currentTarget.blur();
}
}
};
/**
* Marks the status of the field as editing.
*/
ObjectHeaderController.prototype.edit = function () {
this.$scope.editing = true;
};
return ObjectHeaderController;
}
);

View File

@@ -0,0 +1,120 @@
/*****************************************************************************
* 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/ObjectHeaderController"],
function (ObjectHeaderController) {
describe("The object header controller", function () {
var mockScope,
mockDomainObject,
mockCapabilities,
mockMutationCapability,
mockTypeCapability,
mockEvent,
mockCurrentTarget,
controller;
beforeEach(function () {
mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
mockTypeCapability = {
typeDef: {
name: ""
}
};
mockCapabilities = {
mutation: mockMutationCapability,
type: mockTypeCapability
};
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "model"]);
mockDomainObject.model = {name: "Test name"};
mockDomainObject.getCapability.andCallFake(function (key) {
return mockCapabilities[key];
});
mockScope = {
domainObject: mockDomainObject
};
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "innerHTML"]);
mockCurrentTarget.blur.andReturn(mockCurrentTarget);
mockEvent = {
which: {},
type: {},
currentTarget: mockCurrentTarget
};
controller = new ObjectHeaderController(mockScope);
});
it("updates the model with new name on blur", function () {
mockEvent.type = "blur";
mockCurrentTarget.innerHTML = "New name";
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
it("updates the model with a default for blank names", function () {
mockEvent.type = "blur";
mockCurrentTarget.innerHTML = "";
controller.updateName(mockEvent);
expect(mockCurrentTarget.innerHTML.length).not.toEqual(0);
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
it("does not update the model if the same name", function () {
mockEvent.type = "blur";
mockCurrentTarget.innerHTML = mockDomainObject.model.name;
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
});
it("updates the model on enter keypress event only", function () {
mockCurrentTarget.innerHTML = "New name";
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
mockMutationCapability.mutate.mostRecentCall.args[0](mockDomainObject.model);
expect(mockDomainObject.model.name).toBe("New name");
});
it("blurs the field on enter key press", function () {
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
});
});
}
);

View File

@@ -23,7 +23,7 @@
<div class="s-menu-button major create-button" ng-click="createController.toggle()">
<span class="title-label">Create</span>
</div>
<div class="menu super-menu" ng-show="createController.isActive()">
<div class="menu super-menu l-create-menu" ng-show="createController.isActive()">
<mct-representation mct-object="domainObject" key="'create-menu'">
</mct-representation>
</div>

View File

@@ -19,8 +19,8 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class="contents" ng-controller="CreateMenuController">
<div class="pane left menu-items">
<div class="w-menu" ng-controller="CreateMenuController">
<div class="col menu-items">
<ul>
<li ng-repeat="createAction in createActions" ng-click="createAction.perform()">
<a ng-mouseover="representation.activeMetadata = createAction.getMetadata()"
@@ -31,13 +31,15 @@
</li>
</ul>
</div>
<div class="pane right menu-item-description">
<div class="col menu-item-description">
<div class="desc-area icon {{ representation.activeMetadata.cssClass }}"></div>
<div class="desc-area title">
{{representation.activeMetadata.name}}
</div>
<div class="desc-area description">
{{representation.activeMetadata.description}}
<div class="w-title-desc">
<div class="desc-area title">
{{representation.activeMetadata.name}}
</div>
<div class="desc-area description">
{{representation.activeMetadata.description}}
</div>
</div>
</div>
</div>

View File

@@ -111,7 +111,9 @@ $bubbleMaxW: 300px;
$reqSymbolW: 15px;
$reqSymbolM: $interiorMargin * 2;
$reqSymbolFontSize: 0.75em;
$inputTextP: 3px 5px;
$inputTextPTopBtm: 3px;
$inputTextPLeftRight: 5px;
$inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
/*************** Wait Spinner Defaults */
$waitSpinnerD: 32px;
$waitSpinnerTreeD: 20px;

View File

@@ -316,23 +316,28 @@
text-shadow: $shdwItemText;
}
@mixin input-base($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@mixin input-base() {
@include appearance(none);
border-radius: $controlCr;
box-sizing: border-box;
box-shadow: inset $shdw;
background: $bg;
border: none;
color: $fg;
outline: none;
&:focus { outline: 0; }
&.error {
background-color: $colorFormFieldErrorBg;
color: $colorFormFieldErrorFg;
}
}
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg) {
@include input-base($bg, $fg);
@mixin s-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include input-base();
background: $bg;
box-shadow: inset $shdw;
color: $fg;
}
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include s-input($bg, $fg, $shdw);
border: none;
outline: none;
}
@mixin contextArrow() {
@@ -344,7 +349,7 @@
}
@mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) {
@include input-base($bg, $fg);
@include nice-input($bg, $fg);
padding: $interiorMargin;
}

View File

@@ -234,12 +234,16 @@ textarea {
}
/******************************************************** INPUTS */
%input-base {
@include input-base();
}
input[type="text"],
input[type="search"],
input[type="number"] {
@include nice-input();
vertical-align: baseline;
padding: $inputTextP;
padding: $inputTextPTopBtm $inputTextPLeftRight;
&.numeric {
text-align: right;
}
@@ -283,6 +287,32 @@ textarea.lg { position: relative; height: 300px; }
}
}
*[contenteditable].s-input-inline,
input[type="text"].s-input-inline,
.s-input-inline input[type="text"] {
// A text input or contenteditable element that indicates edit affordance on hover and looks like an input on focus
@extend %input-base;
@include trans-prop-nice((padding, box-shadow), 250ms);
background: none;
box-shadow: none;
border: 1px solid transparent;
min-width: 20px;
padding-left: 0;
padding-right: 0;
&:hover,
&:focus {
padding-left: $inputTextPLeftRight;
padding-right: $inputTextPLeftRight;
}
&:hover {
border-color: rgba($colorBodyFg, 0.2);
}
&:focus {
@include s-input();
border-color: transparent;
}
}
/******************************************************** SELECTS */
.select {
@include btnSubtle($bg: $colorSelectBg);
@@ -298,6 +328,7 @@ textarea.lg { position: relative; height: 300px; }
select {
@include appearance(none);
box-sizing: border-box;
&:focus { outline: 0; }
background: none;
color: $colorSelectFg;
cursor: pointer;
@@ -722,11 +753,15 @@ body.desktop {
}
.overlay ::-webkit-scrollbar-thumb {
$lr: 15%;
background: $scrollbarThumbColorOverlay;
&:hover { background: $scrollbarThumbColorOverlayHov; }
}
.menu ::-webkit-scrollbar-thumb {
background: $scrollbarThumbColorMenu;
&:hover { background: $scrollbarThumbColorMenuHov; }
}
::-webkit-scrollbar-corner {
background: $scrollbarTrackColorBg;
}

View File

@@ -21,92 +21,87 @@
*****************************************************************************/
/******************************************************** MENU BUTTONS */
.s-menu-button {
// Formerly .btn-menu
@extend .s-button;
span.l-click-area {
// In markup, this element should not enclose anything.
@extend .abs;
}
// Formerly .btn-menu
@extend .s-button;
span.l-click-area {
// In markup, this element should not enclose anything.
@extend .abs;
}
.icon {
font-size: 16px; //120%;
}
.icon {
font-size: 16px; //120%;
}
.title-label {
margin-left: $interiorMarginSm;
}
.title-label {
margin-left: $interiorMarginSm;
}
.color-swatch {
// Used in color menu buttons in toolbar
$d: 10px;
display: inline-block;
border: 1px solid rgba($colorBtnFg, 0.2);
height: $d; width: $d;
height: $d;
width: $d;
vertical-align: middle;
margin-left: $interiorMarginSm;
margin-top: -2px;
}
&:after {
// Adds the downward facing 'context available / invoke menu' arrow element
@include contextArrow();
color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
}
&:after {
// Adds the downward facing 'context available / invoke menu' arrow element
@include contextArrow();
color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
}
&.create-button {
&.create-button {
@extend .icon-plus;
.title-label {
font-size: 1rem;
}
}
.title-label {
font-size: 1rem;
}
}
.menu {
left: 0;
text-align: left;
}
.menu {
left: 0;
text-align: left;
}
}
/******************************************************** MENUS THEMSELVES */
.menu-element {
cursor: pointer;
position: relative;
}
.s-menu {
border-radius: $basicCr;
@include containerSubtle($colorMenuBg, $colorMenuFg);
@include boxShdw($shdwMenu);
@include txtShdw($shdwMenuText);
padding: $interiorMarginSm 0;
cursor: pointer;
position: relative;
}
.menu {
// TODO: reduce size of icons
@extend .s-menu;
display: block;
position: absolute;
z-index: 10;
ul {
@include menuUlReset();
li {
box-sizing: border-box;
border-top: 1px solid pullForward($colorMenuBg, 10%);
border-radius: $basicCr;
@include containerSubtle($colorMenuBg, $colorMenuFg);
@include boxShdw($shdwMenu);
@include txtShdw($shdwMenuText);
padding: $interiorMarginSm 0;
display: block;
position: absolute;
z-index: 10;
ul {
@include menuUlReset();
li {
box-sizing: border-box;
border-top: 1px solid pullForward($colorMenuBg, 10%);
color: $colorMenuFg;
//color: pullForward($colorMenuBg, 60%);
line-height: $menuLineH;
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
position: relative;
white-space: nowrap;
&:first-child {
border: none;
}
&:hover {
background: $colorMenuHovBg;
color: $colorMenuHovFg;
line-height: $menuLineH;
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
position: relative;
white-space: nowrap;
&:first-child {
border: none;
}
&:hover {
background: $colorMenuHovBg;
color: $colorMenuHovFg;
&:before {
color: $colorMenuHovIc;
}
}
}
&:before {
@extend .ui-symbol;
@extend .type-icon;
@@ -114,8 +109,8 @@
display: inline-block;
left: $interiorMargin * 2;
}
}
}
}
}
}
.menu,
@@ -123,94 +118,97 @@
.context-menu,
.super-menu,
.s-menu-button .menu {
pointer-events: auto;
ul li {
a.menu-item-a {
pointer-events: auto;
ul li {
a.menu-item-a {
color: $colorMenuFg;
display: block;
}
}
&:before,
a.menu-item-a:before {
color: $colorMenuIc;
left: $interiorMargin;
}
}
}
}
.checkbox-menu {
// Used in search dropdown in tree
@extend .context-menu;
ul li {
padding-left: 50px;
.checkbox {
$d: 0.7rem;
position: absolute;
left: $interiorMargin;
top: ($menuLineH - $d) / 1.5;
em {
height: $d;
width: $d;
&:before {
font-size: 7px !important;
height: $d;
width: $d;
line-height: $d;
}
}
}
&:before {
// Used in search dropdown in tree
@extend .context-menu;
ul li {
padding-left: 50px;
.checkbox {
$d: 0.7rem;
position: absolute;
left: $interiorMargin;
top: ($menuLineH - $d) / 1.5;
em {
height: $d;
width: $d;
&:before {
font-size: 7px !important;
height: $d;
width: $d;
line-height: $d;
}
}
}
&:before {
// Type icon
left: 25px;
}
}
left: 25px;
}
}
}
.super-menu,
.super-menu > mct-representation,
.super-menu > .contents {
box-sizing: border-box;
display: block;
position: relative;
}
.super-menu {
$w: 500px;
$h: $w - 20;
$plw: 50%;
$prw: 50%;
display: block;
width: $w;
height: $h;
.contents {
@include absPosDefault($interiorMargin);
}
.pane {
box-sizing: border-box;
&.menu-items {
border-right: 1px solid pullForward($colorMenuBg, 10%);
left: 0;
padding-right: $interiorMargin;
right: auto;
width: $plw;
overflow-x: hidden;
overflow-y: auto;
ul {
li {
border-radius: $controlCr;
padding-left: 30px;
border-top: none;
}
}
}
&.menu-item-description {
left: auto;
right: 0;
padding: $interiorMargin * 5;
width: $prw;
$plw: 50%;
$prw: 100% - $plw;
position: absolute;
.w-menu {
align-items: stretch;
display: flex;
flex-direction: row;
margin: $interiorMarginLg;
}
.col {
box-sizing: border-box;
flex: 1 1 auto;
overflow-x: hidden;
&.menu-items {
border-right: 1px solid pullForward($colorMenuBg, 10%);
overflow-y: auto;
padding-right: $interiorMargin;
width: $plw;
ul {
li {
border-radius: $controlCr;
padding-left: 30px;
border-top: none;
}
}
}
&.menu-item-description {
$p: $interiorMargin * 3;
overflow-y: hidden;
padding: $p $p 0 $p;
width: $prw;
.desc-area {
&.icon {
color: $colorCreateMenuLgIcon;
font-size: 8em;
margin-bottom: $interiorMargin * 3;
position: relative;
text-align: center;
}
&.title {
color: $colorCreateMenuText;
font-size: 1.2em;
margin-bottom: $interiorMargin * 2;
}
&.description {
color: pushBack($colorCreateMenuText, 20%);
@@ -218,67 +216,104 @@
line-height: 1.5em;
}
}
}
}
}
}
.w-title-desc {
display: flex;
flex-direction: column;
overflow: hidden; // Height set in specific menu instances
}
// Specific menu instances
&.l-create-menu {
width: 500px;
.col {
max-height: 70vh;
}
.w-title-desc {
height: 190px;
}
.desc-area {
&.icon {
font-size: 8em;
height: 135px;
margin-bottom: $interiorMargin * 3;
}
&.title {
font-size: 1.2em;
margin-bottom: $interiorMargin * 2;
}
}
}
&.mini {
width: 400px;
height: 300px;
.pane {
.col {
max-height: 50vh;
&.menu-items {
font-size: 0.8em;
}
&.menu-item-description {
padding: $interiorMargin * 3;
.desc-area {
&.icon {
font-size: 4em;
}
&.title {
font-size: 1em;
}
}
$p: $interiorMargin * 2;
padding: $p $p 0 $p;
}
}
.w-title-desc {
height: 180px;
}
.desc-area {
&.icon {
font-size: 4em;
height: 70px;
margin-bottom: $interiorMargin * 3;
}
&.title {
font-size: 1em;
margin-bottom: $interiorMargin * 2;
}
}
}
}
.context-menu {
font-size: 0.80rem;
font-size: 0.80rem;
}
.context-menu-holder,
.menu-holder {
position: absolute;
z-index: 120;
.context-menu-wrapper {
position: absolute;
height: 100%;
width: 100%;
}
&.go-left .context-menu,
&.go-left .menu {
right: 0;
}
&.go-up .context-menu,
&.go-up .menu {
bottom: 0;
}
position: absolute;
z-index: 120;
.context-menu-wrapper {
position: absolute;
height: 100%;
width: 100%;
}
&.go-left .context-menu,
&.go-left .menu {
right: 0;
}
&.go-up .context-menu,
&.go-up .menu {
bottom: 0;
}
}
.context-menu-holder {
pointer-events: none;
height: 200px;
width: 170px;
pointer-events: none;
height: 200px;
width: 170px;
}
.btn-bar.right .menu,
.menus-to-left .menu {
z-index: 79;
left: auto;
right: 0;
width: auto;
left: auto;
right: 0;
width: auto;
}
.menus-up .menu {
bottom: $btnStdH; top: auto;
bottom: $btnStdH;
top: auto;
}

View File

@@ -129,9 +129,6 @@
}
.s-filter {
input[type="search"] {
@include input-base();
}
.clear-icon,
.menu-icon,
&:before {

View File

@@ -156,6 +156,8 @@
left: 0;
right: 0;
overflow: auto;
padding-right: $interiorMargin;
padding-bottom: $interiorMargin;
.field.l-input-med {
input[type='text'] {
width: 100%;

View File

@@ -47,7 +47,7 @@
&.t-object-type-hyperlink {
// Hide the right side buttons for objects where they don't make sense
// Note that this will hide the view Switcher button if applied
// to an object that it.
// to an object that has it.
.object-browse-bar .right { display: none; }
}
@@ -120,7 +120,12 @@
}
}
/********************************************************** OBJECT TYPES */
&.t-frame-outer .s-input-inline {
// Prevent inline inputs from being edited when nested in a Layout
pointer-events: none !important;
}
/********************************************************** OBJECT TYPES */
.t-object-type-hyperlink {
.object-holder {
overflow: hidden;

View File

@@ -20,7 +20,7 @@
at runtime from the About dialog for additional information.
-->
<!-- look at action-button for example -->
<span class="t-filter l-filter s-filter"
<span class="t-filter l-filter"
ng-controller="GetterSetterController">
<input type="search"
class="t-filter-input"

View File

@@ -201,13 +201,15 @@ $shdwItemTreeIcon: 0.6;
$colorThumbHoverBg: $colorItemTreeHoverBg;
// Scrollbar
$scrollbarTrackSize: 10px;
$scrollbarTrackShdw: rgba(#000, 0.7) 0 1px 5px;
$scrollbarTrackColorBg: rgba(#000, 0.4);
$scrollbarTrackSize: 7px;
$scrollbarTrackShdw: rgba(#000, 0.5) 0 1px 5px;
$scrollbarTrackColorBg: transparent; //rgba(#000, 0.4);
$scrollbarThumbColor: pullForward($colorBodyBg, 10%);
$scrollbarThumbColorHov: pullForward($scrollbarThumbColor, 2%);
$scrollbarThumbColorOverlay: pullForward($colorOvrBg, 10%);
$scrollbarThumbColorOverlayHov: pullForward($scrollbarThumbColorOverlay, 2%);
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 20%);
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
// Splitter
// All splitterD* values MUST both be either odd or even numbers

View File

@@ -201,13 +201,15 @@ $shdwItemTreeIcon: none;
$colorThumbHoverBg: $colorItemTreeHoverBg;
// Scrollbar
$scrollbarTrackSize: 10px;
$scrollbarTrackSize: 7px;
$scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px;
$scrollbarTrackColorBg: rgba(#000, 0.2);
$scrollbarThumbColor: darken($colorBodyBg, 50%);
$scrollbarThumbColorHov: $colorKey;
$scrollbarThumbColorOverlay: darken($colorOvrBg, 50%);
$scrollbarThumbColorOverlayHov: $scrollbarThumbColorHov;
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%);
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
// Splitter
// All splitterD* values MUST both be either odd or even numbers

View File

@@ -94,31 +94,6 @@ define([
}
},
"extensions": {
"versions": [
{
"name": "Version",
"value": "@@version",
"priority": 999
},
{
"name": "Built",
"value": "@@timestamp",
"description": "The date on which this version of the client was built.",
"priority": 990
},
{
"name": "Revision",
"value": "@@revision",
"description": "A unique revision identifier for the client sources.",
"priority": 995
},
{
"name": "Branch",
"value": "@@branch",
"description": "The name of the branch that was used during the build.",
"priority": 994
}
],
"components": [
{
"provides": "objectService",

View File

@@ -1,7 +1,7 @@
$ueTimeConductorH: (25px, 16px, 20px); // Heights for Ticks, Data Visualization, Controls elements
$ueTimeConductorRtH: (25px, 3px, 20px); // Heights for elements in Real-time mode
$timeCondInputTimeSysDefW: 165px; // Default width for datetime value inputs
$timeCondInputDeltaDefW: 60px; // Default width for delta value inputs, typically 00:00:00
$timeCondInputDeltaDefW: 65px; // Default width for delta value inputs, typically 00:00:00
$timeCondTOIIconD: 12px; // height and width of icon used for TOI indicator
$timeCondTOIValOffset: 0px;
$ticksBlockerFadeW: 50px;

View File

@@ -162,9 +162,6 @@
.l-time-conductor-inputs {
pointer-events: auto;
}
input[type="text"] {
@include trans-prop-nice(padding, 250ms);
}
.time-range-input input[type="text"] {
width: $timeCondInputTimeSysDefW;
}
@@ -290,18 +287,6 @@
.l-time-conductor-inputs-holder {
.l-time-range-input-w {
input[type="text"]:not(.error) {
background: transparent;
box-shadow: none;
border-radius: 0;
padding-left: 0;
padding-right: 0;
&:hover,
&:focus {
@include nice-input();
padding: $inputTextP;
}
}
.icon-calendar {
display: none;
}
@@ -309,8 +294,11 @@
display: none;
}
&.end-date {
// Displays the current time
pointer-events: none;
input[type="text"] {
background: none;
box-shadow: none;
color: pullForward($colorTimeCondKeyBg, 5%);
margin-right: $interiorMargin;
tab-index: -1;

View File

@@ -19,8 +19,8 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class="contents">
<div class="pane left menu-items">
<div class="w-menu">
<div class="col menu-items">
<ul>
<li ng-repeat="metadata in ngModel.options"
ng-click="ngModel.select(metadata)">
@@ -32,13 +32,15 @@
</li>
</ul>
</div>
<div class="pane right menu-item-description">
<div class="col menu-item-description">
<div class="desc-area ui-symbol icon type-icon {{ngModel.activeMetadata.cssClass}}"></div>
<div class="desc-area title">
{{ngModel.activeMetadata.name}}
</div>
<div class="desc-area description">
{{ngModel.activeMetadata.description}}
<div class="w-title-desc">
<div class="desc-area title">
{{ngModel.activeMetadata.name}}
</div>
<div class="desc-area description">
{{ngModel.activeMetadata.description}}
</div>
</div>
</div>
</div>

View File

@@ -24,7 +24,7 @@
ng-click="modeController.toggle()">
<span class="title-label">{{ngModel.selected.name}}</span>
</div>
<div class="menu super-menu mini mode-selector-menu"
<div class="menu super-menu mini l-mode-selector-menu"
ng-show="modeController.isActive()">
<mct-include key="'mode-menu'"
ng-model="ngModel">

View File

@@ -38,7 +38,7 @@
ng-model="boundsModel"
ng-blur="tcController.setOffsetsFromView(boundsModel)"
field="'startOffset'"
class="hrs-min-input">
class="s-input-inline hrs-min-input">
</mct-control>
</span>
</span>
@@ -71,7 +71,7 @@
ng-model="boundsModel"
ng-blur="tcController.setOffsetsFromView(boundsModel)"
field="'endOffset'"
class="hrs-min-input">
class="s-input-inline hrs-min-input">
</mct-control>
</span>
</span>

View File

@@ -201,7 +201,7 @@ define(
var options = [{
key: 'fixed',
name: 'Fixed Timespan Mode',
description: 'Query and explore data that falls between two fixed datetimes',
description: 'Query and explore data that falls between two fixed datetimes.',
cssClass: 'icon-calendar'
}];
var clocks = {};

View File

@@ -23,7 +23,7 @@
<div class="abs object-browse-bar l-flex-row">
<div class="left flex-elem l-flex-row grows">
<mct-representation
key="'object-header'"
key="'object-header-frame'"
mct-object="domainObject"
class="l-flex-row flex-elem object-header grows">
</mct-representation>

View File

@@ -118,7 +118,10 @@ define([
"policies": [
{
"category": "view",
"implementation": PlotViewPolicy
"implementation": PlotViewPolicy,
"depends": [
"openmct"
]
}
],
"representations": [

View File

@@ -30,30 +30,32 @@ define(
* @constructor
* @memberof platform/features/plot
*/
function PlotViewPolicy() {
function PlotViewPolicy(openmct) {
this.openmct = openmct;
}
function hasNumericTelemetry(domainObject) {
var telemetry = domainObject &&
domainObject.getCapability('telemetry'),
metadata = telemetry ? telemetry.getMetadata() : {},
ranges = metadata.ranges || [];
PlotViewPolicy.prototype.hasNumericTelemetry = function (domainObject) {
var adaptedObject = domainObject.useCapability('adapter');
// Generally, we want to allow Plot for telemetry-providing
// objects (most telemetry is plottable.) We only want to
// suppress this for telemetry which only has explicitly
// non-numeric values.
return ranges.length === 0 || ranges.some(function (range) {
// Assume format is numeric if it is undefined
// (numeric telemetry is the common case)
return range.format === undefined ||
range.format === 'number';
});
}
if (!adaptedObject.telemetry) {
return domainObject.hasCapability('delegation') &&
domainObject.getCapability('delegation')
.doesDelegateCapability('telemetry');
}
var metadata = this.openmct.telemetry.getMetadata(adaptedObject);
var rangeValues = metadata.valuesForHints(['range']);
if (rangeValues.length === 0) {
return false;
}
return !rangeValues.every(function (value) {
return value.format === 'string';
});
};
PlotViewPolicy.prototype.allow = function (view, domainObject) {
if (view.key === 'plot') {
return hasNumericTelemetry(domainObject);
return this.hasNumericTelemetry(domainObject);
}
return true;

View File

@@ -27,51 +27,97 @@ define(
describe("Plot view policy", function () {
var testView,
mockDomainObject,
mockTelemetry,
testMetadata,
testAdaptedObject,
openmct,
telemetryMetadata,
policy;
beforeEach(function () {
testView = { key: "plot" };
testMetadata = {};
testAdaptedObject = { telemetry: {} };
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['getId', 'getModel', 'getCapability']
['useCapability', 'hasCapability', 'getCapability']
);
mockTelemetry = jasmine.createSpyObj(
'telemetry',
['getMetadata']
);
mockDomainObject.getCapability.andCallFake(function (c) {
return c === 'telemetry' ? mockTelemetry : undefined;
mockDomainObject.useCapability.andReturn(testAdaptedObject);
openmct = {
telemetry: jasmine.createSpyObj('telemetryAPI', [
'getMetadata'
])
};
telemetryMetadata = jasmine.createSpyObj('telemetryMetadata', [
'valuesForHints'
]);
telemetryMetadata.valuesForHints.andReturn([]);
openmct.telemetry.getMetadata.andReturn(telemetryMetadata);
policy = new PlotViewPolicy(openmct);
});
it('fetches metadata from telem api', function () {
policy.allow(testView, mockDomainObject);
expect(mockDomainObject.useCapability)
.toHaveBeenCalledWith('adapter');
expect(openmct.telemetry.getMetadata)
.toHaveBeenCalledWith(testAdaptedObject);
expect(telemetryMetadata.valuesForHints)
.toHaveBeenCalledWith(['range']);
});
it('returns false if no ranges exist', function () {
telemetryMetadata.valuesForHints.andReturn([]);
expect(policy.allow(testView, mockDomainObject)).toBe(false);
});
it('returns true if any ranges exist', function () {
telemetryMetadata.valuesForHints.andReturn([{}]);
expect(policy.allow(testView, mockDomainObject)).toBe(true);
});
it('returns false if all ranges are strings', function () {
telemetryMetadata.valuesForHints.andReturn([{
format: 'string'
}, {
format: 'string'
}]);
expect(policy.allow(testView, mockDomainObject)).toBe(false);
});
it('returns true if only some ranges are strings', function () {
telemetryMetadata.valuesForHints.andReturn([{
format: 'string'
}, {}]);
expect(policy.allow(testView, mockDomainObject)).toBe(true);
});
it('returns true for telemetry delegators', function () {
delete testAdaptedObject.telemetry;
mockDomainObject.hasCapability.andCallFake(function (c) {
return c === 'delegation';
});
mockTelemetry.getMetadata.andReturn(testMetadata);
policy = new PlotViewPolicy();
mockDomainObject.getCapability.andReturn(
jasmine.createSpyObj('delegation', [
'doesDelegateCapability'
])
);
mockDomainObject.getCapability('delegation')
.doesDelegateCapability.andCallFake(function (c) {
return c === 'telemetry';
});
expect(policy.allow(testView, mockDomainObject)).toBe(true);
expect(openmct.telemetry.getMetadata).not.toHaveBeenCalled();
});
it("allows the imagery view for domain objects with numeric telemetry", function () {
testMetadata.ranges = [{ key: "foo", format: "number" }];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
it("allows the imagery view for domain objects with unspecified telemetry", function () {
testMetadata.ranges = [{ key: "foo" }];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
it("disallows the imagery view for domain objects without image telemetry", function () {
testMetadata.ranges = [{ key: "foo", format: "somethingElse" }];
expect(policy.allow(testView, mockDomainObject)).toBeFalsy();
it('returns true for non-telemetry non-delegators', function () {
delete testAdaptedObject.telemetry;
mockDomainObject.hasCapability.andReturn(false);
expect(policy.allow(testView, mockDomainObject)).toBe(false);
});
it("allows other views", function () {
testView.key = "somethingElse";
testMetadata.ranges = [{ key: "foo", format: "somethingElse" }];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
expect(policy.allow(testView, mockDomainObject)).toBe(true);
});
});
}
);

View File

@@ -47,7 +47,7 @@ define([
"name": "Export as JSON",
"implementation": ExportAsJSONAction,
"category": "contextual",
"cssClass": "icon-save",
"cssClass": "icon-export",
"depends": [
"exportService",
"policyService",
@@ -59,7 +59,7 @@ define([
"name": "Import from JSON",
"implementation": ImportAsJSONAction,
"category": "contextual",
"cssClass": "icon-download",
"cssClass": "icon-import",
"depends": [
"exportService",
"identifierService",

View File

@@ -25,10 +25,12 @@
*/
define(
[
'../../../src/api/objects/object-utils'
'../../../src/api/objects/object-utils',
'lodash'
],
function (
objectUtils
objectUtils,
_
) {
var ZERO = function () {
@@ -189,14 +191,17 @@ define(
return fullRequest;
};
function asSeries(telemetry, defaultDomain, defaultRange, sourceMap) {
function getValue(index, key) {
return telemetry[index][sourceMap[key].source];
}
function asSeries(telemetry, defaultDomain, defaultRange) {
return {
getRangeValue: function (index, range) {
return telemetry[index][range || defaultRange];
return getValue(index, range || defaultRange);
},
getDomainValue: function (index, domain) {
return telemetry[index][domain || defaultDomain];
return getValue(index, domain || defaultDomain);
},
getPointCount: function () {
return telemetry.length;
@@ -223,9 +228,11 @@ define(
var telemetryAPI = this.openmct.telemetry;
var metadata = telemetryAPI.getMetadata(domainObject);
var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
var defaultDomain = metadata.valuesForHints(['domain'])[0].key;
var defaultRange = metadata.valuesForHints(['range'])[0];
defaultRange = defaultRange ? defaultRange.source : undefined;
defaultRange = defaultRange ? defaultRange.key : undefined;
var sourceMap = _.indexBy(metadata.values(), 'key');
var isLegacyProvider = telemetryAPI.findRequestProvider(domainObject) ===
telemetryAPI.legacyProvider;
@@ -250,7 +257,7 @@ define(
requestTelemetryFromService().then(getRelevantResponse);
} else {
return telemetryAPI.request(domainObject, fullRequest).then(function (telemetry) {
return asSeries(telemetry, defaultDomain, defaultRange);
return asSeries(telemetry, defaultDomain, defaultRange, sourceMap);
});
}
};
@@ -286,15 +293,17 @@ define(
var telemetryAPI = this.openmct.telemetry;
var metadata = telemetryAPI.getMetadata(domainObject);
var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
var defaultDomain = metadata.valuesForHints(['domain'])[0].key;
var defaultRange = metadata.valuesForHints(['range'])[0];
defaultRange = defaultRange ? defaultRange.source : undefined;
defaultRange = defaultRange ? defaultRange.key : undefined;
var sourceMap = _.indexBy(metadata.values(), 'key');
var isLegacyProvider = telemetryAPI.findSubscriptionProvider(domainObject) ===
telemetryAPI.legacyProvider;
function update(telemetry) {
callback(asSeries([telemetry], defaultDomain, defaultRange));
callback(asSeries([telemetry], defaultDomain, defaultRange, sourceMap));
}
// Unpack the relevant telemetry series

View File

@@ -34,6 +34,7 @@ define(
mockUnsubscribe,
telemetry,
mockTelemetryAPI,
mockMetadata,
mockAPI;
function mockPromise(value) {
@@ -90,14 +91,23 @@ define(
"findRequestProvider",
"findSubscriptionProvider"
]);
mockTelemetryAPI.getMetadata.andReturn({
valuesForHints: function (hint) {
var metadatum = {};
metadatum[hint] = "foo";
return [metadatum];
}
mockMetadata = jasmine.createSpyObj('telemetryMetadata', [
'valuesForHints',
'values'
]);
mockMetadata.valuesForHints.andCallFake(function (hints) {
var hint = hints[0];
var metadatum = {
key: 'default' + hint
};
metadatum[hint] = "foo";
return [metadatum];
});
mockTelemetryAPI.getMetadata.andReturn(mockMetadata);
mockAPI = {
telemetry: mockTelemetryAPI,
time: {
@@ -150,8 +160,8 @@ define(
key: "testKey", // from model
start: 42, // from argument
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domains: [{ domain: "foo", key: 'defaultdomain' }],
ranges: [{ range: "foo", key: 'defaultrange' }]
}]);
});
@@ -172,8 +182,8 @@ define(
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domains: [{ domain: "foo", key: 'defaultdomain' }],
ranges: [{ range: "foo", key: 'defaultrange' }]
});
});
@@ -191,8 +201,8 @@ define(
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domains: [{ domain: "foo", key: 'defaultdomain' }],
ranges: [{ range: "foo", key: 'defaultrange' }]
});
});
@@ -240,6 +250,21 @@ define(
var mockProvider = {};
var dunzo = false;
mockMetadata.values.andReturn([
{
key: 'defaultrange',
source: 'prop1'
},
{
key: 'defaultdomain',
source: 'prop2'
},
{
key: 'prop3',
source: 'prop3'
}
]);
mockTelemetryAPI.findRequestProvider.andReturn(mockProvider);
mockTelemetryAPI.request.andReturn(Promise.resolve(mockTelemetry));
@@ -257,6 +282,18 @@ define(
expect(returnedTelemetry.getDomainValue).toBeDefined();
expect(returnedTelemetry.getRangeValue).toBeDefined();
expect(returnedTelemetry.getPointCount()).toBe(2);
// Default domain + remap should work.
expect(returnedTelemetry.getDomainValue(0)).toBe('val2');
expect(returnedTelemetry.getDomainValue(1)).toBe('val5');
// explicit domain should work
expect(returnedTelemetry.getDomainValue(0, 'prop3')).toBe('val3');
expect(returnedTelemetry.getDomainValue(1, 'prop3')).toBe('val6');
// default range + remap should work
expect(returnedTelemetry.getRangeValue(0)).toBe('val1');
expect(returnedTelemetry.getRangeValue(1)).toBe('val4');
// explicit range should work
expect(returnedTelemetry.getRangeValue(0, 'prop3')).toBe('val3');
expect(returnedTelemetry.getRangeValue(1, 'prop3')).toBe('val6');
});
});
@@ -275,8 +312,8 @@ define(
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domains: [{ domain: "foo", key: "defaultdomain" }],
ranges: [{ range: "foo", key: "defaultrange" }]
}]
);

View File

@@ -1,7 +0,0 @@
/**
* Open MCT https://nasa.github.io/openmct/
* Version: ${version}
* Built: ${timestamp}
* Revision: ${revision}
* Branch: ${branch}
*/

View File

@@ -0,0 +1,45 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
], function (
) {
return function (buildInfo) {
return function (openmct) {
var aliases = { timestamp: "Built" };
var descriptions = {
timestamp: "The date on which this version of Open MCT was built.",
revision: "A unique revision identifier for the client sources.",
branch: "The name of the branch that was used during the build."
};
Object.keys(buildInfo).forEach(function (key) {
openmct.legacyExtension("versions", {
key: key,
name: aliases[key] || (key.charAt(0).toUpperCase() + key.substring(1)),
value: buildInfo[key],
description: descriptions[key]
});
});
};
};
});

View File

@@ -0,0 +1,50 @@
/*****************************************************************************
* 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([
'./plugin'
], function (plugin) {
describe("The buildInfo plugin", function () {
var mockmct;
var testInfo;
beforeEach(function () {
mockmct = jasmine.createSpyObj('openmct', ['legacyExtension']);
testInfo = { foo: 123, bar: "baz" };
plugin(testInfo)(mockmct);
});
it("registers versions extensions", function () {
Object.keys(testInfo).forEach(function (key) {
expect(mockmct.legacyExtension).toHaveBeenCalledWith(
"versions",
{
key: key,
name: jasmine.any(String),
value: testInfo[key],
description: undefined
}
);
});
});
});
});

View File

@@ -27,7 +27,8 @@ define([
'../../platform/features/autoflow/plugin',
'./timeConductor/plugin',
'../../example/imagery/plugin',
'../../platform/import-export/bundle'
'../../platform/import-export/bundle',
'./slideshow/plugin'
], function (
_,
UTCTimeSystem,
@@ -35,7 +36,8 @@ define([
AutoflowPlugin,
TimeConductorPlugin,
ExampleImagery,
ImportExport
ImportExport,
Slideshow
) {
var bundleMap = {
CouchDB: 'platform/persistence/couch',
@@ -58,6 +60,8 @@ define([
plugins.ImportExport = ImportExport;
plugins.Slideshow = Slideshow;
/**
* A tabular view showing the latest values of multiple telemetry points at
* once. Formatted so that labels and values are aligned.

View File

@@ -0,0 +1,93 @@
/*****************************************************************************
* 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([], function () {
var SLIDESHOW_TEMPLATE =
'<span ng-controller="SlideshowController as slideshow">' +
'<mct-representation key="slideshow.key()" mct-object="slideshow.object()">' +
'</mct-representation></span>';
function SlideshowController($scope, $interval) {
this.composition = [];
this.counter = 0;
$scope.$watch('domainObject', this.update.bind(this));
var interval = $interval(function () {
this.counter += 1;
}.bind(this), 4000);
//$scope.$on("$destroy", interval.cancel.bind(interval));
}
SlideshowController.prototype.update = function (domainObject) {
var composition = domainObject.useCapability("composition");
if (!composition) {
this.composition = [];
return;
}
composition.then(function (composition) {
this.composition = composition;
}.bind(this));
};
SlideshowController.prototype.object = function () {
return Array.isArray(this.composition) && this.composition.length ?
this.composition[this.counter % this.composition.length] :
undefined;
};
SlideshowController.prototype.key = function () {
var object = this.object();
var view = object && object.useCapability('view')[0];
return view && view.key;
};
return function slideshow(options) {
return function install(openmct) {
openmct.types.addType('slideshow', {
name: "Slideshow",
description: "A slideshow display of other objects",
cssClass: 'icon-object',
initialize: function (slideshow) {
slideshow.composition = [];
},
creatable: true
});
openmct.legacyExtension("controllers", {
key: "SlideshowController",
implementation: SlideshowController,
depends: [ "$scope", "$interval" ]
});
openmct.legacyExtension("views", {
key: "slideshow",
type: "slideshow",
editable: true,
gestures: [ "drop" ],
template: SLIDESHOW_TEMPLATE
});
};
};
});

View File

@@ -37,8 +37,7 @@ define(['EventEmitter'], function (EventEmitter) {
this.key = 'local';
this.cssClass = 'icon-clock';
this.name = 'Local Clock';
this.description = "Updates every second, providing UTC timestamps from " +
"user's local computer.";
this.description = "Provides UTC timestamps every second from the local system clock.";
this.period = period;
this.timeoutHandle = undefined;

View File

@@ -18,6 +18,14 @@
* 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.
*
* Open MCT https://nasa.github.io/openmct/
* Version: @@version
* Built: @@timestamp
* Revision: @@revision
* Branch: @@branch
*
* @preserve
*****************************************************************************/
(function (root, factory) {
@@ -29,3 +37,9 @@
root.openmct = factory();
}
}(this, function() {
var BUILD_CONSTANTS = {
version: "@@version",
timestamp: "@@timestamp",
revision: "@@revision",
branch: "@@branch"
};