mirror of
https://github.com/nasa/openmct.git
synced 2025-01-31 00:23:54 +00:00
Made changes to error reporting
This commit is contained in:
commit
8e85675732
@ -6,6 +6,7 @@
|
||||
"platform/commonUI/browse",
|
||||
"platform/commonUI/edit",
|
||||
"platform/commonUI/dialog",
|
||||
"platform/commonUI/formats",
|
||||
"platform/commonUI/general",
|
||||
"platform/commonUI/inspect",
|
||||
"platform/commonUI/mobile",
|
||||
|
@ -187,7 +187,7 @@ GLOBAL.window = GLOBAL.window || GLOBAL; // nomnoml expects window to be define
|
||||
destPath = path.dirname(destination),
|
||||
streamOptions = {};
|
||||
if (file.match(/png$/)){
|
||||
streamOptions.encoding = 'binary';
|
||||
streamOptions.encoding = null;
|
||||
} else {
|
||||
streamOptions.encoding = 'utf8';
|
||||
}
|
||||
|
@ -16,6 +16,23 @@
|
||||
"implementation": "SinewaveLimitCapability.js"
|
||||
}
|
||||
],
|
||||
"formats": [
|
||||
{
|
||||
"key": "example.delta",
|
||||
"implementation": "SinewaveDeltaFormat.js"
|
||||
}
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"key": "TIME_CONDUCTOR_DOMAINS",
|
||||
"value": [
|
||||
{ "key": "time", "name": "Time" },
|
||||
{ "key": "yesterday", "name": "Yesterday" },
|
||||
{ "key": "delta", "name": "Delta", "format": "example.delta" }
|
||||
],
|
||||
"priority": -1
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"key": "generator",
|
||||
@ -38,6 +55,11 @@
|
||||
{
|
||||
"key": "yesterday",
|
||||
"name": "Yesterday"
|
||||
},
|
||||
{
|
||||
"key": "delta",
|
||||
"name": "Delta",
|
||||
"format": "example.delta"
|
||||
}
|
||||
],
|
||||
"ranges": [
|
||||
|
@ -19,18 +19,8 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
// Styles to temporarily hide non-functional elements
|
||||
/*global define,Promise*/
|
||||
|
||||
/******************************** BROWSE */
|
||||
.browse-mode {
|
||||
.browse {
|
||||
&.top-bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.browse-area.holder {
|
||||
// When .browse.top-bar is hidden, set the top of the browse-area holder
|
||||
top: $bodyMargin;
|
||||
}
|
||||
}
|
||||
define({
|
||||
START_TIME: Date.now() - 24 * 60 * 60 * 1000 // Now minus a day.
|
||||
});
|
68
example/generator/src/SinewaveDeltaFormat.js
Normal file
68
example/generator/src/SinewaveDeltaFormat.js
Normal file
@ -0,0 +1,68 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise*/
|
||||
|
||||
define(
|
||||
['./SinewaveConstants', 'moment'],
|
||||
function (SinewaveConstants, moment) {
|
||||
"use strict";
|
||||
|
||||
var START_TIME = SinewaveConstants.START_TIME,
|
||||
FORMAT_REGEX = /^-?\d+:\d+:\d+$/,
|
||||
SECOND = 1000,
|
||||
MINUTE = SECOND * 60,
|
||||
HOUR = MINUTE * 60;
|
||||
|
||||
function SinewaveDeltaFormat() {
|
||||
}
|
||||
|
||||
function twoDigit(v) {
|
||||
return v >= 10 ? String(v) : ('0' + v);
|
||||
}
|
||||
|
||||
SinewaveDeltaFormat.prototype.format = function (value) {
|
||||
var delta = Math.abs(value - START_TIME),
|
||||
negative = value < START_TIME,
|
||||
seconds = Math.floor(delta / SECOND) % 60,
|
||||
minutes = Math.floor(delta / MINUTE) % 60,
|
||||
hours = Math.floor(delta / HOUR);
|
||||
return (negative ? "-" : "") +
|
||||
[ hours, minutes, seconds ].map(twoDigit).join(":");
|
||||
};
|
||||
|
||||
SinewaveDeltaFormat.prototype.validate = function (text) {
|
||||
return FORMAT_REGEX.test(text);
|
||||
};
|
||||
|
||||
SinewaveDeltaFormat.prototype.parse = function (text) {
|
||||
var negative = text[0] === "-",
|
||||
parts = text.replace("-", "").split(":");
|
||||
return [ HOUR, MINUTE, SECOND ].map(function (sz, i) {
|
||||
return parseInt(parts[i], 10) * sz;
|
||||
}).reduce(function (a, b) {
|
||||
return a + b;
|
||||
}, 0) * (negative ? -1 : 1) + START_TIME;
|
||||
};
|
||||
|
||||
return SinewaveDeltaFormat;
|
||||
}
|
||||
);
|
@ -25,12 +25,12 @@
|
||||
* Module defining SinewaveTelemetry. Created by vwoeltje on 11/12/14.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
['./SinewaveConstants'],
|
||||
function (SinewaveConstants) {
|
||||
"use strict";
|
||||
|
||||
var ONE_DAY = 60 * 60 * 24,
|
||||
firstObservedTime = Math.floor(Date.now() / 1000) - ONE_DAY;
|
||||
firstObservedTime = Math.floor(SinewaveConstants.START_TIME / 1000);
|
||||
|
||||
/**
|
||||
*
|
||||
@ -58,6 +58,9 @@ define(
|
||||
};
|
||||
|
||||
generatorData.getDomainValue = function (i, domain) {
|
||||
// delta uses the same numeric values as the default domain,
|
||||
// so it's not checked for here, just formatted for display
|
||||
// differently.
|
||||
return (i + offset) * 1000 + firstTime * 1000 -
|
||||
(domain === 'yesterday' ? ONE_DAY : 0);
|
||||
};
|
||||
|
@ -31,10 +31,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "BrowseTreeController",
|
||||
"implementation": "BrowseTreeController.js",
|
||||
"key": "PaneController",
|
||||
"implementation": "PaneController.js",
|
||||
"priority": "preferred",
|
||||
"depends": [ "$scope", "agentService" ]
|
||||
"depends": [ "$scope", "agentService","$window" ]
|
||||
},
|
||||
{
|
||||
"key": "BrowseObjectController",
|
||||
|
@ -41,7 +41,6 @@
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mct-representation key="representation.selected.key"
|
||||
mct-object="representation.selected.key && domainObject"
|
||||
class="abs object-holder">
|
||||
|
@ -22,22 +22,27 @@
|
||||
|
||||
<div class="abs holder-all browse-mode" ng-controller="BrowseController">
|
||||
<mct-include key="'topbar-browse'"></mct-include>
|
||||
<div class="holder browse-area s-browse-area abs browse-wrapper"
|
||||
ng-controller="BrowseTreeController as tree"
|
||||
ng-class="tree.visible() ? 'browse-showtree' : 'browse-hidetree'">
|
||||
<mct-split-pane class='contents abs' anchor='left'>
|
||||
<div class="abs holder holder-main browse-area s-browse-area browse-wrapper"
|
||||
ng-controller="PaneController as modelPaneTree"
|
||||
ng-class="modelPaneTree.visible() ? 'pane-tree-showing' : 'pane-tree-hidden'">
|
||||
<mct-split-pane class='abs contents'
|
||||
anchor='left'>
|
||||
<div class='split-pane-component treeview pane left'>
|
||||
<div class="holder abs l-mobile">
|
||||
<!--<a class="mini-tab-icon anchor-left toggle-pane toggle-search mobile-hide"
|
||||
title="Enable search"
|
||||
ng-click="modelPaneTree.toggle()"
|
||||
ng-class="{ collapsed : !modelPaneTree.visible() }"
|
||||
ng-style="{ opacity: modelPaneTree.visible()? 0:1 }"></a>-->
|
||||
<div class="holder holder-create-and-search abs l-mobile">
|
||||
<mct-representation key="'create-button'"
|
||||
mct-object="navigatedObject"
|
||||
mct-device="desktop">
|
||||
</mct-representation>
|
||||
<div class='holder search-holder abs'
|
||||
ng-class="{active: treeModel.search}">
|
||||
<mct-representation key="'search'"
|
||||
mct-object="domainObject"
|
||||
<mct-include key="'search'"
|
||||
ng-model="treeModel">
|
||||
</mct-representation>
|
||||
</mct-include>
|
||||
</div>
|
||||
<div class='tree-holder abs mobile-tree-holder'
|
||||
ng-hide="treeModel.search">
|
||||
@ -50,17 +55,40 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mct-splitter class="mobile-hide"></mct-splitter>
|
||||
<mct-splitter class="splitter-treeview mobile-hide"></mct-splitter>
|
||||
|
||||
<div class='split-pane-component items pane right-repr'>
|
||||
<div class='holder abs l-mobile' id='content-area'>
|
||||
<mct-representation mct-object="navigatedObject"
|
||||
key="'browse-object'">
|
||||
</mct-representation>
|
||||
<div class='split-pane-component items pane primary-pane right'>
|
||||
<a class="mini-tab-icon anchor-left toggle-pane toggle-tree"
|
||||
title="{{ modelPaneTree.visible()? 'Hide' : 'Show' }} this pane"
|
||||
ng-click="modelPaneTree.toggle()"
|
||||
ng-class="{ collapsed : !modelPaneTree.visible() }"></a>
|
||||
|
||||
<div class='holder holder-object-and-inspector abs l-mobile' id='content-area'
|
||||
ng-controller="PaneController as modelPaneInspect"
|
||||
ng-class="modelPaneInspect.visible() ? 'pane-inspect-showing' : 'pane-inspect-hidden'">
|
||||
|
||||
<mct-split-pane class='l-object-and-inspector contents abs' anchor='right'>
|
||||
<div class='split-pane-component t-object pane primary-pane left'>
|
||||
<mct-representation mct-object="navigatedObject"
|
||||
key="'browse-object'"
|
||||
class="abs holder holder-object">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
<mct-splitter class="splitter-inspect mobile-hide flush-right edge-shdw"></mct-splitter>
|
||||
|
||||
<div class="split-pane-component t-inspect pane right mobile-hide">
|
||||
<mct-representation key="'object-inspector'"
|
||||
mct-object="domainObject"
|
||||
ng-model="treeModel">
|
||||
</mct-representation>
|
||||
<a class="mini-tab-icon anchor-right mobile-hide toggle-pane toggle-inspect"
|
||||
title="{{ modelPaneInspect.visible()? 'Hide' : 'Show' }} the Inspection pane"
|
||||
ng-click="modelPaneInspect.toggle()"
|
||||
ng-class="{ collapsed : !modelPaneInspect.visible() }"></a>
|
||||
</div>
|
||||
</mct-split-pane>
|
||||
</div>
|
||||
<div class="key-properties ui-symbol icon mobile-menu-icon desktop-hide"
|
||||
mct-device="mobile"
|
||||
ng-click="tree.toggle()">m</div>
|
||||
</div>
|
||||
</mct-split-pane>
|
||||
</div>
|
||||
|
@ -19,7 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class='object-header object-header-mobile'>
|
||||
<div class='object-header'>
|
||||
<span class='type-icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<!--span class='type-name mobile-important-hide'>{{type.getName()}}</span-->
|
||||
<span class="l-elem-wrapper l-flex">
|
||||
|
@ -19,13 +19,12 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="menu-element wrapper" ng-controller="ClickAwayController as createController">
|
||||
<span ng-controller="ClickAwayController as createController">
|
||||
<div class="s-menu-btn major create-btn" ng-click="createController.toggle()">
|
||||
<span class="ui-symbol icon type-icon">+</span>
|
||||
<span class="title-label">Create</span>
|
||||
</div>
|
||||
<div class="menu super-menu" ng-show="createController.isActive()">
|
||||
<mct-representation mct-object="domainObject" key="'create-menu'">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
@ -26,14 +26,8 @@
|
||||
<div class='ui-symbol profile' title='Shared'>O</div>
|
||||
<mct-representation class="desktop-hide" key="'info-button'" mct-object="domainObject"></mct-representation>
|
||||
</div>
|
||||
<div class='item-main abs'>
|
||||
<div class='ui-symbol icon lg item-type'>
|
||||
{{type.getGlyph()}}
|
||||
<span
|
||||
class="ui-symbol l-icon-link" title="This object is a link"
|
||||
ng-show="location.isLink()"
|
||||
></span>
|
||||
</div>
|
||||
<div class='item-main abs lg'>
|
||||
<span class="t-item-icon" ng-class="{ 'l-icon-link':location.isLink() }">{{type.getGlyph()}}</span>
|
||||
<div class='ui-symbol abs item-open'>}</div>
|
||||
</div>
|
||||
<div class='bottom-bar bar abs'>
|
||||
|
@ -153,7 +153,6 @@ define(
|
||||
$scope.$on("$destroy", function () {
|
||||
navigationService.removeListener(setNavigation);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return BrowseController;
|
||||
|
@ -33,10 +33,12 @@ define(
|
||||
* @constructor
|
||||
* @memberof platform/commonUI/browse
|
||||
*/
|
||||
function BrowseTreeController($scope, agentService) {
|
||||
function PaneController($scope, agentService, $window) {
|
||||
var self = this;
|
||||
this.agentService = agentService;
|
||||
this.state = true;
|
||||
|
||||
// Fast and cheap: if this has been opened in a new window, hide panes by default
|
||||
this.state = !$window.opener;
|
||||
|
||||
/**
|
||||
* Callback to invoke when any selection occurs in the tree.
|
||||
@ -44,7 +46,7 @@ define(
|
||||
* to the tree representation.
|
||||
*
|
||||
* @property {Function} callback
|
||||
* @memberof platform/commonUI/browse.BrowseTreeController#
|
||||
* @memberof platform/commonUI/browse.PaneController#
|
||||
*/
|
||||
this.callback = function () {
|
||||
// Note that, since this is a callback to pass, this is not
|
||||
@ -59,20 +61,20 @@ define(
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the visibility of the tree.
|
||||
* Toggle the visibility of the pane.
|
||||
*/
|
||||
BrowseTreeController.prototype.toggle = function () {
|
||||
PaneController.prototype.toggle = function () {
|
||||
this.state = !this.state;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the desired visibility state of the tree.
|
||||
* Get the desired visibility state of the pane.
|
||||
* @returns {boolean} true when visible
|
||||
*/
|
||||
BrowseTreeController.prototype.visible = function () {
|
||||
PaneController.prototype.visible = function () {
|
||||
return this.state;
|
||||
};
|
||||
|
||||
return BrowseTreeController;
|
||||
return PaneController;
|
||||
}
|
||||
);
|
@ -22,22 +22,24 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/BrowseTreeController"],
|
||||
function (BrowseTreeController) {
|
||||
["../src/PaneController"],
|
||||
function (PaneController) {
|
||||
'use strict';
|
||||
|
||||
describe("The BrowseTreeController", function () {
|
||||
describe("The PaneController", function () {
|
||||
var mockScope,
|
||||
mockAgentService,
|
||||
mockDomainObjects,
|
||||
mockWindow,
|
||||
controller;
|
||||
|
||||
// We want to reinstantiate for each test case
|
||||
// because device state can influence constructor-time behavior
|
||||
function instantiateController() {
|
||||
return new BrowseTreeController(
|
||||
return new PaneController(
|
||||
mockScope,
|
||||
mockAgentService
|
||||
mockAgentService,
|
||||
mockWindow
|
||||
);
|
||||
}
|
||||
|
||||
@ -58,6 +60,7 @@ define(
|
||||
"agentService",
|
||||
[ "isMobile", "isPhone", "isTablet", "isPortrait", "isLandscape" ]
|
||||
);
|
||||
mockWindow = jasmine.createSpyObj("$window", ["open"]);
|
||||
});
|
||||
|
||||
it("is initially visible", function () {
|
@ -1,7 +1,7 @@
|
||||
[
|
||||
"BrowseController",
|
||||
"BrowseObjectController",
|
||||
"BrowseTreeController",
|
||||
"PaneController",
|
||||
"MenuArrowController",
|
||||
"creation/CreateAction",
|
||||
"creation/CreateActionProvider",
|
||||
|
@ -181,7 +181,7 @@ define(
|
||||
* @typedef DialogOption
|
||||
* @property {string} label a label to be displayed as the button
|
||||
* text for this action
|
||||
* @property {function} action a function to be called when the
|
||||
* @property {function} callback a function to be called when the
|
||||
* button is clicked
|
||||
*/
|
||||
|
||||
|
26
platform/commonUI/formats/bundle.json
Normal file
26
platform/commonUI/formats/bundle.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "Time services bundle",
|
||||
"description": "Defines interfaces and provides default implementations for handling different time systems.",
|
||||
"extensions": {
|
||||
"components": [
|
||||
{
|
||||
"provides": "formatService",
|
||||
"type": "provider",
|
||||
"implementation": "FormatProvider.js",
|
||||
"depends": [ "formats[]" ]
|
||||
}
|
||||
],
|
||||
"formats": [
|
||||
{
|
||||
"key": "utc",
|
||||
"implementation": "UTCTimeFormat.js"
|
||||
}
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"key": "DEFAULT_TIME_FORMAT",
|
||||
"value": "utc"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
114
platform/commonUI/formats/src/FormatProvider.js
Normal file
114
platform/commonUI/formats/src/FormatProvider.js
Normal file
@ -0,0 +1,114 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* An object used to convert between numeric values and text values,
|
||||
* typically used to display these values to the user and to convert
|
||||
* user input to a numeric format, particularly for time formats.
|
||||
* @interface {Format}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parse text (typically user input) to a numeric value.
|
||||
* Behavior is undefined when the text cannot be parsed;
|
||||
* `validate` should be called first if the text may be invalid.
|
||||
* @method parse
|
||||
* @memberof Format#
|
||||
* @param {string} text the text to parse
|
||||
* @returns {number} the parsed numeric value
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determine whether or not some text (typically user input) can
|
||||
* be parsed to a numeric value by this format.
|
||||
* @method validate
|
||||
* @memberof Format#
|
||||
* @param {string} text the text to parse
|
||||
* @returns {boolean} true if the text can be parsed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a numeric value to a text value for display using
|
||||
* this format.
|
||||
* @method format
|
||||
* @memberof Format#
|
||||
* @param {number} value the numeric value to format
|
||||
* @returns {string} the text representation of the value
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides access to `Format` objects which can be used to
|
||||
* convert values between human-readable text and numeric
|
||||
* representations.
|
||||
* @interface FormatService
|
||||
*/
|
||||
|
||||
/**
|
||||
* Look up a format by its symbolic identifier.
|
||||
* @method getFormat
|
||||
* @memberof FormatService#
|
||||
* @param {string} key the identifier for this format
|
||||
* @returns {Format} the format
|
||||
* @throws {Error} errors when the requested format is unrecognized
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides formats from the `formats` extension category.
|
||||
* @constructor
|
||||
* @implements {FormatService}
|
||||
* @memberof platform/commonUI/formats
|
||||
* @param {Array.<function(new : Format)>} format constructors,
|
||||
* from the `formats` extension category.
|
||||
*/
|
||||
function FormatProvider(formats) {
|
||||
var formatMap = {};
|
||||
|
||||
function addToMap(Format) {
|
||||
var key = Format.key;
|
||||
if (key && !formatMap[key]) {
|
||||
formatMap[key] = new Format();
|
||||
}
|
||||
}
|
||||
|
||||
formats.forEach(addToMap);
|
||||
this.formatMap = formatMap;
|
||||
}
|
||||
|
||||
FormatProvider.prototype.getFormat = function (key) {
|
||||
var format = this.formatMap[key];
|
||||
if (!format) {
|
||||
throw new Error("FormatProvider: No format found for " + key);
|
||||
}
|
||||
return format;
|
||||
};
|
||||
|
||||
return FormatProvider;
|
||||
|
||||
});
|
@ -19,17 +19,45 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/* Classes to be used for lists of properties and values */
|
||||
/*global define*/
|
||||
|
||||
.properties {
|
||||
.s-row {
|
||||
border-top: 1px solid $colorInteriorBorder;
|
||||
font-size: 0.8em;
|
||||
&:first-child {
|
||||
border: none;
|
||||
}
|
||||
.s-value {
|
||||
color: #fff;
|
||||
}
|
||||
define([
|
||||
'moment'
|
||||
], function (
|
||||
moment
|
||||
) {
|
||||
"use strict";
|
||||
|
||||
var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss",
|
||||
DATE_FORMATS = [
|
||||
DATE_FORMAT,
|
||||
"YYYY-MM-DD HH:mm",
|
||||
"YYYY-MM-DD"
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Formatter for UTC timestamps. Interprets numeric values as
|
||||
* milliseconds since the start of 1970.
|
||||
*
|
||||
* @implements {Format}
|
||||
* @constructor
|
||||
* @memberof platform/commonUI/formats
|
||||
*/
|
||||
function UTCTimeFormat() {
|
||||
}
|
||||
}
|
||||
|
||||
UTCTimeFormat.prototype.format = function (value) {
|
||||
return moment.utc(value).format(DATE_FORMAT);
|
||||
};
|
||||
|
||||
UTCTimeFormat.prototype.parse = function (text) {
|
||||
return moment.utc(text, DATE_FORMATS).valueOf();
|
||||
};
|
||||
|
||||
UTCTimeFormat.prototype.validate = function (text) {
|
||||
return moment.utc(text, DATE_FORMATS).isValid();
|
||||
};
|
||||
|
||||
return UTCTimeFormat;
|
||||
});
|
68
platform/commonUI/formats/test/FormatProviderSpec.js
Normal file
68
platform/commonUI/formats/test/FormatProviderSpec.js
Normal file
@ -0,0 +1,68 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../src/FormatProvider'],
|
||||
function (FormatProvider) {
|
||||
'use strict';
|
||||
|
||||
var KEYS = [ 'a', 'b', 'c' ];
|
||||
|
||||
describe("The FormatProvider", function () {
|
||||
var mockFormats,
|
||||
mockLog,
|
||||
mockFormatInstances,
|
||||
provider;
|
||||
|
||||
beforeEach(function () {
|
||||
mockFormatInstances = KEYS.map(function (k) {
|
||||
return jasmine.createSpyObj(
|
||||
'format-' + k,
|
||||
[ 'parse', 'validate', 'format' ]
|
||||
);
|
||||
});
|
||||
// Return constructors
|
||||
mockFormats = KEYS.map(function (k, i) {
|
||||
function MockFormat() { return mockFormatInstances[i]; }
|
||||
MockFormat.key = k;
|
||||
return MockFormat;
|
||||
});
|
||||
provider = new FormatProvider(mockFormats);
|
||||
});
|
||||
|
||||
it("looks up formats by key", function () {
|
||||
KEYS.forEach(function (k, i) {
|
||||
expect(provider.getFormat(k))
|
||||
.toEqual(mockFormatInstances[i]);
|
||||
});
|
||||
});
|
||||
|
||||
it("throws an error about unknown formats", function () {
|
||||
expect(function () {
|
||||
provider.getFormat('some-unknown-format');
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
56
platform/commonUI/formats/test/UTCTimeFormatSpec.js
Normal file
56
platform/commonUI/formats/test/UTCTimeFormatSpec.js
Normal file
@ -0,0 +1,56 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../src/UTCTimeFormat', 'moment'],
|
||||
function (UTCTimeFormat, moment) {
|
||||
'use strict';
|
||||
|
||||
describe("The UTCTimeFormat", function () {
|
||||
var format;
|
||||
|
||||
beforeEach(function () {
|
||||
format = new UTCTimeFormat();
|
||||
});
|
||||
|
||||
it("formats UTC timestamps", function () {
|
||||
var timestamp = 12345670000,
|
||||
formatted = format.format(timestamp);
|
||||
expect(formatted).toEqual(jasmine.any(String));
|
||||
expect(moment.utc(formatted).valueOf()).toEqual(timestamp);
|
||||
});
|
||||
|
||||
it("validates time inputs", function () {
|
||||
expect(format.validate("1977-05-25 11:21:22")).toBe(true);
|
||||
expect(format.validate("garbage text")).toBe(false);
|
||||
});
|
||||
|
||||
it("parses valid input", function () {
|
||||
var text = "1977-05-25 11:21:22",
|
||||
parsed = format.parse(text);
|
||||
expect(parsed).toEqual(jasmine.any(Number));
|
||||
expect(parsed).toEqual(moment.utc(text).valueOf());
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
4
platform/commonUI/formats/test/suite.json
Normal file
4
platform/commonUI/formats/test/suite.json
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
"FormatProvider",
|
||||
"UTCTimeFormat"
|
||||
]
|
@ -61,13 +61,18 @@
|
||||
{
|
||||
"key": "TimeRangeController",
|
||||
"implementation": "controllers/TimeRangeController.js",
|
||||
"depends": [ "$scope", "now" ]
|
||||
"depends": [ "$scope", "formatService", "DEFAULT_TIME_FORMAT", "now" ]
|
||||
},
|
||||
{
|
||||
"key": "DateTimePickerController",
|
||||
"implementation": "controllers/DateTimePickerController.js",
|
||||
"depends": [ "$scope", "now" ]
|
||||
},
|
||||
{
|
||||
"key": "DateTimeFieldController",
|
||||
"implementation": "controllers/DateTimeFieldController.js",
|
||||
"depends": [ "$scope", "formatService", "DEFAULT_TIME_FORMAT" ]
|
||||
},
|
||||
{
|
||||
"key": "TreeNodeController",
|
||||
"implementation": "controllers/TreeNodeController.js",
|
||||
@ -116,6 +121,11 @@
|
||||
"implementation": "controllers/SelectorController.js",
|
||||
"depends": [ "objectService", "$scope" ]
|
||||
},
|
||||
{
|
||||
"key": "ObjectInspectorController",
|
||||
"implementation": "controllers/ObjectInspectorController.js",
|
||||
"depends": [ "$scope", "objectService" ]
|
||||
},
|
||||
{
|
||||
"key": "BannerController",
|
||||
"implementation": "controllers/BannerController.js",
|
||||
@ -245,6 +255,10 @@
|
||||
"key": "switcher",
|
||||
"templateUrl": "templates/controls/switcher.html",
|
||||
"uses": [ "view" ]
|
||||
},
|
||||
{
|
||||
"key": "object-inspector",
|
||||
"templateUrl": "templates/object-inspector.html"
|
||||
}
|
||||
],
|
||||
"controls": [
|
||||
@ -255,6 +269,10 @@
|
||||
{
|
||||
"key": "datetime-picker",
|
||||
"templateUrl": "templates/controls/datetime-picker.html"
|
||||
},
|
||||
{
|
||||
"key": "datetime-field",
|
||||
"templateUrl": "templates/controls/datetime-field.html"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
|
@ -1,19 +1,59 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "WTD Symbols v2.3",
|
||||
"lastOpened": 1444267493342,
|
||||
"created": 1444266013303
|
||||
"name": "WTD Symbols",
|
||||
"lastOpened": 1446490786311,
|
||||
"created": 1446489891263
|
||||
},
|
||||
"iconSets": [
|
||||
{
|
||||
"selection": [
|
||||
{
|
||||
"order": 113,
|
||||
"id": 92,
|
||||
"prevSize": 32,
|
||||
"code": 58901,
|
||||
"name": "icon-crosshair",
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 110,
|
||||
"id": 91,
|
||||
"prevSize": 32,
|
||||
"code": 58899,
|
||||
"name": "icon-collapse-pane-left",
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 111,
|
||||
"id": 90,
|
||||
"prevSize": 32,
|
||||
"code": 58900,
|
||||
"name": "icon-collapse-pane-right",
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 109,
|
||||
"id": 89,
|
||||
"prevSize": 32,
|
||||
"code": 58898,
|
||||
"name": "icon-save",
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 108,
|
||||
"id": 88,
|
||||
"prevSize": 32,
|
||||
"code": 58897,
|
||||
"name": "icon-dataset",
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 90,
|
||||
"id": 87,
|
||||
"prevSize": 32,
|
||||
"code": 58896,
|
||||
"name": "icon-bell",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 91,
|
||||
@ -21,7 +61,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58889,
|
||||
"name": "icon-hourglass",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 92,
|
||||
@ -34,7 +74,7 @@
|
||||
58890
|
||||
],
|
||||
"name": "icon-info-v15",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 93,
|
||||
@ -42,7 +82,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58887,
|
||||
"name": "icon-x-in-circle",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 94,
|
||||
@ -50,7 +90,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58881,
|
||||
"name": "icon-datatable",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 95,
|
||||
@ -58,7 +98,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58882,
|
||||
"name": "icon-tabular-scrolling",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 96,
|
||||
@ -66,7 +106,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58884,
|
||||
"name": "icon-tabular",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 97,
|
||||
@ -74,7 +114,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58885,
|
||||
"name": "icon-calendar",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 98,
|
||||
@ -82,7 +122,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58886,
|
||||
"name": "icon-paint-bucket",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 99,
|
||||
@ -90,7 +130,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 123,
|
||||
"name": "icon-pointer-left",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 100,
|
||||
@ -98,7 +138,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 125,
|
||||
"name": "icon-pointer-right",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 101,
|
||||
@ -106,7 +146,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 80,
|
||||
"name": "icon-person",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 102,
|
||||
@ -114,7 +154,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 232,
|
||||
"name": "icon-chain-links",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 103,
|
||||
@ -122,7 +162,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 115,
|
||||
"name": "icon-database-in-brackets",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 104,
|
||||
@ -130,7 +170,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 114,
|
||||
"name": "icon-refresh",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 105,
|
||||
@ -138,7 +178,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 108,
|
||||
"name": "icon-lock",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 106,
|
||||
@ -146,7 +186,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 51,
|
||||
"name": "icon-box-with-dashed-lines",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 10,
|
||||
@ -154,7 +194,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58880,
|
||||
"name": "icon-box-with-arrow-cursor",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 11,
|
||||
@ -162,7 +202,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 65,
|
||||
"name": "icon-activity-mode",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 12,
|
||||
@ -170,7 +210,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 97,
|
||||
"name": "icon-activity",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 87,
|
||||
@ -178,7 +218,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 33,
|
||||
"name": "icon-alert-rect",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 14,
|
||||
@ -186,7 +226,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58883,
|
||||
"name": "icon-alert-triangle",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 15,
|
||||
@ -194,7 +234,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 238,
|
||||
"name": "icon-arrow-double-down",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 16,
|
||||
@ -202,7 +242,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 235,
|
||||
"name": "icon-arrow-double-up",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 2,
|
||||
@ -210,7 +250,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 118,
|
||||
"name": "icon-arrow-down",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 19,
|
||||
@ -218,7 +258,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 60,
|
||||
"name": "icon-arrow-left",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 20,
|
||||
@ -226,7 +266,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 62,
|
||||
"name": "icon-arrow-right",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 21,
|
||||
@ -234,7 +274,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 236,
|
||||
"name": "icon-arrow-tall-down",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 22,
|
||||
@ -242,7 +282,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 237,
|
||||
"name": "icon-arrow-tall-up",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 23,
|
||||
@ -250,7 +290,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 94,
|
||||
"name": "icon-arrow-up",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 24,
|
||||
@ -258,7 +298,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 73,
|
||||
"name": "icon-arrows-out",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 25,
|
||||
@ -266,7 +306,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58893,
|
||||
"name": "icon-arrows-right-left",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 33,
|
||||
@ -274,7 +314,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 53,
|
||||
"name": "icon-arrows-up-down",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 26,
|
||||
@ -282,7 +322,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 42,
|
||||
"name": "icon-asterisk",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 27,
|
||||
@ -290,7 +330,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 72,
|
||||
"name": "icon-autoflow-tabular",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 28,
|
||||
@ -298,7 +338,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 224,
|
||||
"name": "icon-box",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 29,
|
||||
@ -306,7 +346,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 50,
|
||||
"name": "icon-check",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 30,
|
||||
@ -314,7 +354,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 67,
|
||||
"name": "icon-clock",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 31,
|
||||
@ -322,7 +362,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 46,
|
||||
"name": "icon-connectivity",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 32,
|
||||
@ -330,7 +370,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 100,
|
||||
"name": "icon-database-query",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 17,
|
||||
@ -338,7 +378,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 68,
|
||||
"name": "icon-database",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 35,
|
||||
@ -346,7 +386,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 81,
|
||||
"name": "icon-dictionary",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 36,
|
||||
@ -354,7 +394,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 242,
|
||||
"name": "icon-duplicate",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 37,
|
||||
@ -362,7 +402,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 102,
|
||||
"name": "icon-folder-new",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 38,
|
||||
@ -370,7 +410,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 70,
|
||||
"name": "icon-folder",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 39,
|
||||
@ -378,7 +418,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 95,
|
||||
"name": "icon-fullscreen-collapse",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 40,
|
||||
@ -386,7 +426,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 122,
|
||||
"name": "icon-fullscreen-expand",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 41,
|
||||
@ -394,7 +434,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 71,
|
||||
"name": "icon-gear",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 49,
|
||||
@ -402,7 +442,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 227,
|
||||
"name": "icon-image",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 42,
|
||||
@ -410,7 +450,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 225,
|
||||
"name": "icon-layers",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 43,
|
||||
@ -418,7 +458,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 76,
|
||||
"name": "icon-layout",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 44,
|
||||
@ -426,7 +466,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 226,
|
||||
"name": "icon-line-horz",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 75,
|
||||
@ -434,7 +474,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 244,
|
||||
"name": "icon-link",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 46,
|
||||
@ -442,7 +482,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 88,
|
||||
"name": "icon-magnify-in",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 47,
|
||||
@ -450,7 +490,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 89,
|
||||
"name": "icon-magnify-out",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 48,
|
||||
@ -458,7 +498,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 77,
|
||||
"name": "icon-magnify",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 34,
|
||||
@ -466,7 +506,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 109,
|
||||
"name": "icon-menu",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 50,
|
||||
@ -474,7 +514,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 243,
|
||||
"name": "icon-move",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 51,
|
||||
@ -482,7 +522,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 121,
|
||||
"name": "icon-new-window",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 52,
|
||||
@ -490,7 +530,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 111,
|
||||
"name": "icon-object",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 73,
|
||||
@ -498,7 +538,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 63,
|
||||
"name": "icon-object-unknown",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 53,
|
||||
@ -506,7 +546,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 86,
|
||||
"name": "icon-packet",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 54,
|
||||
@ -514,7 +554,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 234,
|
||||
"name": "icon-page",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 55,
|
||||
@ -522,7 +562,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 241,
|
||||
"name": "icon-pause",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 56,
|
||||
@ -530,7 +570,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 112,
|
||||
"name": "icon-pencil",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 65,
|
||||
@ -538,7 +578,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 79,
|
||||
"name": "icon-people",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 57,
|
||||
@ -546,7 +586,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 239,
|
||||
"name": "icon-play",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 58,
|
||||
@ -554,7 +594,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 233,
|
||||
"name": "icon-plot-resource",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 59,
|
||||
@ -562,7 +602,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 43,
|
||||
"name": "icon-plus",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 60,
|
||||
@ -570,7 +610,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 45,
|
||||
"name": "icon-minus",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 61,
|
||||
@ -578,7 +618,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 54,
|
||||
"name": "icon-sine",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 62,
|
||||
@ -586,7 +626,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 228,
|
||||
"name": "icon-T",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 63,
|
||||
@ -594,7 +634,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 116,
|
||||
"name": "icon-telemetry-panel",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 64,
|
||||
@ -602,7 +642,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 84,
|
||||
"name": "icon-telemetry",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 18,
|
||||
@ -610,7 +650,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 246,
|
||||
"name": "icon-thumbs-strip",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 67,
|
||||
@ -618,7 +658,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 83,
|
||||
"name": "icon-timeline",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 68,
|
||||
@ -626,7 +666,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 245,
|
||||
"name": "icon-timer",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 69,
|
||||
@ -634,7 +674,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 90,
|
||||
"name": "icon-trash",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 70,
|
||||
@ -642,7 +682,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 229,
|
||||
"name": "icon-two-parts-both",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 71,
|
||||
@ -650,7 +690,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 231,
|
||||
"name": "icon-two-parts-one-only",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 72,
|
||||
@ -658,7 +698,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 120,
|
||||
"name": "icon-x-heavy",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 66,
|
||||
@ -666,7 +706,7 @@
|
||||
"prevSize": 32,
|
||||
"code": 58946,
|
||||
"name": "icon-x",
|
||||
"tempChar": ""
|
||||
"tempChar": ""
|
||||
}
|
||||
],
|
||||
"id": 2,
|
||||
@ -681,6 +721,121 @@
|
||||
"height": 1024,
|
||||
"prevSize": 32,
|
||||
"icons": [
|
||||
{
|
||||
"id": 92,
|
||||
"paths": [
|
||||
"M514 2c-282.8 0-512 229.2-512 512s229.2 512 512 512 512-229.2 512-512-229.2-512-512-512zM860.2 450h-282.2v-282.2c69.6 12.8 133.8 46.2 185 97.4 51 51 84.4 115.2 97.2 184.8zM450 167.8v282.2h-282.2c12.8-69.6 46.2-133.8 97.4-185 51-51 115.2-84.4 184.8-97.2zM167.8 578h282.2v282.2c-69.6-12.8-133.8-46.2-185-97.4-51-51-84.4-115.2-97.2-184.8zM578 860.2v-282.2h282.2c-12.8 69.6-46.2 133.8-97.4 185-51 51-115.2 84.4-184.8 97.2z"
|
||||
],
|
||||
"attrs": [
|
||||
{
|
||||
"fill": "rgb(0, 0, 0)"
|
||||
}
|
||||
],
|
||||
"isMulticolor": false,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"icon-crosshair"
|
||||
],
|
||||
"colorPermutations": {
|
||||
"125525525516161751": [
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 91,
|
||||
"paths": [
|
||||
"M256 0h-256v1024h256c105.6 0 192-86.4 192-192v-640c0-105.6-86.4-192-192-192z",
|
||||
"M512 320l512 320v-640z"
|
||||
],
|
||||
"attrs": [
|
||||
{
|
||||
"fill": "rgb(0, 0, 0)"
|
||||
},
|
||||
{
|
||||
"fill": "rgb(0, 0, 0)"
|
||||
}
|
||||
],
|
||||
"isMulticolor": false,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"icon-collapse-pane-left"
|
||||
],
|
||||
"colorPermutations": {
|
||||
"125525525516161751": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 90,
|
||||
"paths": [
|
||||
"M768 0h256v1024h-256c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192z",
|
||||
"M512 320l-512 320v-640z"
|
||||
],
|
||||
"attrs": [
|
||||
{
|
||||
"fill": "rgb(0, 0, 0)"
|
||||
},
|
||||
{
|
||||
"fill": "rgb(0, 0, 0)"
|
||||
}
|
||||
],
|
||||
"isMulticolor": false,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"icon-collapse-pane-right"
|
||||
],
|
||||
"colorPermutations": {
|
||||
"125525525516161751": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 89,
|
||||
"paths": [
|
||||
"M192.2 576c-0.2 0-0.2 0 0 0l-0.2 448h640v-447.8c0 0 0 0-0.2-0.2h-639.6z",
|
||||
"M978.8 210.8l-165.4-165.4c-25-25-74.2-45.4-109.4-45.4h-576c-70.4 0-128 57.6-128 128v768c0 70.4 57.6 128 128 128v-448c0-35.2 28.8-64 64-64h640c35.2 0 64 28.8 64 64v448c70.4 0 128-57.6 128-128v-576c0-35.2-20.4-84.4-45.2-109.2zM704 256c0 35.2-28.8 64-64 64h-448c-35.2 0-64-28.8-64-64v-192h320v192h128v-192h128v192z"
|
||||
],
|
||||
"attrs": [
|
||||
{
|
||||
"fill": "rgb(0, 0, 0)"
|
||||
},
|
||||
{
|
||||
"fill": "rgb(0, 0, 0)"
|
||||
}
|
||||
],
|
||||
"isMulticolor": false,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"icon-save-v2"
|
||||
],
|
||||
"colorPermutations": {
|
||||
"125525525516161751": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 88,
|
||||
"paths": [
|
||||
"M896 192h-320c-16.4-16.4-96.8-96.8-109.2-109.2l-37.4-37.4c-25-25-74.2-45.4-109.4-45.4h-256c-35.2 0-64 28.8-64 64v384c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v-128c0-70.4-57.6-128-128-128z",
|
||||
"M896 448h-768c-70.4 0-128 57.6-128 128v320c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-320c0-70.4-57.6-128-128-128zM320 896h-128v-320h128v320zM576 896h-128v-320h128v320zM832 896h-128v-320h128v320z"
|
||||
],
|
||||
"attrs": [],
|
||||
"isMulticolor": false,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"icon-dataset"
|
||||
],
|
||||
"colorPermutations": {
|
||||
"125525525516161751": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 87,
|
||||
"paths": [
|
||||
|
Binary file not shown.
@ -88,5 +88,10 @@
|
||||
<glyph unicode="" glyph-name="icon-hourglass" d="M1024 960h-1024c0-282.8 229.2-512 512-512s512 229.2 512 512zM512 576c-102.6 0-199 40-271.6 112.4-41.2 41.2-72 90.2-90.8 143.6h724.6c-18.8-53.4-49.6-102.4-90.8-143.6-72.4-72.4-168.8-112.4-271.4-112.4zM512 448c-282.8 0-512-229.2-512-512h1024c0 282.8-229.2 512-512 512z" />
|
||||
<glyph unicode="" glyph-name="icon-arrows-right-left" d="M1024 448l-448-512v1024zM448 960l-448-512 448-512z" />
|
||||
<glyph unicode="" glyph-name="icon-bell" d="M512-64c106 0 192 86 192 192h-384c0-106 86-192 192-192zM896 512v64c0 212-172 384-384 384s-384-172-384-384v-64c0-70.6-57.4-128-128-128v-128h1024v128c-70.6 0-128 57.4-128 128z" />
|
||||
<glyph unicode="" glyph-name="icon-dataset" d="M896 768h-320c-16.4 16.4-96.8 96.8-109.2 109.2l-37.4 37.4c-25 25-74.2 45.4-109.4 45.4h-256c-35.2 0-64-28.8-64-64v-384c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v128c0 70.4-57.6 128-128 128zM896 512h-768c-70.4 0-128-57.6-128-128v-320c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v320c0 70.4-57.6 128-128 128zM320 64h-128v320h128v-320zM576 64h-128v320h128v-320zM832 64h-128v320h128v-320z" />
|
||||
<glyph unicode="" glyph-name="icon-save" d="M192.2 384c-0.2 0-0.2 0 0 0l-0.2-448h640v447.8c0 0 0 0-0.2 0.2h-639.6zM978.8 749.2l-165.4 165.4c-25 25-74.2 45.4-109.4 45.4h-576c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128v448c0 35.2 28.8 64 64 64h640c35.2 0 64-28.8 64-64v-448c70.4 0 128 57.6 128 128v576c0 35.2-20.4 84.4-45.2 109.2zM704 704c0-35.2-28.8-64-64-64h-448c-35.2 0-64 28.8-64 64v192h320v-192h128v192h128v-192z" />
|
||||
<glyph unicode="" glyph-name="icon-collapse-pane-left" d="M256 960h-256v-1024h256c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM512 640l512-320v640z" />
|
||||
<glyph unicode="" glyph-name="icon-collapse-pane-right" d="M768 960h256v-1024h-256c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192zM512 640l-512-320v640z" />
|
||||
<glyph unicode="" glyph-name="icon-crosshair" d="M514 958c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM860.2 510h-282.2v282.2c69.6-12.8 133.8-46.2 185-97.4 51-51 84.4-115.2 97.2-184.8zM450 792.2v-282.2h-282.2c12.8 69.6 46.2 133.8 97.4 185 51 51 115.2 84.4 184.8 97.2zM167.8 382h282.2v-282.2c-69.6 12.8-133.8 46.2-185 97.4-51 51-84.4 115.2-97.2 184.8zM578 99.8v282.2h282.2c-12.8-69.6-46.2-133.8-97.4-185-51-51-115.2-84.4-184.8-97.2z" />
|
||||
<glyph unicode="" glyph-name="icon-x" d="M384 448l-365.332-365.332c-24.89-24.89-24.89-65.62 0-90.51l37.49-37.49c24.89-24.89 65.62-24.89 90.51 0 0 0 365.332 365.332 365.332 365.332l365.332-365.332c24.89-24.89 65.62-24.89 90.51 0l37.49 37.49c24.89 24.89 24.89 65.62 0 90.51l-365.332 365.332c0 0 365.332 365.332 365.332 365.332 24.89 24.89 24.89 65.62 0 90.51l-37.49 37.49c-24.89 24.89-65.62 24.89-90.51 0 0 0-365.332-365.332-365.332-365.332l-365.332 365.332c-24.89 24.89-65.62 24.89-90.51 0l-37.49-37.49c-24.89-24.89-24.89-65.62 0-90.51 0 0 365.332-365.332 365.332-365.332z" />
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
Binary file not shown.
Binary file not shown.
@ -42,7 +42,11 @@ $ueFooterH: 25px;
|
||||
$ueColMargin: 1.5%;
|
||||
$ueAppLogoW: 105px;
|
||||
$ueEditToolBarH: 25px;
|
||||
$ueBrowseLeftPaneW: 25%;
|
||||
$ueBrowseLeftPaneTreeW: 25%;
|
||||
$ueBrowseRightPaneInspectW: 20%;
|
||||
$ueCollapsedPaneEdgeM: 20px;
|
||||
$uePaneMiniTabH: $ueTopBarH;
|
||||
$uePaneMiniTabW: 9px;
|
||||
$ueEditLeftPaneW: 75%;
|
||||
$treeSearchInputBarH: 25px;
|
||||
$ueTimeControlH: (33px, 20px, 20px);
|
||||
@ -57,7 +61,8 @@ $ueBrowseGridItemBottomBarH: 30px;
|
||||
$itemPadLR: 5px;
|
||||
// Tree
|
||||
$treeVCW: 10px;
|
||||
$treeTypeIconH: 16px;
|
||||
$treeTypeIconH: 1.4em; // was 16px
|
||||
$treeTypeIconHPx: 16px;
|
||||
$treeTypeIconW: 20px;
|
||||
$treeContextTriggerW: 20px;
|
||||
// Tabular
|
||||
|
@ -34,10 +34,6 @@
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.ui-symbol {
|
||||
font-family: 'symbolsfont';
|
||||
}
|
||||
|
||||
/************************** HTML ENTITIES */
|
||||
a {
|
||||
color: $colorA;
|
||||
@ -55,7 +51,7 @@ body, html {
|
||||
color: $colorBodyFg;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
//font-weight: 500;
|
||||
font-weight: 200;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
@ -29,11 +29,14 @@
|
||||
}
|
||||
|
||||
.ui-symbol {
|
||||
font-family: 'symbolsfont';
|
||||
&.type-icon {
|
||||
color: $colorObjHdrIc;
|
||||
}
|
||||
&.icon {
|
||||
color: $colorKey;
|
||||
//position: relative;
|
||||
font-size: inherit;
|
||||
&.alert {
|
||||
color: $colorAlert;
|
||||
&:hover {
|
||||
@ -69,18 +72,32 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
//.tree-item .type-icon {
|
||||
// font-size: 16px; // 16px is crisp size
|
||||
//}
|
||||
|
||||
.l-icon-link:before {
|
||||
content: "\f4";
|
||||
}
|
||||
|
||||
.l-icon-alert {
|
||||
display: none !important; // Remove this when alerts are enabled
|
||||
&:before {
|
||||
color: $colorAlert;
|
||||
content: "!";
|
||||
}
|
||||
}
|
||||
|
||||
// NEW!!
|
||||
.t-item-icon {
|
||||
// Used in grid-item.html, tree-item, inspector location, more?
|
||||
@extend .ui-symbol;
|
||||
@extend .icon;
|
||||
display: inline-block;
|
||||
line-height: normal; // This is Ok for the symbolsfont
|
||||
position: relative;
|
||||
&.l-icon-link {
|
||||
&:before {
|
||||
color: $colorIconLink;
|
||||
content: "\f4";
|
||||
height: auto; width: auto;
|
||||
position: absolute;
|
||||
left: 0; top: 0; right: 0; bottom: 10%;
|
||||
@include transform-origin(bottom, left);
|
||||
@include transform(scale(0.3));
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
107
platform/commonUI/general/res/sass/_inspector.scss
Normal file
107
platform/commonUI/general/res/sass/_inspector.scss
Normal file
@ -0,0 +1,107 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/* Styles for the Inspector pane */
|
||||
|
||||
.l-inspect,
|
||||
.l-inspect table tr td {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.l-inspect {
|
||||
@extend .abs;
|
||||
background: $colorInspectorBg;
|
||||
color: $colorInspectorFg;
|
||||
line-height: 140%;
|
||||
.pane-header {
|
||||
color: pushBack($colorInspectorFg, 20%);
|
||||
font-size: 0.8rem;
|
||||
&:before {
|
||||
color: pushBack($colorInspectorFg, 10%);
|
||||
content:'\e615'; // e615 Crosshair symbol
|
||||
display: inline;
|
||||
font-family: symbolsfont;
|
||||
margin-right: $interiorMargin;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
ul li,
|
||||
em {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
ul li {
|
||||
margin-bottom: $interiorMarginLg;
|
||||
}
|
||||
|
||||
em {
|
||||
@include border-radius($basicCr);
|
||||
background-color: $colorInspectorSectionHeaderBg;
|
||||
color: $colorInspectorSectionHeaderFg;
|
||||
margin-bottom: $interiorMargin;
|
||||
padding: $formTBPad $formLRPad;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.inspector-properties {
|
||||
&:not(.first) {
|
||||
border-top: 1px solid $colorInspectorSectionHeaderBg;
|
||||
}
|
||||
padding: $interiorMarginSm 0;
|
||||
.label {
|
||||
color: $colorInspectorPropName;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.value {
|
||||
color: $colorInspectorPropVal;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.inspector-location {
|
||||
//line-height: 180%;
|
||||
.location-item {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 2px 4px;
|
||||
&:hover {
|
||||
background: $colorItemTreeHoverBg;
|
||||
color: $colorItemTreeHoverFg;
|
||||
.icon {
|
||||
color: $colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:not(.last) .t-object-label .t-title-label:after {
|
||||
color: pushBack($colorInspectorFg, 15%);
|
||||
content: '\3e';
|
||||
display: inline-block;
|
||||
font-family: symbolsfont;
|
||||
font-size: 8px;
|
||||
line-height: inherit;
|
||||
margin-left: $interiorMarginSm;
|
||||
width: 4px;
|
||||
}
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@
|
||||
@import "helpers/bubbles";
|
||||
@import "helpers/splitter";
|
||||
@import "helpers/wait-spinner";
|
||||
@import "properties";
|
||||
@import "inspector";
|
||||
|
||||
/********************************* CONTROLS */
|
||||
@import "controls/breadcrumb";
|
||||
@ -69,7 +69,6 @@
|
||||
@import "lists/tabular";
|
||||
@import "plots/plots-main";
|
||||
@import "iframe";
|
||||
@import "hide-non-functional";
|
||||
@import "views";
|
||||
@import "items/item";
|
||||
@import "mobile/item";
|
||||
|
@ -41,36 +41,41 @@
|
||||
width: $d;
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice($props, $t: 500ms) {
|
||||
@if $t == 0 {
|
||||
@mixin trans-prop-nice($props, $dur: 500ms, $delay: 0) {
|
||||
// Multiple $props must be in parans like this: (left, right)
|
||||
@if $dur == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property($props);
|
||||
@include transition-duration($t);
|
||||
@include transition-duration($dur);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
@include transition-delay($delay);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-fade($t: 0.5s) {
|
||||
@if $t == 0 {
|
||||
@mixin trans-prop-nice-fade($dur: 500ms, $delay: 0) {
|
||||
@if $dur == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property(visibility, opacity, background-color, border-color);
|
||||
@include transition-duration($t);
|
||||
@include transition-property(opacity, background-color, border-color, color);
|
||||
@include transition-duration($dur);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
@include transition-delay($delay);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-resize-h($t: 0.5s) {
|
||||
@mixin trans-prop-nice-resize-h($dur: 500ms, $delay: 0) {
|
||||
@include transition-property(height, bottom, top);
|
||||
@include transition-duration($t);
|
||||
@include transition-duration($dur);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
@include transition-delay($delay);
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-resize-w($t: 0.5s) {
|
||||
@mixin trans-prop-nice-resize-w($dur: 500ms, $delay: 0) {
|
||||
@include transition-property(width, left, right);
|
||||
@include transition-duration($t);
|
||||
@include transition-duration($dur);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
@include transition-delay($delay);
|
||||
}
|
||||
|
||||
@mixin triangle-right($size, $color) {
|
||||
@ -173,31 +178,28 @@
|
||||
}
|
||||
|
||||
@mixin controlGrippy($b, $direction: horizontal, $w: 1px, $style: dotted) {
|
||||
&:before {
|
||||
@include trans-prop-nice("border-color", 0.75s);
|
||||
content: '';
|
||||
display: block;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
//&:before {
|
||||
//@include trans-prop-nice("border-color", 25ms);
|
||||
content: '';
|
||||
display: block;
|
||||
//height: auto;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
|
||||
@if $direction == "horizontal" {
|
||||
border-top: $w $style darken($b, 15%);
|
||||
top: 2px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
@if $direction == "horizontal" {
|
||||
border-top: $w $style darken($b, 15%);
|
||||
top: 2px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
height: 1px;
|
||||
|
||||
} @else if $direction == "vertical" {
|
||||
border-left: $w $style darken($b, 15%);
|
||||
left: 2px;
|
||||
bottom: 5px;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
&:not(.disabled):hover:before {
|
||||
@include trans-prop-nice("border-color", 25ms);
|
||||
border-color: $colorGrippyInteriorHover;
|
||||
} @else if $direction == "vertical" {
|
||||
border-left: $w $style darken($b, 15%);
|
||||
left: 2px;
|
||||
bottom: 5px;
|
||||
top: 5px;
|
||||
width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,6 +275,12 @@
|
||||
@return percentage($d);
|
||||
}
|
||||
|
||||
@function splitterHandleInset($splitterD: 21px, $splitterHandleD: 1px) {
|
||||
// Space to either side of the handle
|
||||
@return ($splitterD - $splitterHandleD) * 0.5;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************** CONTROLS, FORM ELEMENTS */
|
||||
|
||||
@mixin containerBase($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@ -364,10 +372,7 @@
|
||||
/* This doesn't work on an element inside an element with absolute positioning that has height: auto */
|
||||
//position: relative;
|
||||
top: 50%;
|
||||
@include webkitProp(transform, translateY(-50%));
|
||||
//-webkit-transform: translateY(-50%);
|
||||
//-ms-transform: translateY(-50%);
|
||||
//transform: translateY(-50%);
|
||||
@include transform(translateY(-50%));
|
||||
}
|
||||
|
||||
@mixin verticalCenterBlock($holderH, $itemH) {
|
||||
|
@ -22,13 +22,17 @@
|
||||
$baseRatio: 1.5;
|
||||
$pad: $interiorMargin * $baseRatio;
|
||||
|
||||
.s-btn {
|
||||
@include box-sizing(border-box);
|
||||
.s-btn,
|
||||
.s-icon-btn {
|
||||
@include user-select(none);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
height: $btnStdH;
|
||||
line-height: $btnStdH;
|
||||
}
|
||||
|
||||
.s-btn {
|
||||
@include box-sizing(border-box);
|
||||
padding: 0 $pad;
|
||||
font-size: 0.7rem;
|
||||
|
||||
@ -89,6 +93,155 @@ $pad: $interiorMargin * $baseRatio;
|
||||
}
|
||||
}
|
||||
|
||||
.s-icon-btn {
|
||||
@extend .ui-symbol;
|
||||
color: $colorBtnIcon;
|
||||
&:hover {
|
||||
color: lighten($colorBtnIcon, $ltGamma);
|
||||
}
|
||||
}
|
||||
|
||||
.mini-tab {
|
||||
// Meant to be used as pane hide/show control elements in concert with mct-splitter
|
||||
//@extend .ui-symbol;
|
||||
@include desktop {
|
||||
//@include test(green);
|
||||
$iconH: $uePaneMiniTabH;
|
||||
$iconW: $uePaneMiniTabW;
|
||||
$iconInnerLR: 0;
|
||||
$arwD: 9px;
|
||||
$arwOffsetX: 0px;
|
||||
$arwAnimOffsetX: 2px + $iconInnerLR;
|
||||
$cBg: pullForward($colorBodyBg, 15%);
|
||||
$cFg: $cBg;
|
||||
|
||||
|
||||
@include border-radius($basicCr);
|
||||
//@include boxShdw($shdwBtns);
|
||||
@include box-sizing(border-box);
|
||||
@include trans-prop-nice((color, background-color), 100ms);
|
||||
color: $cFg;
|
||||
cursor: pointer;
|
||||
font-family: symbolsfont;
|
||||
font-size: $arwD;
|
||||
display: block;
|
||||
position: absolute;
|
||||
line-height: $iconH;
|
||||
height: $iconH; width: $iconW;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
//background-color: $cBg;
|
||||
color: $colorKey; //pullForward($cFg, $ltGamma);
|
||||
}
|
||||
|
||||
&.collapsed {
|
||||
// State when the pane this element controls has been collapsed
|
||||
@include btnSubtle($colorBtnBg, $colorKey, $colorBtnFg, $colorBtnIcon);
|
||||
&:before { opacity: 0; }
|
||||
&:after { opacity: 1; }
|
||||
&:hover {
|
||||
&:before { opacity: 1; }
|
||||
&:after { opacity: 0; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
//@include test();
|
||||
@include trans-prop-nice((left, right, opacity), 250ms);
|
||||
display: block;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&:before {
|
||||
// Always the arrow icon
|
||||
//@include test(green);
|
||||
//font-size: $arwD;
|
||||
width: $arwD;
|
||||
}
|
||||
&:after {
|
||||
// Always icon; content is set in _layout.scss
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.anchor-left {
|
||||
// |<
|
||||
text-align: right;
|
||||
&:before {
|
||||
content:'\3c'; // Collapse left icon e613
|
||||
right: $iconInnerLR;
|
||||
}
|
||||
//&:hover:before { right: $arwAnimOffsetX; }
|
||||
&.collapsed {
|
||||
@include border-left-radius(0);
|
||||
text-align: left;
|
||||
&:before {
|
||||
content:'\3e';
|
||||
left: $iconInnerLR;
|
||||
}
|
||||
&:hover:before { left: $arwAnimOffsetX; }
|
||||
}
|
||||
}
|
||||
&.anchor-right {
|
||||
// >|
|
||||
text-align: left;
|
||||
&:before {
|
||||
content:'\3e'; // Collapse right icon e614
|
||||
left: $iconInnerLR;
|
||||
}
|
||||
//&:hover:before { left: $arwAnimOffsetX; }
|
||||
&.collapsed {
|
||||
@include border-right-radius(0);
|
||||
&:before {
|
||||
text-align: right;
|
||||
content:'\3c';
|
||||
right: $iconInnerLR;
|
||||
}
|
||||
&:hover:before { right: $arwAnimOffsetX; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mini-tab-icon {
|
||||
// Meant to be used as pane hide/show control elements in concert with mct-splitter
|
||||
//@extend .ui-symbol;
|
||||
@include desktop {
|
||||
$d: $uePaneMiniTabW;
|
||||
//@include trans-prop-nice(transform, 150ms);
|
||||
color: pullForward($colorBodyBg, 15%);
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-family: symbolsfont;
|
||||
font-size: $d;
|
||||
position: absolute;
|
||||
height: $d; width: $d;
|
||||
line-height: $d;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
position: absolute;
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '\78'; // X icon
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $colorKey;
|
||||
//@include transform(scale(1.2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-btn-set {
|
||||
// Buttons that have a very tight conceptual grouping - no internal space between them.
|
||||
// Structure: .btn-set > mct-representation class=first|last > .s-btn
|
||||
|
@ -21,246 +21,239 @@
|
||||
*****************************************************************************/
|
||||
|
||||
.accordion {
|
||||
$accordionHeadH: 18px;
|
||||
margin-top: $interiorMargin;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.accordion-head {
|
||||
$op: 0.2;
|
||||
@include border-radius($basicCr * 0.75);
|
||||
@include box-sizing("border-box");
|
||||
background: rgba($colorBodyFg, $op);
|
||||
cursor: pointer;
|
||||
font-size: 0.75em;
|
||||
line-height: $accordionHeadH;
|
||||
margin-bottom: $interiorMargin;
|
||||
padding: 0 $interiorMargin;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: $accordionHeadH;
|
||||
text-transform: uppercase;
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, $op * 2);
|
||||
}
|
||||
&:after {
|
||||
content: "^";
|
||||
display: block;
|
||||
font-family: 'symbolsfont';
|
||||
font-size: 0.9em;
|
||||
position: absolute;
|
||||
right: $interiorMargin;
|
||||
text-transform: none;
|
||||
top: 0;
|
||||
}
|
||||
&:not(.expanded):after {
|
||||
content: "v";
|
||||
}
|
||||
}
|
||||
.accordion-contents {
|
||||
position: absolute;
|
||||
top: $accordionHeadH + $interiorMargin;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
$accordionHeadH: 18px;
|
||||
margin-top: $interiorMargin;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.accordion-head {
|
||||
$op: 0.2;
|
||||
@include border-radius($basicCr * 0.75);
|
||||
@include box-sizing("border-box");
|
||||
background: rgba($colorBodyFg, $op);
|
||||
cursor: pointer;
|
||||
font-size: 0.75em;
|
||||
line-height: $accordionHeadH;
|
||||
margin-bottom: $interiorMargin;
|
||||
padding: 0 $interiorMargin;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: $accordionHeadH;
|
||||
text-transform: uppercase;
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, $op * 2);
|
||||
}
|
||||
&:after {
|
||||
content: "^";
|
||||
display: block;
|
||||
font-family: 'symbolsfont';
|
||||
font-size: 0.9em;
|
||||
position: absolute;
|
||||
right: $interiorMargin;
|
||||
text-transform: none;
|
||||
top: 0;
|
||||
}
|
||||
&:not(.expanded):after {
|
||||
content: "v";
|
||||
}
|
||||
}
|
||||
.accordion-contents {
|
||||
position: absolute;
|
||||
top: $accordionHeadH + $interiorMargin;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.l-composite-control {
|
||||
vertical-align: middle;
|
||||
&.l-checkbox {
|
||||
.composite-control-label {
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
vertical-align: middle;
|
||||
&.l-checkbox {
|
||||
.composite-control-label {
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-control-group {
|
||||
// Buttons that have a conceptual grouping - internal space between, and a divider between groups.
|
||||
// @include test();
|
||||
@include box-sizing(border-box);
|
||||
border-left: 1px solid $colorInteriorBorder;
|
||||
display: inline-block;
|
||||
padding: 0 $interiorMargin;
|
||||
position: relative;
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
// Buttons that have a conceptual grouping - internal space between, and a divider between groups.
|
||||
// @include test();
|
||||
@include box-sizing(border-box);
|
||||
border-left: 1px solid $colorInteriorBorder;
|
||||
display: inline-block;
|
||||
padding: 0 $interiorMargin;
|
||||
position: relative;
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.l-local-controls {
|
||||
// Control shown when hovering over an object, like plots and imagery
|
||||
// Default position is upper right
|
||||
$p: $interiorMargin;
|
||||
position: absolute;
|
||||
top: $p;
|
||||
right: $p;
|
||||
z-index: 5;
|
||||
// Control shown when hovering over an object, like plots and imagery
|
||||
// Default position is upper right
|
||||
$p: $interiorMargin;
|
||||
position: absolute;
|
||||
top: $p;
|
||||
right: $p;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.s-local-controls {
|
||||
font-size: 0.7rem;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
label.checkbox.custom {
|
||||
$bg: pullForward($colorBodyBg, 10%);
|
||||
$d: $formRowCtrlsH;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
line-height: $d;
|
||||
margin-right: $interiorMargin * 4;
|
||||
padding-left: $d + $interiorMargin;
|
||||
position: relative;
|
||||
vertical-align: middle; // was top
|
||||
em {
|
||||
color: $colorBodyFg;
|
||||
display: inline-block;
|
||||
height: $d;
|
||||
min-width: $d;
|
||||
&:before {
|
||||
@include border-radius($basicCr * .75);
|
||||
background: $bg;
|
||||
//border-bottom: 1px solid lighten($bg, 10%);
|
||||
@include box-shadow(inset rgba(black, 0.4) 0 1px 2px);
|
||||
box-sizing: border-box;
|
||||
content: " ";
|
||||
font-family: 'symbolsfont';
|
||||
font-size: 0.8em;
|
||||
display: inline-block;
|
||||
margin-right: $interiorMargin;
|
||||
height: $d;
|
||||
width: $d;
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
&.no-text {
|
||||
overflow: hidden;
|
||||
margin-right: 0;
|
||||
padding-left: 0;
|
||||
height: $d;
|
||||
width: $d;
|
||||
em {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
input {
|
||||
display: none;
|
||||
&:checked ~ em:before {
|
||||
background: $colorCheck;
|
||||
color: lighten($colorCheck, 50%);
|
||||
content: "2";
|
||||
}
|
||||
}
|
||||
$bg: pullForward($colorBodyBg, 10%);
|
||||
$d: $formRowCtrlsH;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
line-height: $d;
|
||||
margin-right: $interiorMargin * 4;
|
||||
padding-left: $d + $interiorMargin;
|
||||
position: relative;
|
||||
vertical-align: middle; // was top
|
||||
em {
|
||||
color: $colorBodyFg;
|
||||
display: inline-block;
|
||||
height: $d;
|
||||
min-width: $d;
|
||||
&:before {
|
||||
@include border-radius($basicCr * .75);
|
||||
background: $bg;
|
||||
//border-bottom: 1px solid lighten($bg, 10%);
|
||||
@include box-shadow(inset rgba(black, 0.4) 0 1px 2px);
|
||||
box-sizing: border-box;
|
||||
content: " ";
|
||||
font-family: 'symbolsfont';
|
||||
font-size: 0.8em;
|
||||
display: inline-block;
|
||||
margin-right: $interiorMargin;
|
||||
height: $d;
|
||||
width: $d;
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
&.no-text {
|
||||
overflow: hidden;
|
||||
margin-right: 0;
|
||||
padding-left: 0;
|
||||
height: $d;
|
||||
width: $d;
|
||||
em {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
input {
|
||||
display: none;
|
||||
&:checked ~ em:before {
|
||||
background: $colorCheck;
|
||||
color: lighten($colorCheck, 50%);
|
||||
content: "2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-labeled {
|
||||
margin-left: $interiorMargin;
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
&.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
margin-left: $interiorMargin;
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
&.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.s-menu-btn label.checkbox.custom {
|
||||
margin-left: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.item .checkbox {
|
||||
&.checked label {
|
||||
@include box-shadow(none);
|
||||
border-bottom: none;
|
||||
}
|
||||
&.checked label {
|
||||
@include box-shadow(none);
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.context-available {
|
||||
$c: $colorKey;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, 10%);
|
||||
}
|
||||
$c: $colorKey;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.view-switcher {
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
}
|
||||
|
||||
/******************************************************** OBJECT-HEADER */
|
||||
.object-header {
|
||||
//@include test();
|
||||
font-size: 1em;
|
||||
//@include test();
|
||||
font-size: 1em;
|
||||
|
||||
//> .title-label,
|
||||
//> .type-icon,
|
||||
//> .context-available {
|
||||
// //@include tmpBorder(#6666ff);
|
||||
// //vertical-align: middle;
|
||||
//}
|
||||
> .type-icon {
|
||||
color: $colorObjHdrIc;
|
||||
font-size: 120%;
|
||||
float: left;
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
> .type-icon {
|
||||
color: $colorObjHdrIc;
|
||||
font-size: 120%;
|
||||
float: left;
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
.l-elem-wrapper {
|
||||
//@include test(#66f, 0.2);
|
||||
@include justify-content(flex-start);
|
||||
mct-representation {
|
||||
// Holds the context-available item
|
||||
// Must have min-width to make flex work properly
|
||||
// in Safari
|
||||
min-width: 0.7em;
|
||||
}
|
||||
}
|
||||
|
||||
.l-elem-wrapper {
|
||||
//@include test(#66f, 0.2);
|
||||
@include webkitProp(justify-content, flex-start);
|
||||
mct-representation {
|
||||
// Holds the context-available item
|
||||
// Must have min-width to make flex work properly
|
||||
// in Safari
|
||||
min-width: 0.7em;
|
||||
}
|
||||
}
|
||||
.action {
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
.action {
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
.title-label {
|
||||
//@include test(green, 0.9);
|
||||
color: $colorObjHdrTxt;
|
||||
@include ellipsize();
|
||||
//color: pushBack($colorBodyFg, 40%);
|
||||
@include webkitProp(flex, '0 1 auto');
|
||||
padding-right: 0.35em; // For context arrow. Done with em's so pad is relative to the scale of the text.
|
||||
//position: relative;
|
||||
}
|
||||
|
||||
.title-label {
|
||||
//@include test(green, 0.9);
|
||||
color: $colorObjHdrTxt;
|
||||
@include ellipsize();
|
||||
//color: pushBack($colorBodyFg, 40%);
|
||||
@include webkitProp(flex, '0 1 auto');
|
||||
padding-right: 0.35em; // For context arrow. Done with em's so pad is relative to the scale of the text.
|
||||
//position: relative;
|
||||
}
|
||||
.context-available {
|
||||
font-size: 0.7em;
|
||||
@include webkitProp(flex, '0 0 1');
|
||||
//margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
.context-available {
|
||||
font-size: 0.7em;
|
||||
@include webkitProp(flex, '0 0 1');
|
||||
//margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
.context-available {
|
||||
@include trans-prop-nice(opacity, 0.25s);
|
||||
opacity: 0;
|
||||
}
|
||||
&:hover {
|
||||
.context-available {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include desktop {
|
||||
.context-available {
|
||||
@include trans-prop-nice(opacity, 0.25s);
|
||||
opacity: 0;
|
||||
}
|
||||
&:hover {
|
||||
.context-available {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** PROGRESS BAR */
|
||||
@ -280,20 +273,20 @@ label.checkbox.custom {
|
||||
|
||||
.l-progress-bar {
|
||||
// Assume will be determinate by default
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.progress-amt-holder {
|
||||
.progress-amt-holder {
|
||||
@include absPosDefault(1px);
|
||||
}
|
||||
.progress-amt,
|
||||
.progress-amt:before,
|
||||
.progress-amt:after {
|
||||
@include absPosDefault();
|
||||
@include absPosDefault();
|
||||
display: block;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.progress-amt {
|
||||
right: auto; // Allow inline width to control }
|
||||
@ -311,10 +304,10 @@ label.checkbox.custom {
|
||||
@include boxIncised(0.3, 4px);
|
||||
background: $colorProgressBarOuter;
|
||||
//border:1px solid $colorProgressBarOuter;
|
||||
.progress-amt {
|
||||
@include border-radius($basicCr);
|
||||
@include boxShdw();
|
||||
@include border-radius($basicCr - 1);
|
||||
.progress-amt {
|
||||
@include border-radius($basicCr);
|
||||
@include boxShdw();
|
||||
@include border-radius($basicCr - 1);
|
||||
@include trans-prop-nice(width);
|
||||
&:before {
|
||||
background-color: $colorProgressBarAmt;
|
||||
@ -325,7 +318,7 @@ label.checkbox.custom {
|
||||
transparent 5%, rgba(#fff,0.25) 30%, transparent 100%
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.indeterminate) {
|
||||
.progress-amt:before {
|
||||
@ -348,187 +341,185 @@ label.checkbox.custom {
|
||||
/******************************************************** SLIDERS */
|
||||
|
||||
.slider {
|
||||
$knobH: 100%; //14px;
|
||||
.slot {
|
||||
// @include border-radius($basicCr * .75);
|
||||
//@include sliderTrack();
|
||||
width: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.knob {
|
||||
//@include btnSubtle();
|
||||
//@include controlGrippy(rgba(black, 0.3), vertical, 1px, solid);
|
||||
@include trans-prop-nice-fade(.25s);
|
||||
background-color: $sliderColorKnob;
|
||||
&:hover {
|
||||
background-color: $sliderColorKnobHov;
|
||||
}
|
||||
position: absolute;
|
||||
height: $knobH;
|
||||
width: $sliderKnobW;
|
||||
top: 0;
|
||||
auto: 0;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
}
|
||||
.knob-l {
|
||||
@include border-left-radius($sliderKnobW);
|
||||
cursor: w-resize;
|
||||
}
|
||||
.knob-r {
|
||||
@include border-right-radius($sliderKnobW);
|
||||
cursor: e-resize;
|
||||
}
|
||||
.range {
|
||||
@include trans-prop-nice-fade(.25s);
|
||||
background-color: $sliderColorRange;
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
top: 0; //$tbOffset;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: auto;
|
||||
&:hover {
|
||||
background-color: $sliderColorRangeHov;
|
||||
}
|
||||
}
|
||||
$knobH: 100%; //14px;
|
||||
.slot {
|
||||
// @include border-radius($basicCr * .75);
|
||||
//@include sliderTrack();
|
||||
width: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.knob {
|
||||
@include trans-prop-nice-fade(.25s);
|
||||
background-color: $sliderColorKnob;
|
||||
&:hover {
|
||||
background-color: $sliderColorKnobHov;
|
||||
}
|
||||
position: absolute;
|
||||
height: $knobH;
|
||||
width: $sliderKnobW;
|
||||
top: 0;
|
||||
auto: 0;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
}
|
||||
.knob-l {
|
||||
@include border-left-radius($sliderKnobW);
|
||||
cursor: w-resize;
|
||||
}
|
||||
.knob-r {
|
||||
@include border-right-radius($sliderKnobW);
|
||||
cursor: e-resize;
|
||||
}
|
||||
.range {
|
||||
@include trans-prop-nice-fade(.25s);
|
||||
background-color: $sliderColorRange;
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
top: 0; //$tbOffset;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: auto;
|
||||
&:hover {
|
||||
background-color: $sliderColorRangeHov;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** DATETIME PICKER */
|
||||
.l-datetime-picker {
|
||||
$r1H: 15px;
|
||||
@include user-select(none);
|
||||
font-size: 0.8rem;
|
||||
padding: $interiorMarginLg !important;
|
||||
width: 230px;
|
||||
.l-month-year-pager {
|
||||
$pagerW: 20px;
|
||||
//@include test();
|
||||
//font-size: 0.8rem;
|
||||
height: $r1H;
|
||||
margin-bottom: $interiorMargin;
|
||||
position: relative;
|
||||
.pager,
|
||||
.val {
|
||||
//@include test(red);
|
||||
@extend .abs;
|
||||
}
|
||||
.pager {
|
||||
width: $pagerW;
|
||||
@extend .ui-symbol;
|
||||
&.prev {
|
||||
right: auto;
|
||||
&:before {
|
||||
content: "\3c";
|
||||
}
|
||||
}
|
||||
&.next {
|
||||
left: auto;
|
||||
text-align: right;
|
||||
&:before {
|
||||
content: "\3e";
|
||||
}
|
||||
}
|
||||
}
|
||||
.val {
|
||||
text-align: center;
|
||||
left: $pagerW + $interiorMargin;
|
||||
right: $pagerW + $interiorMargin;
|
||||
}
|
||||
}
|
||||
.l-calendar,
|
||||
.l-time-selects {
|
||||
border-top: 1px solid $colorInteriorBorder
|
||||
}
|
||||
.l-time-selects {
|
||||
line-height: $formInputH;
|
||||
}
|
||||
$r1H: 15px;
|
||||
@include user-select(none);
|
||||
font-size: 0.8rem;
|
||||
padding: $interiorMarginLg !important;
|
||||
width: 230px;
|
||||
.l-month-year-pager {
|
||||
$pagerW: 20px;
|
||||
//@include test();
|
||||
//font-size: 0.8rem;
|
||||
height: $r1H;
|
||||
margin-bottom: $interiorMargin;
|
||||
position: relative;
|
||||
.pager,
|
||||
.val {
|
||||
//@include test(red);
|
||||
@extend .abs;
|
||||
}
|
||||
.pager {
|
||||
width: $pagerW;
|
||||
@extend .ui-symbol;
|
||||
&.prev {
|
||||
right: auto;
|
||||
&:before {
|
||||
content: "\3c";
|
||||
}
|
||||
}
|
||||
&.next {
|
||||
left: auto;
|
||||
text-align: right;
|
||||
&:before {
|
||||
content: "\3e";
|
||||
}
|
||||
}
|
||||
}
|
||||
.val {
|
||||
text-align: center;
|
||||
left: $pagerW + $interiorMargin;
|
||||
right: $pagerW + $interiorMargin;
|
||||
}
|
||||
}
|
||||
.l-calendar,
|
||||
.l-time-selects {
|
||||
border-top: 1px solid $colorInteriorBorder
|
||||
}
|
||||
.l-time-selects {
|
||||
line-height: $formInputH;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** CALENDAR */
|
||||
.l-calendar {
|
||||
$colorMuted: pushBack($colorMenuFg, 30%);
|
||||
ul.l-cal-row {
|
||||
@include display-flex;
|
||||
@include flex-flow(row nowrap);
|
||||
margin-top: 1px;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
li {
|
||||
@include flex(1 0);
|
||||
//@include test();
|
||||
margin-left: 1px;
|
||||
padding: $interiorMargin;
|
||||
text-align: center;
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
&.l-header li {
|
||||
color: $colorMuted;
|
||||
}
|
||||
&.l-body li {
|
||||
@include trans-prop-nice(background-color, .25s);
|
||||
cursor: pointer;
|
||||
&.in-month {
|
||||
background-color: $colorCalCellInMonthBg;
|
||||
}
|
||||
.sub {
|
||||
color: $colorMuted;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
&.selected {
|
||||
background: $colorCalCellSelectedBg;
|
||||
color: $colorCalCellSelectedFg;
|
||||
.sub {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: $colorCalCellHovBg;
|
||||
color: $colorCalCellHovFg;
|
||||
.sub {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$colorMuted: pushBack($colorMenuFg, 30%);
|
||||
ul.l-cal-row {
|
||||
@include display-flex;
|
||||
@include flex-flow(row nowrap);
|
||||
margin-top: 1px;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
li {
|
||||
@include flex(1 0);
|
||||
//@include test();
|
||||
margin-left: 1px;
|
||||
padding: $interiorMargin;
|
||||
text-align: center;
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
&.l-header li {
|
||||
color: $colorMuted;
|
||||
}
|
||||
&.l-body li {
|
||||
@include trans-prop-nice(background-color, .25s);
|
||||
cursor: pointer;
|
||||
&.in-month {
|
||||
background-color: $colorCalCellInMonthBg;
|
||||
}
|
||||
.sub {
|
||||
color: $colorMuted;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
&.selected {
|
||||
background: $colorCalCellSelectedBg;
|
||||
color: $colorCalCellSelectedFg;
|
||||
.sub {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: $colorCalCellHovBg;
|
||||
color: $colorCalCellHovFg;
|
||||
.sub {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** BROWSER ELEMENTS */
|
||||
|
||||
@include desktop {
|
||||
::-webkit-scrollbar {
|
||||
@include border-radius(2px);
|
||||
@include box-sizing(border-box);
|
||||
@include box-shadow(inset $scrollbarTrackShdw);
|
||||
background-color: $scrollbarTrackColorBg;
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
@include border-radius(2px);
|
||||
@include box-sizing(border-box);
|
||||
@include box-shadow(inset $scrollbarTrackShdw);
|
||||
background-color: $scrollbarTrackColorBg;
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
$bg: $scrollbarThumbColor;
|
||||
$hc: $scrollbarThumbColorHov;
|
||||
$gr: 5%;
|
||||
@include background-image(linear-gradient(lighten($bg, $gr), $bg 20px));
|
||||
@include border-radius(2px);
|
||||
@include box-sizing(border-box);
|
||||
//@include boxShdwSubtle();
|
||||
//border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($hc, $gr), $hc 20px));
|
||||
}
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
$bg: $scrollbarThumbColor;
|
||||
$hc: $scrollbarThumbColorHov;
|
||||
$gr: 5%;
|
||||
@include background-image(linear-gradient(lighten($bg, $gr), $bg 20px));
|
||||
@include border-radius(2px);
|
||||
@include box-sizing(border-box);
|
||||
//@include boxShdwSubtle();
|
||||
//border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($hc, $gr), $hc 20px));
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: $scrollbarTrackColorBg;
|
||||
}
|
||||
}
|
||||
::-webkit-scrollbar-corner {
|
||||
background: $scrollbarTrackColorBg;
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
.l-tree-item-flat-list {
|
||||
// For lists of tree-items that are flat. Remove margin, etc. normally needed for the expansion arrow.
|
||||
.tree-item {
|
||||
.label {
|
||||
.t-object-label {
|
||||
left: $interiorMargin !important;
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,11 @@
|
||||
}
|
||||
|
||||
&.create-btn {
|
||||
&:before {
|
||||
content:'\2b';
|
||||
display: inline;
|
||||
font-family: symbolsfont;
|
||||
}
|
||||
.title-label {
|
||||
font-size: 1rem;
|
||||
}
|
||||
@ -83,7 +88,7 @@
|
||||
@include menuUlReset();
|
||||
li {
|
||||
@include box-sizing(border-box);
|
||||
border-top: 1px solid lighten($colorMenuBg, 20%);
|
||||
border-top: 1px solid pullForward($colorMenuBg, 10%);
|
||||
color: pullForward($colorMenuBg, 60%);
|
||||
line-height: $menuLineH;
|
||||
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
|
||||
|
@ -19,68 +19,114 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.split-layout {
|
||||
$b: pullForward($colorBodyBg, $contrastRatioPercent);
|
||||
|
||||
.splitter {
|
||||
background-color: $b;
|
||||
@include border-radius($splitterEndCr);
|
||||
@include boxShdw($splitterShdw);
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
//@if $colorSplitterHover != 'none' {
|
||||
&:hover {
|
||||
background-color: $colorSplitterHover;
|
||||
}
|
||||
//}
|
||||
}
|
||||
&.horizontal {
|
||||
// Slides vertically up and down, splitting the element horizontally
|
||||
overflow: hidden; // Suppress overall scroll; each internal pane handles its own overflow
|
||||
.pane {
|
||||
left: 0;
|
||||
right: 0;
|
||||
&.top {
|
||||
bottom: auto;
|
||||
}
|
||||
&.bottom {
|
||||
top: auto;
|
||||
}
|
||||
}
|
||||
>.splitter {
|
||||
@include controlGrippy($colorSplitterInterior, horizontal);
|
||||
cursor: row-resize;
|
||||
left: 0; right: 0;
|
||||
width: auto;
|
||||
height: $splitterW;
|
||||
}
|
||||
}
|
||||
&.vertical {
|
||||
// Slides horizontally left to right, splitting the element vertically
|
||||
.pane {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
&.left {
|
||||
right: auto;
|
||||
}
|
||||
&.right {
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
>.splitter {
|
||||
@include controlGrippy($colorBodyBg, vertical);
|
||||
bottom: 0;
|
||||
cursor: col-resize;
|
||||
width: $splitterW;
|
||||
}
|
||||
}
|
||||
.splitter {
|
||||
// Redo the splitter.
|
||||
// New look is a simple line.
|
||||
// Main width is used to provide a good click area, and is always transparent
|
||||
// :after will be a positioned and colored element that is the handle
|
||||
|
||||
//@include test(red);
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
&:after {
|
||||
// The handle
|
||||
content:"";
|
||||
pointer-events: none;
|
||||
@include absPosDefault(0);
|
||||
background: $colorSplitterBg;
|
||||
display: block;
|
||||
|
||||
@if $splitterEndCr != 'none' {
|
||||
@include border-radius($splitterEndCr);
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
//@include test();
|
||||
&:after {
|
||||
background-color: $colorSplitterActive !important;
|
||||
}
|
||||
}
|
||||
|
||||
@if $colorSplitterHover != 'none' {
|
||||
&:not(:active) {
|
||||
&:hover {
|
||||
&:after {
|
||||
background-color: $colorSplitterHover !important;
|
||||
@include trans-prop-nice(background-color, 150ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.browse-area .splitter {
|
||||
top: $ueTopBarH + $interiorMarginLg;
|
||||
.split-layout {
|
||||
$inset: splitterHandleInset($splitterD,$splitterHandleD);
|
||||
&.horizontal {
|
||||
// Slides vertically up and down, splitting the element horizontally
|
||||
overflow: hidden; // Suppress overall scroll; each internal pane handles its own overflow
|
||||
.pane {
|
||||
left: 0;
|
||||
right: 0;
|
||||
&.top {
|
||||
bottom: auto;
|
||||
}
|
||||
&.bottom {
|
||||
top: auto;
|
||||
}
|
||||
}
|
||||
>.splitter {
|
||||
cursor: row-resize;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: $splitterD;
|
||||
&:after {
|
||||
top: $inset; bottom: $inset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
// Slides horizontally left to right, splitting the element vertically
|
||||
.pane {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
&.left {
|
||||
right: auto;
|
||||
}
|
||||
&.right {
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
>.splitter {
|
||||
cursor: col-resize;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
&:not(.flush-right) {
|
||||
width: $splitterD;
|
||||
&:after {
|
||||
left: $inset; right: $inset;
|
||||
}
|
||||
}
|
||||
&.flush-right {
|
||||
width: ceil($splitterD / 2);
|
||||
&:after {
|
||||
background-color: transparent;
|
||||
left: auto; right: 0; width: $splitterHandleD;
|
||||
}
|
||||
&.edge-shdw {
|
||||
@include background-image(linear-gradient(90deg, rgba(black, 0) 40%, rgba(black, 0.05) 70%, rgba(black, 0.2) 100%));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*.browse-area .splitter {
|
||||
top: 0; //$ueTopBarH + $interiorMarginLg;
|
||||
}
|
||||
|
||||
.edit-area .splitter {
|
||||
top: 0;
|
||||
}
|
||||
}*/
|
||||
|
@ -86,27 +86,16 @@
|
||||
//top: $ueBrowseGridItemTopBarH; bottom: $ueBrowseGridItemBottomBarH; //
|
||||
line-height: $lh;
|
||||
z-index: 1;
|
||||
.item-type {
|
||||
//@include trans-prop-nice("color", $transTime);
|
||||
@include absPosDefault($iconMargin, false);
|
||||
//@include test(red);
|
||||
//color: $colorItemIc;
|
||||
text-align: center;
|
||||
.item-type,
|
||||
.t-item-icon {
|
||||
//@include test();
|
||||
@include transform(translateX(-50%) translateY(-55%));
|
||||
position: absolute;
|
||||
top: 50%; left: 50%;
|
||||
//height: $iconD; width: $iconD;
|
||||
font-size: $iconD * 0.95; //6em;
|
||||
line-height: $iconD;
|
||||
bottom: auto;
|
||||
height: $iconD;
|
||||
top: $iconMargin - 10;
|
||||
.l-icon-link {
|
||||
color: $colorIconLink;
|
||||
height: auto;
|
||||
line-height: 100%;
|
||||
position: absolute;
|
||||
font-size: 0.3em;
|
||||
left: 0px;
|
||||
bottom: 10px;
|
||||
z-index: 2;
|
||||
}
|
||||
//line-height: normal;
|
||||
//text-align: center;
|
||||
}
|
||||
.item-open {
|
||||
@include trans-prop-nice("opacity", $transTime);
|
||||
|
@ -49,18 +49,11 @@
|
||||
|
||||
}
|
||||
.item-main {
|
||||
.item-type {
|
||||
//@include test(blue);
|
||||
.item-type,
|
||||
.t-item-icon {
|
||||
font-size: $mobileListIconSize;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
line-height: 100%;
|
||||
text-align: left;
|
||||
width: $mobileListIconSize;
|
||||
.l-icon-link {
|
||||
bottom: 0;
|
||||
}
|
||||
left: $interiorMarginLg + $interiorMargin;
|
||||
line-height: normal;
|
||||
}
|
||||
.item-open {
|
||||
display: block;
|
||||
|
@ -32,7 +32,7 @@
|
||||
background-color: $colorMobilePaneLeft;
|
||||
}
|
||||
|
||||
.pane.right-repr {
|
||||
.pane.right.items {
|
||||
//@include test();
|
||||
@include slMenuTransitions;
|
||||
margin-left: 0 !important;
|
||||
@ -42,78 +42,66 @@
|
||||
}
|
||||
}
|
||||
|
||||
.user-environ .browse-area,
|
||||
.user-environ .edit-area,
|
||||
.user-environ .editor {
|
||||
top: 0; left: 0; right: 0; bottom: $ueFooterH;
|
||||
}
|
||||
|
||||
.holder.l-mobile {
|
||||
top: $bodyMargin !important;
|
||||
.holder.holder-create-and-search {
|
||||
right: $bodyMargin !important;
|
||||
bottom: $bodyMargin !important;
|
||||
left: $bodyMargin !important;
|
||||
}
|
||||
|
||||
// When the tree is hidden, these are the
|
||||
|
||||
// When the tree is hidden, these are the
|
||||
// classes used for the left menu and the
|
||||
// right representation.
|
||||
.browse-hidetree {
|
||||
@include user-select(none);
|
||||
.pane-tree-hidden {
|
||||
// Sets the left tree menu when the tree
|
||||
// is hidden.
|
||||
.pane.left.treeview {
|
||||
opacity: 0;
|
||||
right: 100% !important;
|
||||
width: auto !important;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
@include trans-prop-nice(opacity, 150ms);
|
||||
//right: 100% !important;
|
||||
//width: auto !important;
|
||||
//overflow-y: hidden;
|
||||
//overflow-x: hidden;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
// Sets the right represenation when
|
||||
// the tree is hidden.
|
||||
.pane.right-repr {
|
||||
.pane.right.items {
|
||||
left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.browse-showtree {
|
||||
.pane-tree-showing {
|
||||
// NOTE: DISABLED SELECTION
|
||||
// Selection disabled in both panes
|
||||
// causing cut/copy/paste menu to
|
||||
// not appear. Should me moved in
|
||||
// future to properly work
|
||||
@include user-select(none);
|
||||
//@include user-select(none);
|
||||
|
||||
// Sets the left tree menu when the tree is shown.
|
||||
.pane.left.treeview {
|
||||
@include trans-prop-nice(opacity, .4s);
|
||||
@include trans-prop-nice(opacity, 250ms, $delay: 250ms);
|
||||
@include background-image(linear-gradient(90deg, rgba(black, 0) 98%, rgba(black, 0.3) 100%));
|
||||
opacity: 1;
|
||||
display: block !important;
|
||||
//width: auto !important; // CH CO
|
||||
right: auto !important;
|
||||
width: $proporMenuWithView !important;
|
||||
}
|
||||
// Sets the right representation when the tree is shown.
|
||||
.pane.right-repr {
|
||||
.pane.right.items {
|
||||
left: $proporMenuWithView !important;
|
||||
//width: auto !important;
|
||||
|
||||
//left: 0 !important;
|
||||
//transform: translateX($proporMenuWithView);
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-menu-icon {
|
||||
.toggle-tree {
|
||||
color: $colorKey !important;
|
||||
font-size: 110%;
|
||||
position: absolute;
|
||||
top: $bodyMargin + 2;
|
||||
left: $bodyMargin;
|
||||
&:after {
|
||||
content:'m' !important;
|
||||
font-family: symbolsfont;
|
||||
}
|
||||
}
|
||||
|
||||
.object-browse-bar {
|
||||
//@include test();
|
||||
left: 30px !important;
|
||||
left: 45px !important;
|
||||
.context-available {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
@ -153,13 +141,13 @@
|
||||
}
|
||||
|
||||
@include phonePortrait {
|
||||
.browse-showtree {
|
||||
.pane-tree-showing {
|
||||
.pane.left.treeview {
|
||||
width: $proporMenuOnly !important;
|
||||
}
|
||||
.pane.right-repr {
|
||||
.pane.right.items {
|
||||
left: 0 !important;
|
||||
@include webkitProp(transform, translateX($proporMenuOnly));
|
||||
@include transform(translateX($proporMenuOnly));
|
||||
#content-area {
|
||||
opacity: 0;
|
||||
}
|
||||
|
@ -37,21 +37,18 @@
|
||||
//@include test(red);
|
||||
position: absolute;
|
||||
font-size: 1.1em;
|
||||
height: $mobileTreeItemH;
|
||||
line-height: inherit;
|
||||
right: 0px;
|
||||
width: $mobileTreeRightArrowW;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.label {
|
||||
.label,
|
||||
.t-object-label {
|
||||
left: 0;
|
||||
right: $mobileTreeRightArrowW + $interiorMargin; // Allows tree item name to stop prior to the arrow
|
||||
line-height: $mobileTreeItemH;
|
||||
//font-size: 1.1em; // CH CO
|
||||
.type-icon {
|
||||
@include verticalCenterBlock($mobileTreeItemH, $treeTypeIconH);
|
||||
}
|
||||
.title-label {
|
||||
}
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,6 @@ ul.tree {
|
||||
font-size: 0.75em;
|
||||
width: $treeVCW;
|
||||
$runningItemW: $interiorMargin + $treeVCW;
|
||||
// NOTE: [Mobile] Removed Hover on Mobile
|
||||
@include desktop {
|
||||
&:hover {
|
||||
color: $colorItemTreeVCHover !important;
|
||||
@ -60,25 +59,34 @@ ul.tree {
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
.label,
|
||||
.t-object-label {
|
||||
display: block;
|
||||
// @include test(orange);
|
||||
@include absPosDefault();
|
||||
//left: $runningItemW + $interiorMargin; // Adding pad to left to make room for link icon
|
||||
line-height: $menuLineH;
|
||||
//left: $runningItemW;
|
||||
|
||||
.t-item-icon {
|
||||
@include txtShdwSubtle($shdwItemTreeIcon);
|
||||
font-size: $treeTypeIconH;
|
||||
color: $colorItemTreeIcon;
|
||||
position: absolute;
|
||||
left: $interiorMargin;
|
||||
top: 50%;
|
||||
width: $treeTypeIconH;
|
||||
@include transform(translateY(-50%));
|
||||
}
|
||||
|
||||
.type-icon {
|
||||
//@include absPosDefault(0, false);
|
||||
$d: $treeTypeIconH; // 16px is crisp size
|
||||
$d: $treeTypeIconH;
|
||||
@include txtShdwSubtle($shdwItemTreeIcon);
|
||||
font-size: $d;
|
||||
font-size: $treeTypeIconH;
|
||||
color: $colorItemTreeIcon;
|
||||
left: $interiorMargin;
|
||||
position: absolute;
|
||||
@include verticalCenterBlock($menuLineHPx, $d);
|
||||
@include verticalCenterBlock($menuLineHPx, $treeTypeIconHPx);
|
||||
line-height: 100%;
|
||||
right: auto; width: $d;
|
||||
right: auto; width: $treeTypeIconH;
|
||||
|
||||
.icon {
|
||||
&.l-icon-link,
|
||||
@ -100,7 +108,8 @@ ul.tree {
|
||||
}
|
||||
}
|
||||
}
|
||||
.title-label {
|
||||
.title-label,
|
||||
.t-title-label {
|
||||
@include absPosDefault();
|
||||
display: block;
|
||||
left: $runningItemW + ($interiorMargin * 3);
|
||||
@ -116,7 +125,7 @@ ul.tree {
|
||||
.view-control {
|
||||
color: $colorItemTreeSelectedVC;
|
||||
}
|
||||
.label .type-icon {
|
||||
.t-object-label .t-item-icon {
|
||||
color: $colorItemTreeSelectedFg; //$colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
@ -125,9 +134,9 @@ ul.tree {
|
||||
// NOTE: [Mobile] Removed Hover on Mobile
|
||||
@include desktop {
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, 0.1); //lighten($colorBodyBg, 5%);
|
||||
color: pullForward($colorBodyFg, 20%);
|
||||
.icon {
|
||||
background: $colorItemTreeHoverBg;
|
||||
color: $colorItemTreeHoverFg;
|
||||
.t-item-icon {
|
||||
color: $colorItemTreeIconHover;
|
||||
}
|
||||
}
|
||||
@ -152,7 +161,7 @@ ul.tree {
|
||||
}
|
||||
|
||||
.tree-item {
|
||||
.label {
|
||||
.t-object-label {
|
||||
left: $interiorMargin + $treeVCW;
|
||||
}
|
||||
}
|
@ -29,13 +29,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
.holder-all {
|
||||
/*.holder-all {
|
||||
$myM: 0; // $interiorMarginSm;
|
||||
top: $myM;
|
||||
right: $myM;
|
||||
bottom: $myM;
|
||||
left: $myM;
|
||||
}
|
||||
}*/
|
||||
|
||||
.browse-area,
|
||||
.edit-area,
|
||||
@ -96,12 +96,8 @@
|
||||
|
||||
.user-environ {
|
||||
.browse-area,
|
||||
.edit-area,
|
||||
.editor {
|
||||
top: $bodyMargin + $ueTopBarH + ($interiorMargin);
|
||||
right: $bodyMargin;
|
||||
bottom: $ueFooterH + $bodyMargin;
|
||||
left: $bodyMargin;
|
||||
top: 0; left: 0; right: 0; bottom: $ueFooterH;
|
||||
}
|
||||
|
||||
.browse-area,
|
||||
@ -115,31 +111,51 @@
|
||||
.edit-area {
|
||||
$tbH: $btnToolbarH + $interiorMargin;
|
||||
top: $bodyMargin + $ueTopBarEditH + ($interiorMargin);
|
||||
left: $bodyMargin;
|
||||
right: $bodyMargin;
|
||||
bottom: $bodyMargin + $ueFooterH;
|
||||
.tool-bar {
|
||||
bottom: auto;
|
||||
height: $tbH;
|
||||
line-height: $btnToolbarH;
|
||||
}
|
||||
.work-area {
|
||||
.object-holder.work-area {
|
||||
top: $tbH + $interiorMargin * 2;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.ue-bottom-bar {
|
||||
//@include absPosDefault($bodyMargin);
|
||||
@include absPosDefault(0); // New status bar design
|
||||
top: auto;
|
||||
height: $ueFooterH;
|
||||
.status-holder {
|
||||
//right: $ueAppLogoW + $bodyMargin; New status bar design
|
||||
z-index: 1;
|
||||
}
|
||||
.app-logo {
|
||||
left: auto;
|
||||
width: $ueAppLogoW;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
// from _bottom-bar.scss
|
||||
.ue-bottom-bar {
|
||||
@include absPosDefault(0);// New status bar design
|
||||
top: auto;
|
||||
height: $ueFooterH;
|
||||
line-height: $ueFooterH - ($interiorMargin * 2);
|
||||
background: $colorFooterBg;
|
||||
color: lighten($colorBodyBg, 30%);
|
||||
font-size: .7rem;
|
||||
|
||||
.status-holder {
|
||||
@include box-sizing(border-box);
|
||||
@include absPosDefault($interiorMargin);
|
||||
@include ellipsize();
|
||||
//line-height: $ueFooterH - ($interiorMargin * 2);
|
||||
right: 120px;
|
||||
text-transform: uppercase;
|
||||
z-index: 1;
|
||||
}
|
||||
.app-logo {
|
||||
@include box-sizing(border-box);
|
||||
@include absPosDefault($interiorMargin);
|
||||
cursor: pointer;
|
||||
left: auto;
|
||||
width: $ueAppLogoW;
|
||||
z-index: 2;
|
||||
&.logo-openmctweb {
|
||||
background: url($dirImgs + 'logo-openmctweb.svg') no-repeat center center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cols {
|
||||
@ -205,10 +221,19 @@
|
||||
|
||||
.browse-mode {
|
||||
.split-layout {
|
||||
.split-pane-component.pane.left {
|
||||
min-width: 150px;
|
||||
max-width: 800px;
|
||||
width: $ueBrowseLeftPaneW;
|
||||
.split-pane-component.pane {
|
||||
//@include test(green);
|
||||
&.treeview.left {
|
||||
min-width: 150px;
|
||||
max-width: 800px;
|
||||
width: $ueBrowseLeftPaneTreeW;
|
||||
}
|
||||
&.t-inspect.right {
|
||||
min-width: 200px;
|
||||
max-width: 600px;
|
||||
//padding-left: $ueCollapsedPaneEdgeM; // Allow room for mini-tab element
|
||||
width: $ueBrowseRightPaneInspectW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -226,16 +251,33 @@
|
||||
}
|
||||
|
||||
.pane {
|
||||
@include box-sizing(border-box);
|
||||
position: absolute;
|
||||
|
||||
.pane-header {
|
||||
text-transform: uppercase;
|
||||
height: $ueTopBarH;
|
||||
line-height: $ueTopBarH;
|
||||
margin-bottom: $interiorMargin;
|
||||
}
|
||||
|
||||
.primary-pane {
|
||||
// Need to lift up this pane to ensure that 'collapsed' panes don't block user interactions
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&.treeview.left {
|
||||
.create-btn-holder {
|
||||
bottom: auto;
|
||||
top: 0;
|
||||
height: $ueTopBarH;
|
||||
.wrapper.menu-element {
|
||||
position: absolute;
|
||||
bottom: $interiorMargin;
|
||||
}
|
||||
//.create-btn-holder {
|
||||
// //bottom: auto;
|
||||
// //top: 0;
|
||||
// height: $ueTopBarH;
|
||||
// .wrapper.menu-element {
|
||||
// position: absolute;
|
||||
// bottom: $interiorMargin;
|
||||
// }
|
||||
//}
|
||||
.holder-create-and-search{
|
||||
|
||||
}
|
||||
.search-holder {
|
||||
top: $ueTopBarH + $interiorMarginLg;
|
||||
@ -245,6 +287,54 @@
|
||||
top: $ueTopBarH + $interiorMarginLg + $treeSearchInputBarH + $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
.mini-tab-icon.toggle-pane {
|
||||
//@include test(blue, 0.3);
|
||||
z-index: 5;
|
||||
@include desktop {
|
||||
$d: $uePaneMiniTabH;
|
||||
$paneExpandedOffset: $splitterD + $uePaneMiniTabW;
|
||||
top: $bodyMargin;
|
||||
height: $d;
|
||||
line-height: $d;
|
||||
&:after {
|
||||
// Always the icon that shows when the pane is collapsed
|
||||
opacity: 0;
|
||||
}
|
||||
&.collapsed {
|
||||
&:before {
|
||||
opacity: 0;
|
||||
}
|
||||
&:after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
&.toggle-tree.anchor-left {
|
||||
left: 0;
|
||||
@include transform(translateX(-1 * $paneExpandedOffset));
|
||||
&:after {
|
||||
content: '\6d'; // Menu 'hamburger' icon
|
||||
}
|
||||
&.collapsed {
|
||||
left: 0;
|
||||
@include transform(translateX((-1 * $ueCollapsedPaneEdgeM) + $interiorMargin));
|
||||
}
|
||||
&:not(.collapsed):before {
|
||||
@include trans-prop-nice(opacity, 200ms, 200ms);
|
||||
}
|
||||
}
|
||||
&.toggle-inspect.anchor-right {
|
||||
right: $bodyMargin;
|
||||
&:after {
|
||||
content: '\e615'; // e615: Crosshair icon; was e608: Info "i" icon
|
||||
}
|
||||
&.collapsed {
|
||||
right: $interiorMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.items {
|
||||
.object-browse-bar {
|
||||
.left.abs,
|
||||
@ -266,32 +356,50 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.vertical {
|
||||
/* &.vertical {
|
||||
// Slides left and right
|
||||
> .pane {
|
||||
// @include test();
|
||||
margin-left: $interiorMargin;
|
||||
> .pane.left {
|
||||
> .holder {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
.holder {
|
||||
right: $interiorMarginSm;
|
||||
}
|
||||
left: $bodyMargin;
|
||||
}
|
||||
}
|
||||
> .pane.right {
|
||||
> .holder {
|
||||
right: $bodyMargin;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// Specific elements margins
|
||||
.holder.holder-create-and-search {
|
||||
top: $bodyMargin;
|
||||
right: 0;
|
||||
bottom: $bodyMargin;
|
||||
left: $bodyMargin;
|
||||
}
|
||||
|
||||
.holder.holder-object-and-inspector {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
.holder-object {
|
||||
top: $bodyMargin;
|
||||
bottom: $bodyMargin;
|
||||
}
|
||||
.holder-inspector-elements {
|
||||
top: $bodyMargin;
|
||||
bottom: $bodyMargin;
|
||||
left: $bodyMargin;
|
||||
right: $bodyMargin;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.object-holder {
|
||||
overflow: hidden; // Contained objects need to handle their own overflow now
|
||||
@include absPosDefault(0, auto);
|
||||
top: $ueTopBarH + $interiorMarginLg;
|
||||
> ng-include {
|
||||
@include absPosDefault(0, auto);
|
||||
}
|
||||
&.l-controls-visible {
|
||||
&.l-time-controller-visible {
|
||||
bottom: nth($ueTimeControlH,1) + nth($ueTimeControlH,2) +nth($ueTimeControlH,3) + ($interiorMargin * 3);
|
||||
@ -343,4 +451,84 @@
|
||||
@include webkitProp(flex, '1 1 0');
|
||||
padding-right: $interiorMarginLg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When the tree is hidden, these are the
|
||||
// classes used for the left menu and the
|
||||
// right representation.
|
||||
.pane-tree-hidden {
|
||||
// Sets the left tree menu when the tree is hidden.
|
||||
//.pane.left.treeview,
|
||||
.tree-holder,
|
||||
.splitter-treeview,
|
||||
.holder-create-and-search {
|
||||
opacity: 0;
|
||||
}
|
||||
/*.holder-create-and-search {
|
||||
@include trans-prop-nice((top, left), 250ms);
|
||||
top: $ueTopBarH + $interiorMargin;
|
||||
left: -1 * $bodyMargin !important;
|
||||
.create-btn {
|
||||
@include border-left-radius(0);
|
||||
@include trans-prop-nice((width), 250ms);
|
||||
width: $uePaneMiniTabW !important;
|
||||
text-align: center !important;
|
||||
padding: 0;
|
||||
.title-label,
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
&:before {
|
||||
font-size: 9px;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
.pane-tree-showing {
|
||||
// Sets the left tree menu when the tree is shown.
|
||||
//.pane.left.treeview,
|
||||
.tree-holder,
|
||||
.splitter-treeview {
|
||||
@include trans-prop-nice(opacity, $dur: 250ms, $delay: 250ms);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.holder-create-and-search {
|
||||
@include trans-prop-nice(opacity, $dur: 250ms, $delay: 200ms);
|
||||
}
|
||||
}
|
||||
|
||||
.pane-inspect-showing {
|
||||
.l-object-and-inspector {
|
||||
.l-inspect,
|
||||
.splitter-inspect {
|
||||
@include trans-prop-nice(opacity, $dur: 250ms, $delay: 250ms);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pane-inspect-hidden {
|
||||
.l-object-and-inspector {
|
||||
.l-inspect,
|
||||
.splitter-inspect {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
.pane.treeview.left .tree-holder {
|
||||
padding-right: $interiorMargin;
|
||||
}
|
||||
.pane-tree-hidden {
|
||||
.pane.right.primary-pane { left: $ueCollapsedPaneEdgeM !important; }
|
||||
}
|
||||
.pane-inspect-hidden .l-object-and-inspector {
|
||||
.pane.left { right: $ueCollapsedPaneEdgeM !important; }
|
||||
}
|
||||
|
||||
.pane:not(.resizing) {
|
||||
@include trans-prop-nice-resize-w(250ms);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
<span class="s-btn"
|
||||
ng-controller="DateTimeFieldController">
|
||||
<input type="text"
|
||||
ng-model="textValue"
|
||||
ng-class="{ error: textInvalid }">
|
||||
</input>
|
||||
<a class="ui-symbol icon icon-calendar"
|
||||
ng-if="structure.format === 'utc' || !structure.format"
|
||||
ng-click="pickerActive = !pickerActive">
|
||||
</a>
|
||||
<mct-popup ng-if="pickerActive">
|
||||
<div mct-click-elsewhere="pickerActive = false">
|
||||
<mct-control key="'datetime-picker'"
|
||||
ng-model="ngModel"
|
||||
field="field"
|
||||
options="{ hours: true }">
|
||||
</mct-control>
|
||||
</div>
|
||||
</mct-popup>
|
||||
</span>
|
@ -22,47 +22,24 @@
|
||||
<div ng-controller="TimeRangeController">
|
||||
<div class="l-time-range-inputs-holder">
|
||||
<span class="l-time-range-inputs-elem ui-symbol type-icon">C</span>
|
||||
<span class="l-time-range-input" ng-controller="ToggleController as t1">
|
||||
<!--<span class="lbl">Start</span>-->
|
||||
<span class="s-btn time-range-start">
|
||||
<input type="text"
|
||||
ng-model="boundsModel.start"
|
||||
ng-class="{ error: !boundsModel.startValid }">
|
||||
</input>
|
||||
<a class="ui-symbol icon icon-calendar" ng-click="t1.toggle()"></a>
|
||||
<mct-popup ng-if="t1.isActive()">
|
||||
<div mct-click-elsewhere="t1.setState(false)">
|
||||
<mct-control key="'datetime-picker'"
|
||||
ng-model="ngModel.outer"
|
||||
field="'start'"
|
||||
options="{ hours: true }">
|
||||
</mct-control>
|
||||
</div>
|
||||
</mct-popup>
|
||||
</span>
|
||||
<span class="l-time-range-input">
|
||||
<mct-control key="'datetime-field'"
|
||||
structure="{ format: parameters.format }"
|
||||
ng-model="ngModel.outer"
|
||||
field="'start'"
|
||||
class="time-range-start">
|
||||
</mct-control>
|
||||
</span>
|
||||
|
||||
<span class="l-time-range-inputs-elem lbl">to</span>
|
||||
|
||||
<span class="l-time-range-input" ng-controller="ToggleController as t2">
|
||||
<!--<span class="lbl">End</span>-->
|
||||
<span class="s-btn l-time-range-input">
|
||||
<input type="text"
|
||||
ng-model="boundsModel.end"
|
||||
ng-class="{ error: !boundsModel.endValid }">
|
||||
</input>
|
||||
<a class="ui-symbol icon icon-calendar" ng-click="t2.toggle()">
|
||||
</a>
|
||||
<mct-popup ng-if="t2.isActive()">
|
||||
<div mct-click-elsewhere="t2.setState(false)">
|
||||
<mct-control key="'datetime-picker'"
|
||||
ng-model="ngModel.outer"
|
||||
field="'end'"
|
||||
options="{ hours: true }">
|
||||
</mct-control>
|
||||
</div>
|
||||
</mct-popup>
|
||||
</span>
|
||||
<mct-control key="'datetime-field'"
|
||||
structure="{ format: parameters.format }"
|
||||
ng-model="ngModel.outer"
|
||||
field="'end'"
|
||||
class="time-range-end">
|
||||
</mct-control>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -97,7 +74,7 @@
|
||||
<div class="l-time-range-ticks-holder">
|
||||
<div class="l-time-range-ticks">
|
||||
<div
|
||||
ng-repeat="tick in ticks"
|
||||
ng-repeat="tick in ticks track by $index"
|
||||
ng-style="{ left: $index * (100 / (ticks.length - 1)) + '%' }"
|
||||
class="tick tick-x"
|
||||
>
|
||||
|
@ -19,16 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span class="label s-label">
|
||||
<span class='ui-symbol icon type-icon'>
|
||||
{{type.getGlyph()}}
|
||||
<span
|
||||
class='ui-symbol icon l-icon-link'
|
||||
ng-show="location.isLink()"
|
||||
></span>
|
||||
<span class='ui-symbol icon l-icon-alert'></span>
|
||||
</span>
|
||||
<span class='title-label'>
|
||||
{{model.name}}
|
||||
</span>
|
||||
<span class="t-object-label">
|
||||
<span class="t-item-icon" ng-class="{ 'l-icon-link':location.isLink() }">{{type.getGlyph()}}</span>
|
||||
<span class='t-title-label'>{{model.name}}</span>
|
||||
</span>
|
||||
|
@ -0,0 +1,63 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<span class="l-inspect" ng-controller="ObjectInspectorController as controller">
|
||||
<div class="abs holder holder-inspector-elements">
|
||||
<div class="pane-header">Inspection</div>
|
||||
<ul>
|
||||
<li>
|
||||
<em>Properties</em>
|
||||
<div class="inspector-properties"
|
||||
ng-repeat="data in metadata"
|
||||
ng-class="{ first:$index === 0 }">
|
||||
<div class="label">{{ data.name }}</div>
|
||||
<div class="value">{{ data.value }}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li ng-if="contextutalParents.length > 0">
|
||||
<em title="The location of this linked object.">Location</em>
|
||||
<span class="inspector-location"
|
||||
ng-repeat="parent in contextutalParents"
|
||||
ng-class="{ last:($index + 1) === contextualParents.length }">
|
||||
<mct-representation key="'label'"
|
||||
mct-object="parent"
|
||||
ng-model="ngModel"
|
||||
ng-click="ngModel.selectedObject = parent"
|
||||
class="location-item">
|
||||
</mct-representation>
|
||||
</span>
|
||||
</li>
|
||||
<li ng-if="primaryParents.length > 0">
|
||||
<em title="The location of the original object that this was linked from.">Original Location</em>
|
||||
<span class="inspector-location"
|
||||
ng-repeat="parent in primaryParents"
|
||||
ng-class="{ last:($index + 1) === primaryParents.length }">
|
||||
<mct-representation key="'label'"
|
||||
mct-object="parent"
|
||||
ng-model="ngModel"
|
||||
ng-click="ngModel.selectedObject = parent"
|
||||
class="location-item">
|
||||
</mct-representation>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
@ -0,0 +1,79 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller to support the date-time entry field.
|
||||
*
|
||||
* Accepts a `format` property in the `structure` attribute
|
||||
* which allows a date/time to be specified via its symbolic
|
||||
* key (as will be used to look up said format from the
|
||||
* `formatService`.)
|
||||
*
|
||||
* {@see FormatService}
|
||||
* @constructor
|
||||
* @memberof platform/commonUI/general
|
||||
* @param $scope the Angular scope for this controller
|
||||
* @param {FormatService} formatService the service to user to format
|
||||
* domain values
|
||||
* @param {string} defaultFormat the format to request when no
|
||||
* format has been otherwise specified
|
||||
*/
|
||||
function DateTimeFieldController($scope, formatService, defaultFormat) {
|
||||
var formatter = formatService.getFormat(defaultFormat);
|
||||
|
||||
function updateFromModel(value) {
|
||||
// Only reformat if the value is different from user
|
||||
// input (to avoid reformatting valid input while typing.)
|
||||
if (!formatter.validate($scope.textValue) ||
|
||||
formatter.parse($scope.textValue) !== value) {
|
||||
$scope.textValue = formatter.format(value);
|
||||
$scope.textInvalid = false;
|
||||
}
|
||||
}
|
||||
|
||||
function updateFromView(textValue) {
|
||||
$scope.textInvalid = !formatter.validate(textValue);
|
||||
if (!$scope.textInvalid) {
|
||||
$scope.ngModel[$scope.field] =
|
||||
formatter.parse(textValue);
|
||||
}
|
||||
}
|
||||
|
||||
function setFormat(format) {
|
||||
formatter = formatService.getFormat(format || defaultFormat);
|
||||
updateFromModel($scope.ngModel[$scope.field]);
|
||||
}
|
||||
|
||||
$scope.$watch('structure.format', setFormat);
|
||||
$scope.$watch('ngModel[field]', updateFromModel);
|
||||
$scope.$watch('textValue', updateFromView);
|
||||
}
|
||||
|
||||
return DateTimeFieldController;
|
||||
}
|
||||
);
|
@ -0,0 +1,117 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise*/
|
||||
|
||||
/**
|
||||
* Module defining ObjectInspectorController. Created by shale on 08/21/2015.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The ObjectInspectorController gets and formats the data for
|
||||
* the inspector display
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function ObjectInspectorController($scope, objectService) {
|
||||
$scope.primaryParents = [];
|
||||
$scope.contextutalParents = [];
|
||||
//$scope.isLink = false;
|
||||
|
||||
// Gets an array of the contextual parents/anscestors of the selected object
|
||||
function getContextualPath() {
|
||||
var currentObj = $scope.ngModel.selectedObject,
|
||||
currentParent,
|
||||
parents = [];
|
||||
|
||||
currentParent = currentObj &&
|
||||
currentObj.hasCapability('context') &&
|
||||
currentObj.getCapability('context').getParent();
|
||||
|
||||
while (currentParent && currentParent.getModel().type !== 'root' &&
|
||||
currentParent.hasCapability('context')) {
|
||||
// Record this object
|
||||
parents.unshift(currentParent);
|
||||
|
||||
// Get the next one up the tree
|
||||
currentObj = currentParent;
|
||||
currentParent = currentObj.getCapability('context').getParent();
|
||||
}
|
||||
|
||||
$scope.contextutalParents = parents;
|
||||
}
|
||||
|
||||
// Gets an array of the parents/anscestors of the selected object's
|
||||
// primary location (locational of original non-link)
|
||||
function getPrimaryPath(current) {
|
||||
var location;
|
||||
|
||||
// If this the the initial call of this recursive function
|
||||
if (!current) {
|
||||
current = $scope.ngModel.selectedObject;
|
||||
$scope.primaryParents = [];
|
||||
}
|
||||
|
||||
location = current.getModel().location;
|
||||
|
||||
if (location && location !== 'root') {
|
||||
objectService.getObjects([location]).then(function (obj) {
|
||||
var next = obj[location];
|
||||
|
||||
$scope.primaryParents.unshift(next);
|
||||
getPrimaryPath(next);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Gets the metadata for the selected object
|
||||
function getMetadata() {
|
||||
$scope.metadata = $scope.ngModel.selectedObject &&
|
||||
$scope.ngModel.selectedObject.hasCapability('metadata') &&
|
||||
$scope.ngModel.selectedObject.useCapability('metadata');
|
||||
}
|
||||
|
||||
// Set scope variables when the selected object changes
|
||||
$scope.$watch('ngModel.selectedObject', function () {
|
||||
$scope.isLink = $scope.ngModel.selectedObject &&
|
||||
$scope.ngModel.selectedObject.hasCapability('location') &&
|
||||
$scope.ngModel.selectedObject.getCapability('location').isLink();
|
||||
|
||||
if ($scope.isLink) {
|
||||
getPrimaryPath();
|
||||
getContextualPath();
|
||||
} else {
|
||||
$scope.primaryParents = [];
|
||||
getContextualPath();
|
||||
}
|
||||
|
||||
getMetadata();
|
||||
});
|
||||
}
|
||||
|
||||
return ObjectInspectorController;
|
||||
}
|
||||
);
|
@ -26,33 +26,32 @@ define(
|
||||
function (moment) {
|
||||
"use strict";
|
||||
|
||||
var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss",
|
||||
TICK_SPACING_PX = 150;
|
||||
var TICK_SPACING_PX = 150;
|
||||
|
||||
|
||||
/**
|
||||
* Controller used by the `time-controller` template.
|
||||
* @memberof platform/commonUI/general
|
||||
* @constructor
|
||||
* @param $scope the Angular scope for this controller
|
||||
* @param {FormatService} formatService the service to user to format
|
||||
* domain values
|
||||
* @param {string} defaultFormat the format to request when no
|
||||
* format has been otherwise specified
|
||||
* @param {Function} now a function to return current system time
|
||||
*/
|
||||
function TimeConductorController($scope, now) {
|
||||
function TimeRangeController($scope, formatService, defaultFormat, now) {
|
||||
var tickCount = 2,
|
||||
innerMinimumSpan = 1000, // 1 second
|
||||
outerMinimumSpan = 1000 * 60 * 60, // 1 hour
|
||||
initialDragValue;
|
||||
initialDragValue,
|
||||
formatter = formatService.getFormat(defaultFormat);
|
||||
|
||||
function formatTimestamp(ts) {
|
||||
return moment.utc(ts).format(DATE_FORMAT);
|
||||
return formatter.format(ts);
|
||||
}
|
||||
|
||||
function parseTimestamp(text) {
|
||||
var m = moment.utc(text, DATE_FORMAT);
|
||||
if (m.isValid()) {
|
||||
return m.valueOf();
|
||||
} else {
|
||||
throw new Error("Could not parse " + text);
|
||||
}
|
||||
}
|
||||
|
||||
// From 0.0-1.0 to "0%"-"1%"
|
||||
// From 0.0-1.0 to "0%"-"100%"
|
||||
function toPercent(p) {
|
||||
return (100 * p) + "%";
|
||||
}
|
||||
@ -101,41 +100,15 @@ define(
|
||||
return { start: bounds.start, end: bounds.end };
|
||||
}
|
||||
|
||||
function updateBoundsTextForProperty(ngModel, property) {
|
||||
try {
|
||||
if (!$scope.boundsModel[property] ||
|
||||
parseTimestamp($scope.boundsModel[property]) !==
|
||||
ngModel.outer[property]) {
|
||||
$scope.boundsModel[property] =
|
||||
formatTimestamp(ngModel.outer[property]);
|
||||
}
|
||||
} catch (e) {
|
||||
// User-entered text is invalid, so leave it be
|
||||
// until they fix it.
|
||||
}
|
||||
}
|
||||
|
||||
function updateBoundsText(ngModel) {
|
||||
updateBoundsTextForProperty(ngModel, 'start');
|
||||
updateBoundsTextForProperty(ngModel, 'end');
|
||||
}
|
||||
|
||||
function updateViewFromModel(ngModel) {
|
||||
var t = now();
|
||||
|
||||
ngModel = ngModel || {};
|
||||
ngModel.outer = ngModel.outer || defaultBounds();
|
||||
ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
|
||||
|
||||
// First, dates for the date pickers for outer bounds
|
||||
updateBoundsText(ngModel);
|
||||
|
||||
// Then various updates for the inner span
|
||||
updateViewForInnerSpanFromModel(ngModel);
|
||||
|
||||
// Stick it back is scope (in case we just set defaults)
|
||||
$scope.ngModel = ngModel;
|
||||
|
||||
updateViewForInnerSpanFromModel(ngModel);
|
||||
updateTicks();
|
||||
}
|
||||
|
||||
@ -155,7 +128,8 @@ define(
|
||||
}
|
||||
|
||||
function toMillis(pixels) {
|
||||
var span = $scope.ngModel.outer.end - $scope.ngModel.outer.start;
|
||||
var span =
|
||||
$scope.ngModel.outer.end - $scope.ngModel.outer.start;
|
||||
return (pixels / $scope.spanWidth) * span;
|
||||
}
|
||||
|
||||
@ -243,36 +217,10 @@ define(
|
||||
updateTicks();
|
||||
}
|
||||
|
||||
function updateStartFromText(value) {
|
||||
try {
|
||||
updateOuterStart(parseTimestamp(value));
|
||||
updateBoundsTextForProperty($scope.ngModel, 'end');
|
||||
$scope.boundsModel.startValid = true;
|
||||
} catch (e) {
|
||||
$scope.boundsModel.startValid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function updateEndFromText(value) {
|
||||
try {
|
||||
updateOuterEnd(parseTimestamp(value));
|
||||
updateBoundsTextForProperty($scope.ngModel, 'start');
|
||||
$scope.boundsModel.endValid = true;
|
||||
} catch (e) {
|
||||
$scope.boundsModel.endValid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function updateStartFromPicker(value) {
|
||||
updateOuterStart(value);
|
||||
updateBoundsText($scope.ngModel);
|
||||
}
|
||||
|
||||
function updateEndFromPicker(value) {
|
||||
updateOuterEnd(value);
|
||||
updateBoundsText($scope.ngModel);
|
||||
function updateFormat(key) {
|
||||
formatter = formatService.getFormat(key || defaultFormat);
|
||||
updateViewForInnerSpanFromModel($scope.ngModel);
|
||||
updateTicks();
|
||||
}
|
||||
|
||||
$scope.startLeftDrag = startLeftDrag;
|
||||
@ -282,21 +230,18 @@ define(
|
||||
$scope.rightDrag = rightDrag;
|
||||
$scope.middleDrag = middleDrag;
|
||||
|
||||
$scope.state = false;
|
||||
$scope.ticks = [];
|
||||
$scope.boundsModel = {};
|
||||
|
||||
// Initialize scope to defaults
|
||||
updateViewFromModel($scope.ngModel);
|
||||
|
||||
$scope.$watchCollection("ngModel", updateViewFromModel);
|
||||
$scope.$watch("spanWidth", updateSpanWidth);
|
||||
$scope.$watch("ngModel.outer.start", updateStartFromPicker);
|
||||
$scope.$watch("ngModel.outer.end", updateEndFromPicker);
|
||||
$scope.$watch("boundsModel.start", updateStartFromText);
|
||||
$scope.$watch("boundsModel.end", updateEndFromText);
|
||||
$scope.$watch("ngModel.outer.start", updateOuterStart);
|
||||
$scope.$watch("ngModel.outer.end", updateOuterEnd);
|
||||
$scope.$watch("parameters.format", updateFormat);
|
||||
}
|
||||
|
||||
return TimeConductorController;
|
||||
return TimeRangeController;
|
||||
}
|
||||
);
|
||||
|
@ -132,10 +132,10 @@ define(
|
||||
// Get actual size (to obey min-width etc.)
|
||||
firstSize = getSize(first[0]);
|
||||
first.css(anchor.dimension, firstSize + 'px');
|
||||
splitter.css(anchor.edge, (firstSize + splitterSize) + 'px');
|
||||
splitter.css(anchor.edge, firstSize + 'px');
|
||||
splitter.css(anchor.opposite, "auto");
|
||||
|
||||
last.css(anchor.edge, (firstSize + splitterSize * 3) + 'px');
|
||||
last.css(anchor.edge, (firstSize + splitterSize) + 'px');
|
||||
last.css(anchor.opposite, "0px");
|
||||
|
||||
position = firstSize + splitterSize;
|
||||
@ -178,6 +178,12 @@ define(
|
||||
return position;
|
||||
}
|
||||
|
||||
// Dynamically apply a CSS class to elements when the user
|
||||
// is actively resizing
|
||||
function toggleClass(classToToggle) {
|
||||
$element.children().toggleClass(classToToggle);
|
||||
}
|
||||
|
||||
// Make sure anchor parameter is something we know
|
||||
if (!ANCHORS[anchorKey]) {
|
||||
$log.warn(ANCHOR_WARNING_MESSAGE);
|
||||
@ -208,6 +214,7 @@ define(
|
||||
// Interface exposed by controller, for mct-splitter to user
|
||||
return {
|
||||
position: getSetPosition,
|
||||
toggleClass: toggleClass,
|
||||
anchor: function () {
|
||||
return anchor;
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ define(
|
||||
// Pixel width to allocate for the splitter itself
|
||||
var SPLITTER_TEMPLATE = "<div class='abs'" +
|
||||
"mct-drag-down=\"splitter.startMove()\" " +
|
||||
"mct-drag=\"splitter.move(delta)\"></div>",
|
||||
"mct-drag=\"splitter.move(delta)\" " +
|
||||
"mct-drag-up=\"splitter.endMove()\"></div>",
|
||||
OFFSETS_BY_EDGE = {
|
||||
left: "offsetLeft",
|
||||
right: "offsetRight",
|
||||
@ -53,6 +54,7 @@ define(
|
||||
startMove: function () {
|
||||
var splitter = element[0];
|
||||
initialPosition = mctSplitPane.position();
|
||||
mctSplitPane.toggleClass('resizing');
|
||||
},
|
||||
// Handle user changes to splitter position
|
||||
move: function (delta) {
|
||||
@ -63,6 +65,11 @@ define(
|
||||
|
||||
// Update the position of this splitter
|
||||
mctSplitPane.position(initialPosition + pixelDelta);
|
||||
},
|
||||
// Grab the event when the user is done moving
|
||||
// the splitter and pass it on
|
||||
endMove: function() {
|
||||
mctSplitPane.toggleClass('resizing');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,183 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/DateTimeFieldController", "moment"],
|
||||
function (DateTimeFieldController, moment) {
|
||||
'use strict';
|
||||
|
||||
var TEST_FORMAT = "YYYY-MM-DD HH:mm:ss";
|
||||
|
||||
describe("The DateTimeFieldController", function () {
|
||||
var mockScope,
|
||||
mockFormatService,
|
||||
mockFormat,
|
||||
controller;
|
||||
|
||||
function fireWatch(expr, value) {
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
call.args[1](value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj('$scope', ['$watch']);
|
||||
mockFormatService =
|
||||
jasmine.createSpyObj('formatService', ['getFormat']);
|
||||
mockFormat = jasmine.createSpyObj('format', [
|
||||
'parse',
|
||||
'validate',
|
||||
'format'
|
||||
]);
|
||||
|
||||
mockFormatService.getFormat.andReturn(mockFormat);
|
||||
|
||||
mockFormat.validate.andCallFake(function (text) {
|
||||
return moment.utc(text, TEST_FORMAT).isValid();
|
||||
});
|
||||
mockFormat.parse.andCallFake(function (text) {
|
||||
return moment.utc(text, TEST_FORMAT).valueOf();
|
||||
});
|
||||
mockFormat.format.andCallFake(function (value) {
|
||||
return moment.utc(value).format(TEST_FORMAT);
|
||||
});
|
||||
|
||||
mockScope.ngModel = { testField: 12321 };
|
||||
mockScope.field = "testField";
|
||||
mockScope.structure = { format: "someFormat" };
|
||||
|
||||
controller = new DateTimeFieldController(
|
||||
mockScope,
|
||||
mockFormatService
|
||||
);
|
||||
});
|
||||
|
||||
it("updates models from user-entered text", function () {
|
||||
var newText = "1977-05-25 17:30:00";
|
||||
|
||||
mockScope.textValue = newText;
|
||||
fireWatch("textValue", newText);
|
||||
expect(mockScope.ngModel.testField)
|
||||
.toEqual(mockFormat.parse(newText));
|
||||
expect(mockScope.textInvalid).toBeFalsy();
|
||||
});
|
||||
|
||||
it("updates text from model values", function () {
|
||||
var testTime = mockFormat.parse("1977-05-25 17:30:00");
|
||||
mockScope.ngModel.testField = testTime;
|
||||
fireWatch("ngModel[field]", testTime);
|
||||
expect(mockScope.textValue).toEqual("1977-05-25 17:30:00");
|
||||
});
|
||||
|
||||
describe("when user input is invalid", function () {
|
||||
var newText, oldValue;
|
||||
|
||||
beforeEach(function () {
|
||||
newText = "Not a date";
|
||||
oldValue = mockScope.ngModel.testField;
|
||||
mockScope.textValue = newText;
|
||||
fireWatch("textValue", newText);
|
||||
});
|
||||
|
||||
it("displays error state", function () {
|
||||
expect(mockScope.textInvalid).toBeTruthy();
|
||||
});
|
||||
|
||||
it("does not modify model state", function () {
|
||||
expect(mockScope.ngModel.testField).toEqual(oldValue);
|
||||
});
|
||||
|
||||
it("does not modify user input", function () {
|
||||
expect(mockScope.textValue).toEqual(newText);
|
||||
});
|
||||
});
|
||||
|
||||
it("does not modify valid but irregular user input", function () {
|
||||
// Don't want the controller "fixing" bad or
|
||||
// irregularly-formatted input out from under
|
||||
// the user's fingertips.
|
||||
var newText = "2015-3-3 01:02:04",
|
||||
oldValue = mockScope.ngModel.testField;
|
||||
|
||||
mockFormat.validate.andReturn(true);
|
||||
mockFormat.parse.andReturn(42);
|
||||
mockScope.textValue = newText;
|
||||
fireWatch("textValue", newText);
|
||||
|
||||
expect(mockScope.textValue).toEqual(newText);
|
||||
expect(mockScope.ngModel.testField).toEqual(42);
|
||||
expect(mockScope.ngModel.testField).not.toEqual(oldValue);
|
||||
});
|
||||
|
||||
it("obtains a format from the format service", function () {
|
||||
fireWatch('structure.format', mockScope.structure.format);
|
||||
expect(mockFormatService.getFormat)
|
||||
.toHaveBeenCalledWith(mockScope.structure.format);
|
||||
});
|
||||
|
||||
it("throws an error for unknown formats", function () {
|
||||
mockFormatService.getFormat.andReturn(undefined);
|
||||
expect(function () {
|
||||
fireWatch("structure.format", "some-format");
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
describe("using the obtained format", function () {
|
||||
var testValue = 1234321,
|
||||
testText = "some text";
|
||||
|
||||
beforeEach(function () {
|
||||
mockFormat.validate.andReturn(true);
|
||||
mockFormat.parse.andReturn(testValue);
|
||||
mockFormat.format.andReturn(testText);
|
||||
});
|
||||
|
||||
it("parses user input", function () {
|
||||
var newText = "some other new text";
|
||||
mockScope.textValue = newText;
|
||||
fireWatch("textValue", newText);
|
||||
expect(mockFormat.parse).toHaveBeenCalledWith(newText);
|
||||
expect(mockScope.ngModel.testField).toEqual(testValue);
|
||||
});
|
||||
|
||||
it("validates user input", function () {
|
||||
var newText = "some other new text";
|
||||
mockScope.textValue = newText;
|
||||
fireWatch("textValue", newText);
|
||||
expect(mockFormat.validate).toHaveBeenCalledWith(newText);
|
||||
});
|
||||
|
||||
it("formats model data for display", function () {
|
||||
var newValue = 42;
|
||||
mockScope.ngModel.testField = newValue;
|
||||
fireWatch("ngModel[field]", newValue);
|
||||
expect(mockFormat.format).toHaveBeenCalledWith(newValue);
|
||||
expect(mockScope.textValue).toEqual(testText);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -0,0 +1,112 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
/**
|
||||
* Created by shale on 08/24/2015.
|
||||
*/
|
||||
define(
|
||||
["../../src/controllers/ObjectInspectorController"],
|
||||
function (ObjectInspectorController) {
|
||||
"use strict";
|
||||
|
||||
describe("The object inspector controller ", function () {
|
||||
var mockScope,
|
||||
mockObjectService,
|
||||
mockPromise,
|
||||
mockDomainObject,
|
||||
mockContextCapability,
|
||||
mockLocationCapability,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
[ "$watch" ]
|
||||
);
|
||||
mockScope.ngModel = {};
|
||||
mockScope.ngModel.selectedObject = 'mock selected object';
|
||||
|
||||
mockObjectService = jasmine.createSpyObj(
|
||||
"objectService",
|
||||
[ "getObjects" ]
|
||||
);
|
||||
mockPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then" ]
|
||||
);
|
||||
mockObjectService.getObjects.andReturn(mockPromise);
|
||||
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"selectedObject",
|
||||
[ "hasCapability", "getCapability", "useCapability", "getModel" ]
|
||||
);
|
||||
mockDomainObject.getModel.andReturn({location: 'somewhere'});
|
||||
mockDomainObject.hasCapability.andReturn(true);
|
||||
|
||||
mockContextCapability = jasmine.createSpyObj(
|
||||
"context capability",
|
||||
[ "getParent" ]
|
||||
);
|
||||
mockLocationCapability = jasmine.createSpyObj(
|
||||
"location capability",
|
||||
[ "isLink" ]
|
||||
);
|
||||
mockDomainObject.getCapability.andCallFake(function (param) {
|
||||
if (param === 'location') {
|
||||
return mockLocationCapability;
|
||||
} else if (param === 'context') {
|
||||
return mockContextCapability;
|
||||
}
|
||||
});
|
||||
|
||||
controller = new ObjectInspectorController(mockScope, mockObjectService);
|
||||
|
||||
// Change the selected object to trigger the watch call
|
||||
mockScope.ngModel.selectedObject = mockDomainObject;
|
||||
});
|
||||
|
||||
it("watches for changes to the selected object", function () {
|
||||
expect(mockScope.$watch).toHaveBeenCalledWith('ngModel.selectedObject', jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("looks for contextual parent objects", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
expect(mockContextCapability.getParent).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("if link, looks for primary parent objects", function () {
|
||||
mockLocationCapability.isLink.andReturn(true);
|
||||
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
expect(mockDomainObject.getModel).toHaveBeenCalled();
|
||||
expect(mockObjectService.getObjects).toHaveBeenCalled();
|
||||
mockPromise.then.mostRecentCall.args[0]({'somewhere': mockDomainObject});
|
||||
});
|
||||
|
||||
it("gets metadata", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
expect(mockDomainObject.useCapability).toHaveBeenCalledWith('metadata');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -33,7 +33,10 @@ define(
|
||||
|
||||
describe("The TimeRangeController", function () {
|
||||
var mockScope,
|
||||
mockFormatService,
|
||||
testDefaultFormat,
|
||||
mockNow,
|
||||
mockFormat,
|
||||
controller;
|
||||
|
||||
function fireWatch(expr, value) {
|
||||
@ -57,8 +60,30 @@ define(
|
||||
"$scope",
|
||||
[ "$apply", "$watch", "$watchCollection" ]
|
||||
);
|
||||
mockFormatService = jasmine.createSpyObj(
|
||||
"formatService",
|
||||
[ "getFormat" ]
|
||||
);
|
||||
testDefaultFormat = 'utc';
|
||||
mockFormat = jasmine.createSpyObj(
|
||||
"format",
|
||||
[ "validate", "format", "parse" ]
|
||||
);
|
||||
|
||||
mockFormatService.getFormat.andReturn(mockFormat);
|
||||
|
||||
mockFormat.format.andCallFake(function (value) {
|
||||
return moment.utc(value).format("YYYY-MM-DD HH:mm:ss");
|
||||
});
|
||||
|
||||
mockNow = jasmine.createSpy('now');
|
||||
controller = new TimeRangeController(mockScope, mockNow);
|
||||
|
||||
controller = new TimeRangeController(
|
||||
mockScope,
|
||||
mockFormatService,
|
||||
testDefaultFormat,
|
||||
mockNow
|
||||
);
|
||||
});
|
||||
|
||||
it("watches the model that was passed in", function () {
|
||||
@ -167,70 +192,22 @@ define(
|
||||
.toBeGreaterThan(mockScope.ngModel.inner.start);
|
||||
});
|
||||
|
||||
describe("by typing", function () {
|
||||
it("updates models", function () {
|
||||
var newStart = "1977-05-25 17:30:00",
|
||||
newEnd = "2015-12-18 03:30:00";
|
||||
|
||||
mockScope.boundsModel.start = newStart;
|
||||
fireWatch("boundsModel.start", newStart);
|
||||
expect(mockScope.ngModel.outer.start)
|
||||
.toEqual(moment.utc(newStart).valueOf());
|
||||
expect(mockScope.boundsModel.startValid)
|
||||
.toBeTruthy();
|
||||
|
||||
mockScope.boundsModel.end = newEnd;
|
||||
fireWatch("boundsModel.end", newEnd);
|
||||
expect(mockScope.ngModel.outer.end)
|
||||
.toEqual(moment.utc(newEnd).valueOf());
|
||||
expect(mockScope.boundsModel.endValid)
|
||||
.toBeTruthy();
|
||||
});
|
||||
|
||||
it("displays error state", function () {
|
||||
var newStart = "Not a date",
|
||||
newEnd = "Definitely not a date",
|
||||
oldStart = mockScope.ngModel.outer.start,
|
||||
oldEnd = mockScope.ngModel.outer.end;
|
||||
|
||||
mockScope.boundsModel.start = newStart;
|
||||
fireWatch("boundsModel.start", newStart);
|
||||
expect(mockScope.ngModel.outer.start)
|
||||
.toEqual(oldStart);
|
||||
expect(mockScope.boundsModel.startValid)
|
||||
.toBeFalsy();
|
||||
|
||||
mockScope.boundsModel.end = newEnd;
|
||||
fireWatch("boundsModel.end", newEnd);
|
||||
expect(mockScope.ngModel.outer.end)
|
||||
.toEqual(oldEnd);
|
||||
expect(mockScope.boundsModel.endValid)
|
||||
.toBeFalsy();
|
||||
});
|
||||
|
||||
it("does not modify user input", function () {
|
||||
// Don't want the controller "fixing" bad or
|
||||
// irregularly-formatted input out from under
|
||||
// the user's fingertips.
|
||||
var newStart = "Not a date",
|
||||
newEnd = "2015-3-3 01:02:04",
|
||||
oldStart = mockScope.ngModel.outer.start,
|
||||
oldEnd = mockScope.ngModel.outer.end;
|
||||
|
||||
mockScope.boundsModel.start = newStart;
|
||||
fireWatch("boundsModel.start", newStart);
|
||||
expect(mockScope.boundsModel.start)
|
||||
.toEqual(newStart);
|
||||
|
||||
mockScope.boundsModel.end = newEnd;
|
||||
fireWatch("boundsModel.end", newEnd);
|
||||
expect(mockScope.boundsModel.end)
|
||||
.toEqual(newEnd);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("watches for changes in format selection", function () {
|
||||
expect(mockFormatService.getFormat)
|
||||
.not.toHaveBeenCalledWith('test-format');
|
||||
fireWatch("parameters.format", 'test-format');
|
||||
expect(mockFormatService.getFormat)
|
||||
.toHaveBeenCalledWith('test-format');
|
||||
});
|
||||
|
||||
it("throws an error for unknown formats", function () {
|
||||
mockFormatService.getFormat.andReturn(undefined);
|
||||
expect(function () {
|
||||
fireWatch("parameters.format", "some-format");
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -3,8 +3,10 @@
|
||||
"controllers/BottomBarController",
|
||||
"controllers/ClickAwayController",
|
||||
"controllers/ContextMenuController",
|
||||
"controllers/DateTimeFieldController",
|
||||
"controllers/DateTimePickerController",
|
||||
"controllers/GetterSetterController",
|
||||
"controllers/ObjectInspectorController",
|
||||
"controllers/SelectorController",
|
||||
"controllers/SplitPaneController",
|
||||
"controllers/TimeRangeController",
|
||||
|
@ -55,11 +55,6 @@ define(
|
||||
self.trackPosition(event);
|
||||
};
|
||||
|
||||
// Also make sure we dismiss bubble if representation is destroyed
|
||||
// before the mouse actually leaves it
|
||||
this.scopeOff =
|
||||
element.scope().$on('$destroy', this.hideBubbleCallback);
|
||||
|
||||
this.element = element;
|
||||
this.$timeout = $timeout;
|
||||
this.infoService = infoService;
|
||||
@ -143,7 +138,6 @@ define(
|
||||
this.hideBubble();
|
||||
// ...and detach listeners
|
||||
this.element.off('mouseenter', this.showBubbleCallback);
|
||||
this.scopeOff();
|
||||
};
|
||||
|
||||
return InfoGesture;
|
||||
|
@ -216,18 +216,51 @@ define(
|
||||
* A convenience method for info notifications. Notifications
|
||||
* created via this method will be auto-dismissed after a default
|
||||
* wait period
|
||||
* @param {NotificationModel} notificationModel Options describing the
|
||||
* notification to display
|
||||
* @param {NotificationModel | string} message either a string for
|
||||
* the title of the notification message, or a {@link NotificationModel}
|
||||
* defining the options notification to display
|
||||
* @returns {Notification} the provided notification decorated with
|
||||
* functions to dismiss or minimize
|
||||
*/
|
||||
NotificationService.prototype.info = function (model) {
|
||||
var notificationModel = typeof model === "string" ? {title: model} : model;
|
||||
NotificationService.prototype.info = function (message) {
|
||||
var notificationModel = typeof message === "string" ? {title: message} : message;
|
||||
notificationModel.autoDismiss = notificationModel.autoDismiss || true;
|
||||
notificationModel.severity = "info";
|
||||
return this.notify(notificationModel);
|
||||
};
|
||||
|
||||
/**
|
||||
* A convenience method for alert notifications. Notifications
|
||||
* created via this method will will have severity of "alert" enforced
|
||||
* @param {NotificationModel | string} message either a string for
|
||||
* the title of the alert message with default options, or a
|
||||
* {@link NotificationModel} defining the options notification to
|
||||
* display
|
||||
* @returns {Notification} the provided notification decorated with
|
||||
* functions to dismiss or minimize
|
||||
*/
|
||||
NotificationService.prototype.alert = function (message) {
|
||||
var notificationModel = typeof message === "string" ? {title: message} : message;
|
||||
notificationModel.severity = "alert";
|
||||
return this.notify(notificationModel);
|
||||
};
|
||||
|
||||
/**
|
||||
* A convenience method for error notifications. Notifications
|
||||
* created via this method will will have severity of "error" enforced
|
||||
* @param {NotificationModel | string} message either a string for
|
||||
* the title of the error message with default options, or a
|
||||
* {@link NotificationModel} defining the options notification to
|
||||
* display
|
||||
* @returns {Notification} the provided notification decorated with
|
||||
* functions to dismiss or minimize
|
||||
*/
|
||||
NotificationService.prototype.error = function (message) {
|
||||
var notificationModel = typeof message === "string" ? {title: message} : message;
|
||||
notificationModel.severity = "error";
|
||||
return this.notify(notificationModel);
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies the user of an event. If there is a banner notification
|
||||
* already active, then it will be dismissed or minimized automatically,
|
||||
|
@ -57,6 +57,16 @@ define(
|
||||
expect(activeNotification.model).toBe(successModel);
|
||||
});
|
||||
|
||||
it("allows specification of an info notification given just a" +
|
||||
" title, making the notification active", function() {
|
||||
var activeNotification,
|
||||
notificationTitle = "Test info notification";
|
||||
notificationService.info(notificationTitle);
|
||||
activeNotification = notificationService.getActiveNotification();
|
||||
expect(activeNotification.model.title).toBe(notificationTitle);
|
||||
expect(activeNotification.model.severity).toBe("info");
|
||||
});
|
||||
|
||||
it("gets a new success notification with" +
|
||||
" numerical auto-dismiss specified. ", function() {
|
||||
var activeNotification;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -37,12 +37,14 @@ $timeControllerToiLineColorHov: #fff;
|
||||
|
||||
// General Colors
|
||||
$colorAlt1: #ffc700;
|
||||
$colorAlert: #ff533a;
|
||||
$colorAlert: #ff3c00;
|
||||
$colorIconLink: #49dedb;
|
||||
$colorPausedBg: #c56f01;
|
||||
$colorPausedFg: #fff;
|
||||
$colorCreateBtn: $colorKey;
|
||||
$colorGridLines: rgba(#fff, 0.05);
|
||||
$colorFormLines: rgba(#fff, 0.1);
|
||||
$colorFormSectionHeader: rgba(#000, 0.2);
|
||||
$colorInvokeMenu: #fff;
|
||||
$colorObjHdrTxt: $colorBodyFg;
|
||||
$colorObjHdrIc: pullForward($colorObjHdrTxt, 20%);
|
||||
@ -55,10 +57,10 @@ $colorMenuIc: pullForward($colorKey, 17%);
|
||||
$colorMenuHovBg: pullForward($colorMenuBg, 10%);
|
||||
$colorMenuHovFg: #fff;
|
||||
$colorMenuHovIc: $colorMenuHovFg;
|
||||
$colorCreateMenuLgIcon: $colorMenuFg;
|
||||
$colorCreateMenuText: $colorMenuFg;
|
||||
$shdwMenu: none;
|
||||
$shdwMenuText: rgba(black, 0.1) 0 1px 2px;
|
||||
$colorCreateMenuLgIcon: $colorMenuFg;
|
||||
$colorCreateMenuText: $colorMenuFg;
|
||||
|
||||
// Form colors
|
||||
$colorCheck: $colorKey;
|
||||
@ -73,6 +75,14 @@ $colorInputFg: pullForward($colorBodyFg, 20%);
|
||||
$colorFormText: rgba(#fff, 0.5);
|
||||
$colorInputIcon: pushBack($colorBodyFg, 15%);
|
||||
|
||||
// Inspector
|
||||
$colorInspectorBg: pullForward($colorBodyBg, 3%);
|
||||
$colorInspectorFg: $colorBodyFg;
|
||||
$colorInspectorPropName: pushBack($colorBodyFg, 15%);
|
||||
$colorInspectorPropVal: pullForward($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
|
||||
|
||||
// Status colors, mainly used for messaging and item ancillary symbols
|
||||
$colorStatusFg: #ccc;
|
||||
$colorStatusDefault: #ccc;
|
||||
@ -139,6 +149,8 @@ $colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
|
||||
// Tree
|
||||
$colorItemTreeHoverBg: rgba($colorBodyFg, 0.1);
|
||||
$colorItemTreeHoverFg: pullForward($colorBodyFg, 20%);
|
||||
$colorItemTreeIcon: $colorKey;
|
||||
$colorItemTreeIconHover: lighten($colorItemTreeIcon, 20%);
|
||||
$colorItemTreeFg: $colorBodyFg;
|
||||
@ -157,12 +169,13 @@ $scrollbarThumbColorHov: lighten($scrollbarThumbColor, 2%);
|
||||
$scrollbarTrackShdw: rgba(#000, 0.7) 0 1px 5px;
|
||||
|
||||
// Splitter
|
||||
$splitterD: 25px; // splitterD and HandleD should both be odd, or even
|
||||
$splitterHandleD: 1px;
|
||||
$colorSplitterBg: pullForward($colorBodyBg, 5%);
|
||||
$splitterShdw: rgba(black, 0.4) 0 0 3px;
|
||||
$colorSplitterInterior: $colorBodyBg;
|
||||
$colorSplitterHover: none;
|
||||
$splitterW: 5px;
|
||||
$splitterEndCr: 1px;
|
||||
$colorGrippyInteriorHover: $colorKey;
|
||||
$splitterEndCr: none;
|
||||
$colorSplitterHover: pullForward($colorBodyBg, 15%);
|
||||
$colorSplitterActive: $colorKey;
|
||||
|
||||
// Mobile
|
||||
$colorMobilePaneLeft: darken($colorBodyBg, 5%);
|
||||
@ -179,4 +192,4 @@ $colorAboutLink: #84b3ff;
|
||||
|
||||
// Loading
|
||||
$colorLoadingBg: rgba($colorBodyFg, 0.2);
|
||||
$colorLoadingFg: $colorAlt1;
|
||||
$colorLoadingFg: $colorAlt1;
|
||||
|
@ -4,7 +4,7 @@
|
||||
@include boxShdw($shdwBtns);
|
||||
}
|
||||
|
||||
@mixin btnSubtle($bg: $colorBodyBg, $bgHov: none, $fg: $colorBodyFg, $ic: $colorBtnIcon) {
|
||||
@mixin btnSubtle($bg: $colorBodyBg, $bgHov: none, $fg: $colorBodyFg, $ic: $colorBtnIcon) {
|
||||
@include containerSubtle($bg, $fg);
|
||||
@include btnBase($bg, linear-gradient(lighten($bg, 15%), lighten($bg, 10%)), $fg, $ic);
|
||||
@include text-shadow($shdwItemText);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,6 +75,14 @@ $colorInputIcon: pushBack($colorBodyFg, 25%);
|
||||
$colorSelectBg: #ddd;
|
||||
$colorSelectFg: $colorBodyFg;
|
||||
|
||||
// Inspector
|
||||
$colorInspectorBg: pullForward($colorBodyBg, 5%);
|
||||
$colorInspectorFg: $colorBodyFg;
|
||||
$colorInspectorPropName: pushBack($colorBodyFg, 20%);
|
||||
$colorInspectorPropVal: pullForward($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
|
||||
|
||||
// Limits and staleness colors//
|
||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
||||
@ -110,6 +118,7 @@ $colorItemBgSelected: $colorKey;
|
||||
|
||||
// Tabular
|
||||
$colorTabBorder: pullForward($colorBodyBg, 10%);
|
||||
$colorItemTreeHoverFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabBodyBg: $colorBodyBg;
|
||||
$colorTabBodyFg: pullForward($colorBodyFg, 20%);
|
||||
$colorTabHeaderBg: pullForward($colorBodyBg, 10%);
|
||||
@ -125,6 +134,7 @@ $colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
|
||||
// Tree
|
||||
$colorItemTreeHoverBg: rgba($colorBodyFg, 0.1);
|
||||
$colorItemTreeIcon: $colorKey;
|
||||
$colorItemTreeIconHover: $colorItemTreeIcon; //pushBack($colorItemTreeIcon, 20%);
|
||||
$colorItemTreeVCHover: $colorKey;
|
||||
@ -143,12 +153,13 @@ $scrollbarThumbColor: darken($colorBodyBg, 50%);//
|
||||
$scrollbarThumbColorHov: $colorKey;
|
||||
|
||||
// Splitter
|
||||
$splitterD: 24px;
|
||||
$splitterHandleD: 2px;
|
||||
$colorSplitterBg: pullForward($colorBodyBg, 10%);
|
||||
$splitterShdw: none;
|
||||
$colorSplitterInterior: $colorBodyBg;
|
||||
$colorSplitterHover: $colorKey;
|
||||
$splitterW: 5px;
|
||||
$splitterEndCr: $splitterW;
|
||||
$colorGrippyInteriorHover: $colorBodyBg;
|
||||
$splitterEndCr: none;
|
||||
$colorSplitterHover: none;
|
||||
$colorSplitterActive: $colorKey;
|
||||
|
||||
// Mobile
|
||||
$colorMobilePaneLeft: darken($colorBodyBg, 2%);
|
||||
|
@ -101,13 +101,27 @@ define(
|
||||
self.notificationService.info("Copying complete.");
|
||||
},
|
||||
function error(errorDetails){
|
||||
self.$log.error("Error copying objects. ", errorDetails);
|
||||
//Show more general error message
|
||||
self.notificationService.notify({
|
||||
var errorMessage = {
|
||||
title: "Error copying objects.",
|
||||
severity: "error",
|
||||
hint: errorDetails.message
|
||||
});
|
||||
hint: errorDetails.message,
|
||||
minimized: true, // want the notification to be minimized initially (don't show banner)
|
||||
options: [{
|
||||
label: "OK",
|
||||
callback: function() {
|
||||
self.dialogService.dismiss();
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
self.dialogService.dismiss();
|
||||
if (self.notification) {
|
||||
self.notification.dismiss(); // Clear the progress notification
|
||||
}
|
||||
self.$log.error("Error copying objects. ", errorDetails);
|
||||
//Show more general error message
|
||||
self.notificationService.notify(errorMessage);
|
||||
self.dialogService.showBlockingMessage(errorMessage);
|
||||
|
||||
},
|
||||
function notification(details){
|
||||
|
@ -200,7 +200,7 @@ define(
|
||||
this.buildCopyPlan(domainObject, parent, deferred.notify)
|
||||
.then(this.persistObjects(deferred.notify))
|
||||
.then(this.addClonesToParent(parent, deferred.notify))
|
||||
.then(deferred.resolve);
|
||||
.then(deferred.resolve, deferred.reject);
|
||||
return deferred.promise;
|
||||
} else {
|
||||
throw new Error(
|
||||
|
@ -36,9 +36,9 @@
|
||||
{
|
||||
"key": "TIME_CONDUCTOR_DOMAINS",
|
||||
"value": [
|
||||
{ "key": "time", "name": "Time" },
|
||||
{ "key": "yesterday", "name": "Yesterday" }
|
||||
{ "key": "time", "name": "UTC", "format": "utc" }
|
||||
],
|
||||
"priority": "fallback",
|
||||
"comment": "Placeholder; to be replaced by inspection of available domains."
|
||||
}
|
||||
]
|
||||
|
@ -1,4 +1,5 @@
|
||||
<mct-include key="'time-controller'"
|
||||
parameters='parameters'
|
||||
ng-model='ngModel.conductor'>
|
||||
</mct-include>
|
||||
<mct-control key="'select'"
|
||||
|
@ -27,7 +27,10 @@ define(
|
||||
"use strict";
|
||||
|
||||
var TEMPLATE = [
|
||||
"<mct-include key=\"'time-conductor'\" ng-model='ngModel' class='l-time-controller'>",
|
||||
"<mct-include key=\"'time-conductor'\" ",
|
||||
"ng-model='ngModel' ",
|
||||
"parameters='parameters' ",
|
||||
"class='l-time-controller'>",
|
||||
"</mct-include>"
|
||||
].join(''),
|
||||
THROTTLE_MS = 200,
|
||||
@ -74,11 +77,11 @@ define(
|
||||
broadcastBounds;
|
||||
|
||||
// Combine start/end times into a single object
|
||||
function bounds(start, end) {
|
||||
function bounds() {
|
||||
return {
|
||||
start: conductor.displayStart(),
|
||||
end: conductor.displayEnd(),
|
||||
domain: conductor.domain()
|
||||
domain: conductor.domain().key
|
||||
};
|
||||
}
|
||||
|
||||
@ -97,12 +100,9 @@ define(
|
||||
}
|
||||
|
||||
function updateDomain(value) {
|
||||
conductor.domain(value);
|
||||
repScope.$broadcast('telemetry:display:bounds', bounds(
|
||||
conductor.displayStart(),
|
||||
conductor.displayEnd(),
|
||||
conductor.domain()
|
||||
));
|
||||
var newDomain = conductor.domain(value);
|
||||
conductorScope.parameters.format = newDomain.format;
|
||||
repScope.$broadcast('telemetry:display:bounds', bounds());
|
||||
}
|
||||
|
||||
// telemetry domain metadata -> option for a select control
|
||||
@ -130,7 +130,8 @@ define(
|
||||
{ outer: bounds(), inner: bounds() };
|
||||
conductorScope.ngModel.options =
|
||||
conductor.domainOptions().map(makeOption);
|
||||
conductorScope.ngModel.domain = conductor.domain();
|
||||
conductorScope.ngModel.domain = conductor.domain().key;
|
||||
conductorScope.parameters = {};
|
||||
|
||||
conductorScope
|
||||
.$watch('ngModel.conductor.inner.start', updateConductorInner);
|
||||
|
@ -51,7 +51,7 @@ define(
|
||||
request = request || {};
|
||||
request.start = start;
|
||||
request.end = end;
|
||||
request.domain = domain;
|
||||
request.domain = domain.key;
|
||||
return request;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ define(
|
||||
function TimeConductor(start, end, domains) {
|
||||
this.range = { start: start, end: end };
|
||||
this.domains = domains;
|
||||
this.activeDomain = domains[0].key;
|
||||
this.activeDomain = domains[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,7 +73,7 @@ define(
|
||||
/**
|
||||
* Get available domain options which can be used to bound time
|
||||
* selection.
|
||||
* @returns {TelemetryDomain[]} available domains
|
||||
* @returns {TelemetryDomainMetadata[]} available domains
|
||||
*/
|
||||
TimeConductor.prototype.domainOptions = function () {
|
||||
return this.domains;
|
||||
@ -82,19 +82,21 @@ define(
|
||||
/**
|
||||
* Get or set (if called with an argument) the active domain.
|
||||
* @param {string} [key] the key identifying the domain choice
|
||||
* @returns {TelemetryDomain} the active telemetry domain
|
||||
* @returns {TelemetryDomainMetadata} the active telemetry domain
|
||||
*/
|
||||
TimeConductor.prototype.domain = function (key) {
|
||||
function matchesKey(domain) {
|
||||
return domain.key === key;
|
||||
}
|
||||
var i;
|
||||
|
||||
if (arguments.length > 0) {
|
||||
if (!this.domains.some(matchesKey)) {
|
||||
throw new Error("Unknown domain " + key);
|
||||
for (i = 0; i < this.domains.length; i += 1) {
|
||||
if (this.domains[i].key === key) {
|
||||
return (this.activeDomain = this.domains[i]);
|
||||
}
|
||||
}
|
||||
this.activeDomain = key;
|
||||
|
||||
throw new Error("Unknown domain " + key);
|
||||
}
|
||||
|
||||
return this.activeDomain;
|
||||
};
|
||||
|
||||
|
@ -129,7 +129,7 @@ define(
|
||||
it("exposes conductor state in scope", function () {
|
||||
mockConductor.displayStart.andReturn(1977);
|
||||
mockConductor.displayEnd.andReturn(1984);
|
||||
mockConductor.domain.andReturn('d');
|
||||
mockConductor.domain.andReturn({ key: 'd' });
|
||||
representer.represent(testViews[0], {});
|
||||
|
||||
expect(mockNewScope.ngModel.conductor).toEqual({
|
||||
@ -219,7 +219,7 @@ define(
|
||||
representer.represent(testViews[0], null);
|
||||
|
||||
expect(mockNewScope.ngModel.domain)
|
||||
.toEqual(mockConductor.domain());
|
||||
.toEqual(mockConductor.domain().key);
|
||||
});
|
||||
|
||||
it("exposes domain options in scope", function () {
|
||||
|
@ -77,7 +77,7 @@ define(
|
||||
|
||||
mockConductor.displayStart.andReturn(42);
|
||||
mockConductor.displayEnd.andReturn(1977);
|
||||
mockConductor.domain.andReturn("testDomain");
|
||||
mockConductor.domain.andReturn({ key: "testDomain" });
|
||||
|
||||
decorator = new ConductorTelemetryDecorator(
|
||||
mockConductorService,
|
||||
@ -104,7 +104,7 @@ define(
|
||||
});
|
||||
|
||||
it("with domain selection", function () {
|
||||
expect(request.domain).toEqual(mockConductor.domain());
|
||||
expect(request.domain).toEqual(mockConductor.domain().key);
|
||||
});
|
||||
});
|
||||
|
||||
@ -127,7 +127,7 @@ define(
|
||||
});
|
||||
|
||||
it("with domain selection", function () {
|
||||
expect(request.domain).toEqual(mockConductor.domain());
|
||||
expect(request.domain).toEqual(mockConductor.domain().key);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -59,12 +59,12 @@ define(
|
||||
});
|
||||
|
||||
it("exposes the current domain choice", function () {
|
||||
expect(conductor.domain()).toEqual(testDomains[0].key);
|
||||
expect(conductor.domain()).toEqual(testDomains[0]);
|
||||
});
|
||||
|
||||
it("allows the domain choice to be changed", function () {
|
||||
conductor.domain(testDomains[1].key);
|
||||
expect(conductor.domain()).toEqual(testDomains[1].key);
|
||||
expect(conductor.domain()).toEqual(testDomains[1]);
|
||||
});
|
||||
|
||||
it("throws an error on attempts to set an invalid domain", function () {
|
||||
|
@ -31,10 +31,19 @@ define(
|
||||
"./elements/PlotPalette",
|
||||
"./elements/PlotAxis",
|
||||
"./elements/PlotLimitTracker",
|
||||
"./elements/PlotTelemetryFormatter",
|
||||
"./modes/PlotModeOptions",
|
||||
"./SubPlotFactory"
|
||||
],
|
||||
function (PlotUpdater, PlotPalette, PlotAxis, PlotLimitTracker, PlotModeOptions, SubPlotFactory) {
|
||||
function (
|
||||
PlotUpdater,
|
||||
PlotPalette,
|
||||
PlotAxis,
|
||||
PlotLimitTracker,
|
||||
PlotTelemetryFormatter,
|
||||
PlotModeOptions,
|
||||
SubPlotFactory
|
||||
) {
|
||||
"use strict";
|
||||
|
||||
var AXIS_DEFAULTS = [
|
||||
@ -62,7 +71,10 @@ define(
|
||||
PLOT_FIXED_DURATION
|
||||
) {
|
||||
var self = this,
|
||||
subPlotFactory = new SubPlotFactory(telemetryFormatter),
|
||||
plotTelemetryFormatter =
|
||||
new PlotTelemetryFormatter(telemetryFormatter),
|
||||
subPlotFactory =
|
||||
new SubPlotFactory(plotTelemetryFormatter),
|
||||
cachedObjects = [],
|
||||
updater,
|
||||
lastBounds,
|
||||
@ -71,10 +83,9 @@ define(
|
||||
// Populate the scope with axis information (specifically, options
|
||||
// available for each axis.)
|
||||
function setupAxes(metadatas) {
|
||||
$scope.axes = [
|
||||
new PlotAxis("domain", metadatas, AXIS_DEFAULTS[0]),
|
||||
new PlotAxis("range", metadatas, AXIS_DEFAULTS[1])
|
||||
];
|
||||
$scope.axes.forEach(function (axis) {
|
||||
axis.updateMetadata(metadatas);
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger an update of a specific subplot;
|
||||
@ -125,37 +136,49 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
function getUpdater() {
|
||||
if (!updater) {
|
||||
recreateUpdater();
|
||||
}
|
||||
return updater;
|
||||
}
|
||||
|
||||
// Handle new telemetry data in this plot
|
||||
function updateValues() {
|
||||
self.pending = false;
|
||||
if (handle) {
|
||||
setupModes(handle.getTelemetryObjects());
|
||||
}
|
||||
if (updater) {
|
||||
updater.update();
|
||||
setupAxes(handle.getMetadata());
|
||||
getUpdater().update();
|
||||
self.modeOptions.getModeHandler().plotTelemetry(updater);
|
||||
}
|
||||
if (self.limitTracker) {
|
||||
self.limitTracker.update();
|
||||
self.update();
|
||||
}
|
||||
self.update();
|
||||
}
|
||||
|
||||
// Display new historical data as it becomes available
|
||||
function addHistoricalData(domainObject, series) {
|
||||
self.pending = false;
|
||||
updater.addHistorical(domainObject, series);
|
||||
getUpdater().addHistorical(domainObject, series);
|
||||
self.modeOptions.getModeHandler().plotTelemetry(updater);
|
||||
self.update();
|
||||
}
|
||||
|
||||
// Issue a new request for historical telemetry
|
||||
function requestTelemetry() {
|
||||
if (handle && updater) {
|
||||
if (handle) {
|
||||
handle.request({}, addHistoricalData);
|
||||
}
|
||||
}
|
||||
|
||||
// Requery for data entirely
|
||||
function replot() {
|
||||
if (handle) {
|
||||
updater = undefined;
|
||||
requestTelemetry();
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new subscription; telemetrySubscriber gets
|
||||
// to do the meaningful work here.
|
||||
function subscribe(domainObject) {
|
||||
@ -167,12 +190,7 @@ define(
|
||||
updateValues,
|
||||
true // Lossless
|
||||
);
|
||||
if (handle) {
|
||||
setupModes(handle.getTelemetryObjects());
|
||||
setupAxes(handle.getMetadata());
|
||||
recreateUpdater();
|
||||
requestTelemetry();
|
||||
}
|
||||
replot();
|
||||
}
|
||||
|
||||
// Release the current subscription (called when scope is destroyed)
|
||||
@ -185,12 +203,22 @@ define(
|
||||
|
||||
// Respond to a display bounds change (requery for data)
|
||||
function changeDisplayBounds(event, bounds) {
|
||||
var domainAxis = $scope.axes[0];
|
||||
|
||||
domainAxis.chooseOption(bounds.domain);
|
||||
plotTelemetryFormatter
|
||||
.setDomainFormat(domainAxis.active.format);
|
||||
|
||||
self.pending = true;
|
||||
releaseSubscription();
|
||||
subscribe($scope.domainObject);
|
||||
setBasePanZoom(bounds);
|
||||
}
|
||||
|
||||
function updateDomainFormat(format) {
|
||||
plotTelemetryFormatter.setDomainFormat(format);
|
||||
}
|
||||
|
||||
this.modeOptions = new PlotModeOptions([], subPlotFactory);
|
||||
this.updateValues = updateValues;
|
||||
|
||||
@ -202,6 +230,13 @@ define(
|
||||
|
||||
self.pending = true;
|
||||
|
||||
// Initialize axes; will get repopulated when telemetry
|
||||
// metadata becomes available.
|
||||
$scope.axes = [
|
||||
new PlotAxis("domains", [], AXIS_DEFAULTS[0]),
|
||||
new PlotAxis("ranges", [], AXIS_DEFAULTS[1])
|
||||
];
|
||||
|
||||
// Subscribe to telemetry when a domain object becomes available
|
||||
$scope.$watch('domainObject', subscribe);
|
||||
|
||||
|
@ -121,9 +121,9 @@ define(
|
||||
// Utility, for map/forEach loops. Index 0 is domain,
|
||||
// index 1 is range.
|
||||
function formatValue(v, i) {
|
||||
return (i ?
|
||||
formatter.formatRangeValue :
|
||||
formatter.formatDomainValue)(v);
|
||||
return i ?
|
||||
formatter.formatRangeValue(v) :
|
||||
formatter.formatDomainValue(v);
|
||||
}
|
||||
|
||||
this.hoverCoordinates = this.mousePosition &&
|
||||
|
@ -46,21 +46,9 @@ define(
|
||||
*
|
||||
*/
|
||||
function PlotAxis(axisType, metadatas, defaultValue) {
|
||||
var keys = {},
|
||||
options = [];
|
||||
|
||||
// Look through all metadata objects and assemble a list
|
||||
// of all possible domain or range options
|
||||
function buildOptionsForMetadata(m) {
|
||||
(m[axisType] || []).forEach(function (option) {
|
||||
if (!keys[option.key]) {
|
||||
keys[option.key] = true;
|
||||
options.push(option);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
(metadatas || []).forEach(buildOptionsForMetadata);
|
||||
this.axisType = axisType;
|
||||
this.defaultValue = defaultValue;
|
||||
this.optionKeys = {};
|
||||
|
||||
/**
|
||||
* The currently chosen option for this axis. An
|
||||
@ -68,7 +56,7 @@ define(
|
||||
* directly form the plot template.
|
||||
* @memberof platform/features/plot.PlotAxis#
|
||||
*/
|
||||
this.active = options[0] || defaultValue;
|
||||
this.active = defaultValue;
|
||||
|
||||
/**
|
||||
* The set of options applicable for this axis;
|
||||
@ -77,9 +65,71 @@ define(
|
||||
* human-readable names respectively)
|
||||
* @memberof platform/features/plot.PlotAxis#
|
||||
*/
|
||||
this.options = options;
|
||||
this.options = [];
|
||||
|
||||
// Initialize options from metadata objects
|
||||
this.updateMetadata(metadatas);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update axis options to reflect current metadata.
|
||||
* @param {TelemetryMetadata[]} metadata objects describing
|
||||
* applicable telemetry
|
||||
*/
|
||||
PlotAxis.prototype.updateMetadata = function (metadatas) {
|
||||
var axisType = this.axisType,
|
||||
optionKeys = this.optionKeys,
|
||||
newOptions = {},
|
||||
toAdd = [];
|
||||
|
||||
function isValid(option) {
|
||||
return option && optionKeys[option.key];
|
||||
}
|
||||
|
||||
metadatas.forEach(function (m) {
|
||||
(m[axisType] || []).forEach(function (option) {
|
||||
var key = option.key;
|
||||
if (!optionKeys[key] && !newOptions[key]) {
|
||||
toAdd.push(option);
|
||||
}
|
||||
newOptions[key] = true;
|
||||
});
|
||||
});
|
||||
|
||||
optionKeys = this.optionKeys = newOptions;
|
||||
|
||||
// General approach here is to avoid changing object
|
||||
// instances unless something has really changed, since
|
||||
// Angular is watching; don't want to trigger extra digests.
|
||||
if (!this.options.every(isValid)) {
|
||||
this.options = this.options.filter(isValid);
|
||||
}
|
||||
|
||||
if (toAdd.length > 0) {
|
||||
this.options = this.options.concat(toAdd);
|
||||
}
|
||||
|
||||
if (!isValid(this.active)) {
|
||||
this.active = this.options[0] || this.defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the domain/range selection for this axis. If the
|
||||
* provided `key` is not recognized as an option, no change
|
||||
* will occur.
|
||||
* @param {string} key the identifier for the domain/range
|
||||
*/
|
||||
PlotAxis.prototype.chooseOption = function (key) {
|
||||
var self = this;
|
||||
this.options.forEach(function (option) {
|
||||
if (option.key === key) {
|
||||
self.active = option;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return PlotAxis;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Wraps a `TelemetryFormatter` to provide formats for domain and
|
||||
* range values; provides a single place to track domain/range
|
||||
* formats within a plot, allowing other plot elements to simply
|
||||
* request that values be formatted.
|
||||
* @constructor
|
||||
* @memberof platform/features/plot
|
||||
* @implements {platform/telemetry.TelemetryFormatter}
|
||||
* @param {TelemetryFormatter} telemetryFormatter the formatter
|
||||
* to wrap.
|
||||
*/
|
||||
function PlotTelemetryFormatter(telemetryFormatter) {
|
||||
this.telemetryFormatter = telemetryFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the format to use for domain values.
|
||||
* @param {string} key the format's identifier
|
||||
*/
|
||||
PlotTelemetryFormatter.prototype.setDomainFormat = function (key) {
|
||||
this.domainFormat = key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Specify the format to use for range values.
|
||||
* @param {string} key the format's identifier
|
||||
*/
|
||||
PlotTelemetryFormatter.prototype.setRangeFormat = function (key) {
|
||||
this.rangeFormat = key;
|
||||
};
|
||||
|
||||
PlotTelemetryFormatter.prototype.formatDomainValue = function (value) {
|
||||
return this.telemetryFormatter
|
||||
.formatDomainValue(value, this.domainFormat);
|
||||
};
|
||||
|
||||
PlotTelemetryFormatter.prototype.formatRangeValue = function (value) {
|
||||
return this.telemetryFormatter
|
||||
.formatRangeValue(value, this.rangeFormat);
|
||||
};
|
||||
|
||||
return PlotTelemetryFormatter;
|
||||
}
|
||||
);
|
@ -43,6 +43,14 @@ define(
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
// For phantomjs compatibility, for headless testing
|
||||
// (Function.prototype.bind unsupported)
|
||||
function bind(fn, thisObj) {
|
||||
return fn.bind ? fn.bind(thisObj) : function () {
|
||||
return fn.apply(thisObj, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
// Generate ticks; interpolate from start up to
|
||||
// start + span in count steps, using the provided
|
||||
// formatter to represent each value.
|
||||
@ -72,7 +80,7 @@ define(
|
||||
panZoom.origin[0],
|
||||
panZoom.dimensions[0],
|
||||
count,
|
||||
this.formatter.formatDomainValue
|
||||
bind(this.formatter.formatDomainValue, this.formatter)
|
||||
);
|
||||
};
|
||||
|
||||
@ -87,7 +95,7 @@ define(
|
||||
panZoom.origin[1],
|
||||
panZoom.dimensions[1],
|
||||
count,
|
||||
this.formatter.formatRangeValue
|
||||
bind(this.formatter.formatRangeValue, this.formatter)
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -169,8 +169,9 @@ define(
|
||||
mockDomainObject
|
||||
]);
|
||||
|
||||
// Make an object available
|
||||
// Make an object available; invoke handler's callback
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
mockHandler.handle.mostRecentCall.args[1]();
|
||||
|
||||
expect(controller.getModeOptions().length).toEqual(1);
|
||||
|
||||
@ -181,8 +182,9 @@ define(
|
||||
mockDomainObject
|
||||
]);
|
||||
|
||||
// Make an object available
|
||||
// Make an object available; invoke handler's callback
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
mockHandler.handle.mostRecentCall.args[1]();
|
||||
|
||||
expect(controller.getModeOptions().length).toEqual(2);
|
||||
});
|
||||
|
@ -30,7 +30,12 @@ define(
|
||||
"use strict";
|
||||
|
||||
describe("A plot axis", function () {
|
||||
var testMetadatas = [
|
||||
var testMetadatas,
|
||||
testDefault,
|
||||
axis;
|
||||
|
||||
beforeEach(function () {
|
||||
testMetadatas = [
|
||||
{
|
||||
tests: [
|
||||
{ key: "t0", name: "T0" },
|
||||
@ -52,13 +57,14 @@ define(
|
||||
{ key: "t6", name: "T6" }
|
||||
]
|
||||
}
|
||||
],
|
||||
testDefault = { key: "test", name: "Test" },
|
||||
controller = new PlotAxis("tests", testMetadatas, testDefault);
|
||||
];
|
||||
testDefault = { key: "test", name: "Test" };
|
||||
axis = new PlotAxis("tests", testMetadatas, testDefault);
|
||||
});
|
||||
|
||||
it("pulls out a list of domain or range options", function () {
|
||||
// Should have filtered out duplicates, etc
|
||||
expect(controller.options).toEqual([
|
||||
expect(axis.options).toEqual([
|
||||
{ key: "t0", name: "T0" },
|
||||
{ key: "t1", name: "T1" },
|
||||
{ key: "t2", name: "T2" },
|
||||
@ -70,7 +76,7 @@ define(
|
||||
});
|
||||
|
||||
it("chooses the first option as a default", function () {
|
||||
expect(controller.active).toEqual({ key: "t0", name: "T0" });
|
||||
expect(axis.active).toEqual({ key: "t0", name: "T0" });
|
||||
});
|
||||
|
||||
it("falls back to a provided default if no options are present", function () {
|
||||
@ -78,6 +84,26 @@ define(
|
||||
.toEqual(testDefault);
|
||||
});
|
||||
|
||||
it("allows options to be chosen by key", function () {
|
||||
axis.chooseOption("t3");
|
||||
expect(axis.active).toEqual({ key: "t3", name: "T3" });
|
||||
});
|
||||
|
||||
it("reflects changes to applicable metadata", function () {
|
||||
axis.updateMetadata([ testMetadatas[1] ]);
|
||||
expect(axis.options).toEqual([
|
||||
{ key: "t0", name: "T0" },
|
||||
{ key: "t2", name: "T2" }
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns the same array instance for unchanged metadata", function () {
|
||||
// ...to avoid triggering extra digest cycles.
|
||||
var oldInstance = axis.options;
|
||||
axis.updateMetadata(testMetadatas);
|
||||
expect(axis.options).toBe(oldInstance);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
);
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/elements/PlotTelemetryFormatter"],
|
||||
function (PlotTelemetryFormatter) {
|
||||
'use strict';
|
||||
|
||||
describe("The PlotTelemetryFormatter", function () {
|
||||
var mockFormatter,
|
||||
formatter;
|
||||
|
||||
beforeEach(function () {
|
||||
mockFormatter = jasmine.createSpyObj(
|
||||
'telemetryFormatter',
|
||||
['formatDomainValue', 'formatRangeValue']
|
||||
);
|
||||
formatter = new PlotTelemetryFormatter(mockFormatter);
|
||||
});
|
||||
|
||||
describe("using domain & range format keys", function () {
|
||||
var rangeFormat = "someRangeFormat",
|
||||
domainFormat = "someDomainFormat";
|
||||
|
||||
beforeEach(function () {
|
||||
formatter.setRangeFormat(rangeFormat);
|
||||
formatter.setDomainFormat(domainFormat);
|
||||
});
|
||||
|
||||
it("includes format in formatDomainValue calls", function () {
|
||||
mockFormatter.formatDomainValue.andReturn("formatted!");
|
||||
expect(formatter.formatDomainValue(12321))
|
||||
.toEqual("formatted!");
|
||||
expect(mockFormatter.formatDomainValue)
|
||||
.toHaveBeenCalledWith(12321, domainFormat);
|
||||
});
|
||||
|
||||
it("includes format in formatRangeValue calls", function () {
|
||||
mockFormatter.formatRangeValue.andReturn("formatted!");
|
||||
expect(formatter.formatRangeValue(12321))
|
||||
.toEqual("formatted!");
|
||||
expect(mockFormatter.formatRangeValue)
|
||||
.toHaveBeenCalledWith(12321, rangeFormat);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -14,6 +14,7 @@
|
||||
"elements/PlotPosition",
|
||||
"elements/PlotPreparer",
|
||||
"elements/PlotSeriesWindow",
|
||||
"elements/PlotTelemetryFormatter",
|
||||
"elements/PlotTickGenerator",
|
||||
"elements/PlotUpdater",
|
||||
"modes/PlotModeOptions",
|
||||
|
@ -54,7 +54,8 @@ define(
|
||||
DomainColumn.prototype.getValue = function (domainObject, datum) {
|
||||
return {
|
||||
text: this.telemetryFormatter.formatDomainValue(
|
||||
datum[this.domainMetadata.key]
|
||||
datum[this.domainMetadata.key],
|
||||
this.domainMetadata.format
|
||||
)
|
||||
};
|
||||
};
|
||||
|
@ -4,12 +4,12 @@
|
||||
{
|
||||
"key": "mctInclude",
|
||||
"implementation": "MCTInclude.js",
|
||||
"depends": [ "templates[]", "$sce" ]
|
||||
"depends": [ "templates[]", "templateLinker" ]
|
||||
},
|
||||
{
|
||||
"key": "mctRepresentation",
|
||||
"implementation": "MCTRepresentation.js",
|
||||
"depends": [ "representations[]", "views[]", "representers[]", "$q", "$sce", "$log" ]
|
||||
"depends": [ "representations[]", "views[]", "representers[]", "$q", "templateLinker", "$log" ]
|
||||
}
|
||||
],
|
||||
"gestures": [
|
||||
@ -48,6 +48,12 @@
|
||||
"key": "dndService",
|
||||
"implementation": "services/DndService.js",
|
||||
"depends": [ "$log" ]
|
||||
},
|
||||
{
|
||||
"key": "templateLinker",
|
||||
"implementation": "TemplateLinker.js",
|
||||
"depends": [ "$templateRequest", "$sce", "$compile", "$log" ],
|
||||
"comment": "For internal use by mct-include and mct-representation."
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
|
@ -54,36 +54,38 @@ define(
|
||||
* @param {TemplateDefinition[]} templates an array of
|
||||
* template extensions
|
||||
*/
|
||||
function MCTInclude(templates, $sce) {
|
||||
function MCTInclude(templates, templateLinker) {
|
||||
var templateMap = {};
|
||||
|
||||
function link(scope, element) {
|
||||
var changeTemplate = templateLinker.link(
|
||||
scope,
|
||||
element,
|
||||
scope.key && templateMap[scope.key]
|
||||
);
|
||||
|
||||
scope.$watch('key', function (key) {
|
||||
changeTemplate(key && templateMap[key]);
|
||||
});
|
||||
}
|
||||
|
||||
// Prepopulate templateMap for easy look up by key
|
||||
templates.forEach(function (template) {
|
||||
var key = template.key,
|
||||
path = $sce.trustAsResourceUrl([
|
||||
template.bundle.path,
|
||||
template.bundle.resources,
|
||||
template.templateUrl
|
||||
].join("/"));
|
||||
var key = template.key;
|
||||
// First found should win (priority ordering)
|
||||
templateMap[key] = templateMap[key] || path;
|
||||
templateMap[key] =
|
||||
templateMap[key] || templateLinker.getPath(template);
|
||||
});
|
||||
|
||||
function controller($scope) {
|
||||
// Pass the template URL to ng-include via scope.
|
||||
$scope.inclusion = templateMap[$scope.key];
|
||||
}
|
||||
|
||||
return {
|
||||
// Only show at the element level
|
||||
restrict: "E",
|
||||
|
||||
// Use the included controller to populate scope
|
||||
controller: controller,
|
||||
link: link,
|
||||
|
||||
// Use ng-include as a template; "inclusion" will be the real
|
||||
// template path
|
||||
template: '<ng-include src="inclusion"></ng-include>',
|
||||
// May hide the element, so let other directives act first
|
||||
priority: -1000,
|
||||
|
||||
// Two-way bind key, ngModel, and parameters
|
||||
scope: { key: "=", ngModel: "=", parameters: "=" }
|
||||
|
@ -31,7 +31,6 @@ define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
|
||||
/**
|
||||
* Defines the mct-representation directive. This may be used to
|
||||
* present domain objects as HTML (with event wiring), with the
|
||||
@ -55,7 +54,7 @@ define(
|
||||
* representation extensions
|
||||
* @param {ViewDefinition[]} views an array of view extensions
|
||||
*/
|
||||
function MCTRepresentation(representations, views, representers, $q, $sce, $log) {
|
||||
function MCTRepresentation(representations, views, representers, $q, templateLinker, $log) {
|
||||
var representationMap = {},
|
||||
gestureMap = {};
|
||||
|
||||
@ -72,11 +71,7 @@ define(
|
||||
|
||||
// Get a path to a representation
|
||||
function getPath(representation) {
|
||||
return $sce.trustAsResourceUrl([
|
||||
representation.bundle.path,
|
||||
representation.bundle.resources,
|
||||
representation.templateUrl
|
||||
].join("/"));
|
||||
return templateLinker.getPath(representation);
|
||||
}
|
||||
|
||||
// Look up a matching representation for this domain object
|
||||
@ -94,12 +89,16 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
function link($scope, element, attrs) {
|
||||
function link($scope, element, attrs, ctrl, transclude) {
|
||||
var activeRepresenters = representers.map(function (Representer) {
|
||||
return new Representer($scope, element, attrs);
|
||||
}),
|
||||
toClear = [], // Properties to clear out of scope on change
|
||||
counter = 0;
|
||||
counter = 0,
|
||||
couldRepresent = false,
|
||||
lastId,
|
||||
lastKey,
|
||||
changeTemplate = templateLinker.link($scope, element);
|
||||
|
||||
// Populate scope with any capabilities indicated by the
|
||||
// representation's extension definition
|
||||
@ -144,21 +143,36 @@ define(
|
||||
});
|
||||
}
|
||||
|
||||
function unchanged(canRepresent, id, key) {
|
||||
return canRepresent &&
|
||||
couldRepresent &&
|
||||
id === lastId &&
|
||||
key === lastKey;
|
||||
}
|
||||
|
||||
// General-purpose refresh mechanism; should set up the scope
|
||||
// as appropriate for current representation key and
|
||||
// domain object.
|
||||
function refresh() {
|
||||
var domainObject = $scope.domainObject,
|
||||
representation = lookup($scope.key, domainObject),
|
||||
uses = ((representation || {}).uses || []);
|
||||
path = representation && getPath(representation),
|
||||
uses = ((representation || {}).uses || []),
|
||||
canRepresent = !!(path && domainObject),
|
||||
id = domainObject && domainObject.getId(),
|
||||
key = $scope.key;
|
||||
|
||||
if (unchanged(canRepresent, id, key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create an empty object named "representation", for this
|
||||
// representation to store local variables into.
|
||||
$scope.representation = {};
|
||||
|
||||
// Look up the actual template path, pass it to ng-include
|
||||
// via the "inclusion" field
|
||||
$scope.inclusion = representation && getPath(representation);
|
||||
// Change templates (passing in undefined to clear
|
||||
// if we don't have enough info to show a template.)
|
||||
changeTemplate(canRepresent ? path : undefined);
|
||||
|
||||
// Any existing representers are no longer valid; release them.
|
||||
destroyRepresenters();
|
||||
@ -174,9 +188,14 @@ define(
|
||||
delete $scope[property];
|
||||
});
|
||||
|
||||
// To allow simplified change detection next time around
|
||||
couldRepresent = canRepresent;
|
||||
lastId = id;
|
||||
lastKey = key;
|
||||
|
||||
// Populate scope with fields associated with the current
|
||||
// domain object (if one has been passed in)
|
||||
if (domainObject) {
|
||||
if (canRepresent) {
|
||||
// Track how many representations we've made in this scope,
|
||||
// to ensure that the correct representations are matched to
|
||||
// the correct object/key pairs.
|
||||
@ -233,9 +252,8 @@ define(
|
||||
// Handle Angular's linking step
|
||||
link: link,
|
||||
|
||||
// Use ng-include as a template; "inclusion" will be the real
|
||||
// template path
|
||||
template: '<ng-include src="inclusion"></ng-include>',
|
||||
// May hide the element, so let other directives act first
|
||||
priority: -1000,
|
||||
|
||||
// Two-way bind key and parameters, get the represented domain
|
||||
// object as "mct-object"
|
||||
|
163
platform/representation/src/TemplateLinker.js
Normal file
163
platform/representation/src/TemplateLinker.js
Normal file
@ -0,0 +1,163 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The `templateLinker` service is intended for internal use by
|
||||
* the `mct-include` and `mct-representation` directives. It is
|
||||
* used to support common behavior of directives; specifically,
|
||||
* loading templates and inserting them into a specified element,
|
||||
* and/or removing that element from the DOM when there is no
|
||||
* template to populate it with.
|
||||
*
|
||||
* @param {Function} $templateRequest Angular's `$templateRequest`
|
||||
* service
|
||||
* @param $sce Angular's `$sce` service
|
||||
* @param {Function} $compile Angular's `$compile` service
|
||||
* @param $log Angular's `$log` service
|
||||
* @private
|
||||
*/
|
||||
function TemplateLinker($templateRequest, $sce, $compile, $log) {
|
||||
this.$templateRequest = $templateRequest;
|
||||
this.$sce = $sce;
|
||||
this.$compile = $compile;
|
||||
this.$log = $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a template from the given URL. This request will be handled
|
||||
* via `$templateRequest` to ensure caching et cetera.
|
||||
* @param {string} the URL for the template
|
||||
* @returns {Promise.<string>} a promise for the HTML content of
|
||||
* the template
|
||||
* @private
|
||||
*/
|
||||
TemplateLinker.prototype.load = function (templateUrl) {
|
||||
return this.$templateRequest(
|
||||
this.$sce.trustAsResourceUrl(templateUrl),
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a path to a template from an extension definition fo
|
||||
* a template, representation, or view.
|
||||
* @param {TemplateDefinition} extensionDefinition the definition
|
||||
* of the template/representation/view to resolve
|
||||
*/
|
||||
TemplateLinker.prototype.getPath = function (extensionDefinition) {
|
||||
return [
|
||||
extensionDefinition.bundle.path,
|
||||
extensionDefinition.bundle.resources,
|
||||
extensionDefinition.templateUrl
|
||||
].join('/');
|
||||
};
|
||||
|
||||
/**
|
||||
* Populate the given element with templates, within the given scope;
|
||||
* intended to support the `link` function of the supported directives.
|
||||
*
|
||||
* @param {Scope} scope the Angular scope to use when rendering
|
||||
* templates
|
||||
* @param element the jqLite-wrapped element into which templates
|
||||
* should be inserted
|
||||
* @returns {Function} a function which can be called with a template
|
||||
* URL to switch templates, or `undefined` to remove.
|
||||
*/
|
||||
TemplateLinker.prototype.link = function (scope, element, templateUrl) {
|
||||
var activeElement = element,
|
||||
activeTemplateUrl,
|
||||
comment = this.$compile('<!-- hidden mct element -->')(scope),
|
||||
activeScope,
|
||||
self = this;
|
||||
|
||||
function destroyScope() {
|
||||
if (activeScope) {
|
||||
activeScope.$destroy();
|
||||
activeScope = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function removeElement() {
|
||||
if (activeElement !== comment) {
|
||||
destroyScope();
|
||||
activeElement.replaceWith(comment);
|
||||
activeElement = comment;
|
||||
}
|
||||
}
|
||||
|
||||
function addElement() {
|
||||
if (activeElement !== element) {
|
||||
activeElement.replaceWith(element);
|
||||
activeElement = element;
|
||||
activeElement.empty();
|
||||
}
|
||||
}
|
||||
|
||||
function populateElement(template) {
|
||||
destroyScope();
|
||||
activeScope = scope.$new(false);
|
||||
element.html(template);
|
||||
self.$compile(element.contents())(activeScope);
|
||||
}
|
||||
|
||||
function badTemplate(templateUrl) {
|
||||
self.$log.warn("Couldn't load template at " + templateUrl);
|
||||
removeElement();
|
||||
}
|
||||
|
||||
function changeTemplate(templateUrl) {
|
||||
if (templateUrl) {
|
||||
destroyScope();
|
||||
addElement();
|
||||
self.load(templateUrl).then(function (template) {
|
||||
// Avoid race conditions
|
||||
if (templateUrl === activeTemplateUrl) {
|
||||
populateElement(template);
|
||||
}
|
||||
}, function () {
|
||||
badTemplate(templateUrl);
|
||||
});
|
||||
} else {
|
||||
removeElement();
|
||||
}
|
||||
activeTemplateUrl = templateUrl;
|
||||
}
|
||||
|
||||
if (templateUrl) {
|
||||
changeTemplate(templateUrl);
|
||||
} else {
|
||||
removeElement();
|
||||
}
|
||||
|
||||
return changeTemplate;
|
||||
};
|
||||
|
||||
return TemplateLinker;
|
||||
}
|
||||
);
|
||||
|
@ -31,9 +31,21 @@ define(
|
||||
|
||||
describe("The mct-include directive", function () {
|
||||
var testTemplates,
|
||||
mockSce,
|
||||
testUrls,
|
||||
mockLinker,
|
||||
mockScope,
|
||||
mockElement,
|
||||
mockChangeTemplate,
|
||||
mctInclude;
|
||||
|
||||
function fireWatch(expr, value) {
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
call.args[1](value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
testTemplates = [
|
||||
{
|
||||
@ -47,40 +59,44 @@ define(
|
||||
templateUrl: "z/template.html"
|
||||
}
|
||||
];
|
||||
mockSce = jasmine.createSpyObj(
|
||||
'$sce',
|
||||
['trustAsResourceUrl']
|
||||
);
|
||||
mockSce.trustAsResourceUrl.andCallFake(function (url) {
|
||||
return url;
|
||||
testUrls = {};
|
||||
testTemplates.forEach(function (t, i) {
|
||||
testUrls[t.key] = "some URL " + String(i);
|
||||
});
|
||||
mctInclude = new MCTInclude(testTemplates, mockSce);
|
||||
});
|
||||
|
||||
it("has a built-in template, with ng-include src=inclusion", function () {
|
||||
// Not rigorous, but should detect many cases when template is broken.
|
||||
expect(mctInclude.template.indexOf("ng-include")).not.toEqual(-1);
|
||||
expect(mctInclude.template.indexOf("inclusion")).not.toEqual(-1);
|
||||
mockLinker = jasmine.createSpyObj(
|
||||
'templateLinker',
|
||||
['link', 'getPath']
|
||||
);
|
||||
mockScope = jasmine.createSpyObj('$scope', ['$watch', '$on']);
|
||||
mockElement = jasmine.createSpyObj('element', ['empty']);
|
||||
mockChangeTemplate = jasmine.createSpy('changeTemplate');
|
||||
mockLinker.link.andReturn(mockChangeTemplate);
|
||||
mockLinker.getPath.andCallFake(function (template) {
|
||||
return testUrls[template.key];
|
||||
});
|
||||
mctInclude = new MCTInclude(testTemplates, mockLinker);
|
||||
mctInclude.link(mockScope, mockElement, {});
|
||||
});
|
||||
|
||||
it("is restricted to elements", function () {
|
||||
expect(mctInclude.restrict).toEqual("E");
|
||||
});
|
||||
|
||||
it("reads a template location from a scope's key variable", function () {
|
||||
var scope = { key: "abc" };
|
||||
mctInclude.controller(scope);
|
||||
expect(scope.inclusion).toEqual("a/b/c/template.html");
|
||||
|
||||
scope = { key: "xyz" };
|
||||
mctInclude.controller(scope);
|
||||
expect(scope.inclusion).toEqual("x/y/z/template.html");
|
||||
it("exposes templates via the templateLinker", function () {
|
||||
expect(mockLinker.link)
|
||||
.toHaveBeenCalledWith(mockScope, mockElement, undefined);
|
||||
});
|
||||
|
||||
it("trusts template URLs", function () {
|
||||
mctInclude.controller({ key: "xyz" });
|
||||
expect(mockSce.trustAsResourceUrl)
|
||||
.toHaveBeenCalledWith("x/y/z/template.html");
|
||||
it("reads a template location from a scope's key variable", function () {
|
||||
mockScope.key = 'abc';
|
||||
fireWatch('key', mockScope.key);
|
||||
expect(mockChangeTemplate)
|
||||
.toHaveBeenCalledWith(testUrls.abc);
|
||||
|
||||
mockScope.key = 'xyz';
|
||||
fireWatch('key', mockScope.key);
|
||||
expect(mockChangeTemplate)
|
||||
.toHaveBeenCalledWith(testUrls.xyz);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -36,10 +36,12 @@ define(
|
||||
describe("The mct-representation directive", function () {
|
||||
var testRepresentations,
|
||||
testViews,
|
||||
testUrls,
|
||||
mockRepresenters,
|
||||
mockQ,
|
||||
mockSce,
|
||||
mockLinker,
|
||||
mockLog,
|
||||
mockChangeTemplate,
|
||||
mockScope,
|
||||
mockElement,
|
||||
mockDomainObject,
|
||||
@ -54,7 +56,17 @@ define(
|
||||
};
|
||||
}
|
||||
|
||||
function fireWatch(expr, value) {
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
call.args[1](value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
testUrls = {};
|
||||
|
||||
testRepresentations = [
|
||||
{
|
||||
key: "abc",
|
||||
@ -85,6 +97,11 @@ define(
|
||||
|
||||
testModel = { someKey: "some value" };
|
||||
|
||||
testUrls = {};
|
||||
testViews.concat(testRepresentations).forEach(function (t, i) {
|
||||
testUrls[t.key] = "some URL " + String(i);
|
||||
});
|
||||
|
||||
mockRepresenters = ["A", "B"].map(function (name) {
|
||||
var constructor = jasmine.createSpy("Representer" + name),
|
||||
representer = jasmine.createSpyObj(
|
||||
@ -96,45 +113,44 @@ define(
|
||||
});
|
||||
|
||||
mockQ = { when: mockPromise };
|
||||
mockSce = jasmine.createSpyObj(
|
||||
'$sce',
|
||||
['trustAsResourceUrl']
|
||||
mockLinker = jasmine.createSpyObj(
|
||||
'templateLinker',
|
||||
['link', 'getPath']
|
||||
);
|
||||
mockChangeTemplate = jasmine.createSpy('changeTemplate');
|
||||
mockLog = jasmine.createSpyObj("$log", LOG_FUNCTIONS);
|
||||
|
||||
|
||||
mockSce.trustAsResourceUrl.andCallFake(function (url) {
|
||||
return url;
|
||||
});
|
||||
mockScope = jasmine.createSpyObj("scope", [ "$watch", "$on" ]);
|
||||
mockElement = jasmine.createSpyObj("element", JQLITE_FUNCTIONS);
|
||||
mockDomainObject = jasmine.createSpyObj("domainObject", DOMAIN_OBJECT_METHODS);
|
||||
|
||||
mockDomainObject.getModel.andReturn(testModel);
|
||||
mockLinker.link.andReturn(mockChangeTemplate);
|
||||
mockLinker.getPath.andCallFake(function (ext) {
|
||||
return testUrls[ext.key];
|
||||
});
|
||||
|
||||
mctRepresentation = new MCTRepresentation(
|
||||
testRepresentations,
|
||||
testViews,
|
||||
mockRepresenters,
|
||||
mockQ,
|
||||
mockSce,
|
||||
mockLinker,
|
||||
mockLog
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it("has a built-in template, with ng-include src=inclusion", function () {
|
||||
// Not rigorous, but should detect many cases when template is broken.
|
||||
expect(mctRepresentation.template.indexOf("ng-include")).not.toEqual(-1);
|
||||
expect(mctRepresentation.template.indexOf("inclusion")).not.toEqual(-1);
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
});
|
||||
|
||||
it("is restricted to elements", function () {
|
||||
expect(mctRepresentation.restrict).toEqual("E");
|
||||
});
|
||||
|
||||
it("exposes templates via the templateLinker", function () {
|
||||
expect(mockLinker.link)
|
||||
.toHaveBeenCalledWith(mockScope, mockElement);
|
||||
});
|
||||
|
||||
it("watches scope when linked", function () {
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||
"key",
|
||||
jasmine.any(Function)
|
||||
@ -150,42 +166,46 @@ define(
|
||||
});
|
||||
|
||||
it("recognizes keys for representations", function () {
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
|
||||
mockScope.key = "abc";
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
|
||||
// Trigger the watch
|
||||
mockScope.$watch.calls[0].args[1]();
|
||||
fireWatch('key', mockScope.key);
|
||||
fireWatch('domainObject', mockDomainObject);
|
||||
|
||||
expect(mockScope.inclusion).toEqual("a/b/c/template.html");
|
||||
expect(mockChangeTemplate)
|
||||
.toHaveBeenCalledWith(testUrls.abc);
|
||||
});
|
||||
|
||||
it("recognizes keys for views", function () {
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
|
||||
mockScope.key = "xyz";
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
|
||||
// Trigger the watch
|
||||
mockScope.$watch.calls[0].args[1]();
|
||||
// Trigger the watches
|
||||
fireWatch('key', mockScope.key);
|
||||
fireWatch('domainObject', mockDomainObject);
|
||||
|
||||
expect(mockScope.inclusion).toEqual("x/y/z/template.html");
|
||||
expect(mockChangeTemplate)
|
||||
.toHaveBeenCalledWith(testUrls.xyz);
|
||||
});
|
||||
|
||||
it("trusts template URLs", function () {
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
|
||||
it("does not load templates until there is an object", function () {
|
||||
mockScope.key = "xyz";
|
||||
|
||||
// Trigger the watch
|
||||
mockScope.$watch.calls[0].args[1]();
|
||||
fireWatch('key', mockScope.key);
|
||||
|
||||
expect(mockSce.trustAsResourceUrl)
|
||||
.toHaveBeenCalledWith("x/y/z/template.html");
|
||||
expect(mockChangeTemplate)
|
||||
.not.toHaveBeenCalledWith(jasmine.any(String));
|
||||
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
fireWatch('domainObject', mockDomainObject);
|
||||
|
||||
expect(mockChangeTemplate)
|
||||
.toHaveBeenCalledWith(jasmine.any(String));
|
||||
});
|
||||
|
||||
it("loads declared capabilities", function () {
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
|
||||
mockScope.key = "def";
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
|
||||
@ -199,8 +219,6 @@ define(
|
||||
});
|
||||
|
||||
it("logs when no representation is available for a key", function () {
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
|
||||
mockScope.key = "someUnknownThing";
|
||||
|
||||
// Verify precondition
|
||||
@ -214,8 +232,6 @@ define(
|
||||
});
|
||||
|
||||
it("clears out obsolete peroperties from scope", function () {
|
||||
mctRepresentation.link(mockScope, mockElement);
|
||||
|
||||
mockScope.key = "def";
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
mockDomainObject.useCapability.andReturn("some value");
|
||||
|
230
platform/representation/test/TemplateLinkerSpec.js
Normal file
230
platform/representation/test/TemplateLinkerSpec.js
Normal file
@ -0,0 +1,230 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
|
||||
define(
|
||||
["../src/TemplateLinker"],
|
||||
function (TemplateLinker) {
|
||||
'use strict';
|
||||
|
||||
var JQLITE_METHODS = [ 'replaceWith', 'empty', 'html', 'contents' ],
|
||||
SCOPE_METHODS = [ '$on', '$new', '$destroy' ];
|
||||
|
||||
describe("TemplateLinker", function () {
|
||||
var mockTemplateRequest,
|
||||
mockSce,
|
||||
mockCompile,
|
||||
mockLog,
|
||||
mockScope,
|
||||
mockElement,
|
||||
mockTemplates,
|
||||
mockElements,
|
||||
mockContents,
|
||||
mockNewScope,
|
||||
mockPromise,
|
||||
linker;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTemplateRequest = jasmine.createSpy('$templateRequest');
|
||||
mockSce = jasmine.createSpyObj('$sce', ['trustAsResourceUrl']);
|
||||
mockCompile = jasmine.createSpy('$compile');
|
||||
mockLog = jasmine.createSpyObj('$log', ['error', 'warn']);
|
||||
mockScope = jasmine.createSpyObj('$scope', SCOPE_METHODS);
|
||||
mockNewScope = jasmine.createSpyObj('$scope', SCOPE_METHODS);
|
||||
mockElement = jasmine.createSpyObj('element', JQLITE_METHODS);
|
||||
mockPromise = jasmine.createSpyObj('promise', ['then']);
|
||||
mockTemplates = {};
|
||||
mockElements = {};
|
||||
mockContents = {};
|
||||
|
||||
mockTemplateRequest.andReturn(mockPromise);
|
||||
mockCompile.andCallFake(function (toCompile) {
|
||||
var html = typeof toCompile === 'string' ?
|
||||
toCompile : toCompile.testHtml;
|
||||
mockTemplates[html] = jasmine.createSpy('template');
|
||||
mockElements[html] =
|
||||
jasmine.createSpyObj('templateEl', JQLITE_METHODS);
|
||||
mockTemplates[html].andReturn(mockElements[html]);
|
||||
return mockTemplates[html];
|
||||
});
|
||||
mockSce.trustAsResourceUrl.andCallFake(function (url) {
|
||||
return { trusted: url };
|
||||
});
|
||||
mockScope.$new.andReturn(mockNewScope);
|
||||
mockElement.html.andCallFake(function (html) {
|
||||
mockContents[html] =
|
||||
jasmine.createSpyObj('contentsEl', JQLITE_METHODS);
|
||||
mockContents[html].testHtml = html;
|
||||
});
|
||||
mockElement.contents.andCallFake(function () {
|
||||
return mockContents[
|
||||
mockElement.html.mostRecentCall.args[0]
|
||||
];
|
||||
});
|
||||
|
||||
linker = new TemplateLinker(
|
||||
mockTemplateRequest,
|
||||
mockSce,
|
||||
mockCompile,
|
||||
mockLog
|
||||
);
|
||||
});
|
||||
|
||||
it("resolves extension paths", function () {
|
||||
expect(linker.getPath({
|
||||
bundle: {
|
||||
path: 'a',
|
||||
resources: 'b'
|
||||
},
|
||||
templateUrl: 'c/d.html'
|
||||
})).toEqual('a/b/c/d.html');
|
||||
});
|
||||
|
||||
describe("when linking elements", function () {
|
||||
var changeTemplate,
|
||||
commentElement;
|
||||
|
||||
function findCommentElement() {
|
||||
mockCompile.calls.forEach(function (call) {
|
||||
var html = call.args[0];
|
||||
if (html.indexOf("<!--") > -1) {
|
||||
commentElement = mockElements[html];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
changeTemplate = linker.link(mockScope, mockElement);
|
||||
findCommentElement();
|
||||
});
|
||||
|
||||
it("compiles a comment to use to replace element", function () {
|
||||
expect(commentElement).toBeDefined();
|
||||
});
|
||||
|
||||
it("initially replaces elements with comments", function () {
|
||||
expect(mockElement.replaceWith)
|
||||
.toHaveBeenCalledWith(commentElement);
|
||||
});
|
||||
|
||||
it("provides a function to change templates", function () {
|
||||
expect(changeTemplate).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
describe("and then changing templates", function () {
|
||||
var testUrl,
|
||||
testTemplate;
|
||||
|
||||
beforeEach(function () {
|
||||
testUrl = "some/url/template.html";
|
||||
testTemplate = "<div>Some template!</div>";
|
||||
changeTemplate(testUrl);
|
||||
mockPromise.then.mostRecentCall
|
||||
.args[0](testTemplate);
|
||||
});
|
||||
|
||||
it("loads templates using $templateRequest", function () {
|
||||
expect(mockTemplateRequest).toHaveBeenCalledWith({
|
||||
trusted: testUrl
|
||||
}, false);
|
||||
});
|
||||
|
||||
it("compiles element contents with a new scope", function () {
|
||||
expect(mockCompile)
|
||||
.toHaveBeenCalledWith(mockContents[testTemplate]);
|
||||
expect(mockTemplates[testTemplate])
|
||||
.toHaveBeenCalledWith(mockNewScope);
|
||||
});
|
||||
|
||||
it("replaces comments with specified element", function () {
|
||||
expect(commentElement.replaceWith)
|
||||
.toHaveBeenCalledWith(mockElement);
|
||||
});
|
||||
|
||||
it("inserts HTML content into the specified element", function () {
|
||||
expect(mockElement.html)
|
||||
.toHaveBeenCalledWith(testTemplate);
|
||||
});
|
||||
|
||||
it("clears templates when called with undefined", function () {
|
||||
expect(mockElement.replaceWith.callCount)
|
||||
.toEqual(1);
|
||||
changeTemplate(undefined);
|
||||
expect(mockElement.replaceWith.callCount)
|
||||
.toEqual(2);
|
||||
expect(mockElement.replaceWith.mostRecentCall.args[0])
|
||||
.toEqual(commentElement);
|
||||
});
|
||||
|
||||
it("logs no warnings for nominal changes", function () {
|
||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("which cannot be found", function () {
|
||||
beforeEach(function () {
|
||||
changeTemplate("some/bad/url");
|
||||
// Reject the template promise
|
||||
mockPromise.then.mostRecentCall.args[1]();
|
||||
});
|
||||
|
||||
it("removes the element from the DOM", function () {
|
||||
expect(mockElement.replaceWith.callCount)
|
||||
.toEqual(2);
|
||||
expect(
|
||||
mockElement.replaceWith.mostRecentCall.args[0]
|
||||
).toEqual(commentElement);
|
||||
});
|
||||
|
||||
it("logs a warning", function () {
|
||||
expect(mockLog.warn)
|
||||
.toHaveBeenCalledWith(jasmine.any(String));
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("when an initial template URL is provided", function () {
|
||||
var testUrl;
|
||||
|
||||
beforeEach(function () {
|
||||
testUrl = "some/test/url.html";
|
||||
linker.link(mockScope, mockElement, testUrl);
|
||||
});
|
||||
|
||||
it("does not remove the element initially", function () {
|
||||
expect(mockElement.replaceWith)
|
||||
.not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("loads the specified template", function () {
|
||||
expect(mockTemplateRequest).toHaveBeenCalledWith({
|
||||
trusted: testUrl
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -7,5 +7,6 @@
|
||||
"gestures/GestureRepresenter",
|
||||
"services/DndService",
|
||||
"MCTInclude",
|
||||
"MCTRepresentation"
|
||||
]
|
||||
"MCTRepresentation",
|
||||
"TemplateLinker"
|
||||
]
|
||||
|
@ -27,6 +27,12 @@
|
||||
}
|
||||
],
|
||||
"representations": [
|
||||
{
|
||||
"key": "search-item",
|
||||
"templateUrl": "templates/search-item.html"
|
||||
}
|
||||
],
|
||||
"templates": [
|
||||
{
|
||||
"key": "search",
|
||||
"templateUrl": "templates/search.html"
|
||||
@ -34,10 +40,6 @@
|
||||
{
|
||||
"key": "search-menu",
|
||||
"templateUrl": "templates/search-menu.html"
|
||||
},
|
||||
{
|
||||
"key": "search-item",
|
||||
"templateUrl": "templates/search-item.html"
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
|
@ -43,7 +43,7 @@
|
||||
<a class="ui-symbol clear-icon"
|
||||
ng-class="{content: !(ngModel.input === '' || ngModel.input === undefined)}"
|
||||
ng-click="ngModel.input = ''; controller.search()">
|
||||

|
||||

|
||||
</a>
|
||||
|
||||
<!-- Menu icon/button 'v' -->
|
||||
@ -53,12 +53,12 @@
|
||||
</a>
|
||||
|
||||
<!-- Menu -->
|
||||
<mct-representation key="'search-menu'"
|
||||
<mct-include key="'search-menu'"
|
||||
class="menu-element search-menu-holder"
|
||||
ng-class="{off: !toggle.isActive()}"
|
||||
ng-model="ngModel"
|
||||
ng-click="toggle.setState(true)">
|
||||
</mct-representation>
|
||||
</mct-include>
|
||||
</div>
|
||||
|
||||
<!-- Active filter display -->
|
||||
@ -71,7 +71,7 @@
|
||||

|
||||
</a>
|
||||
|
||||
Filtered by: {{ ngModel.filtersString }}
|
||||
Filtered by: {{ ngModel.filtersString }}
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -37,7 +37,8 @@
|
||||
"services": [
|
||||
{
|
||||
"key": "telemetryFormatter",
|
||||
"implementation": "TelemetryFormatter.js"
|
||||
"implementation": "TelemetryFormatter.js",
|
||||
"depends": [ "formatService", "DEFAULT_TIME_FORMAT" ]
|
||||
},
|
||||
{
|
||||
"key": "telemetrySubscriber",
|
||||
@ -63,4 +64,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,64 @@ define(
|
||||
getRangeValue: ZERO
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides metadata about telemetry associated with a
|
||||
* given domain object.
|
||||
*
|
||||
* @typedef TelemetryMetadata
|
||||
* @property {string} source the machine-readable identifier for
|
||||
* the source of telemetry data for this object; used by
|
||||
* {@link TelemetryService} implementations to determine
|
||||
* whether or not they provide data for this object.
|
||||
* @property {string} key the machine-readable identifier for
|
||||
* telemetry data associated with this specific object,
|
||||
* within that `source`.
|
||||
* @property {TelemetryDomainMetadata[]} domains supported domain
|
||||
* options for telemetry data associated with this object,
|
||||
* to use in interpreting a {@link TelemetrySeries}
|
||||
* @property {TelemetryRangeMetadata[]} ranges supported range
|
||||
* options for telemetry data associated with this object,
|
||||
* to use in interpreting a {@link TelemetrySeries}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides metadata about range options within a telemetry series.
|
||||
* Range options describe distinct properties within any given datum
|
||||
* of a telemetry series; for instance, a telemetry series containing
|
||||
* both raw and uncalibrated values may provide separate ranges for
|
||||
* each.
|
||||
*
|
||||
* @typedef TelemetryRangeMetadata
|
||||
* @property {string} key machine-readable identifier for this range
|
||||
* @property {string} name human-readable name for this range
|
||||
* @property {string} [units] human-readable units for this range
|
||||
* @property {string} [format] data format for this range; usually,
|
||||
* one of `number`, or `string`. If `undefined`,
|
||||
* should presume to be a `number`. Custom formats
|
||||
* may be indicated here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides metadata about domain options within a telemetry series.
|
||||
* Domain options describe distinct properties within any given datum
|
||||
* of a telemtry series; for instance, a telemetry series containing
|
||||
* both spacecraft event time and earth received times may provide
|
||||
* separate domains for each.
|
||||
*
|
||||
* Domains are typically used to represent timestamps in a telemetry
|
||||
* series, but more generally may express any property which will
|
||||
* have unique values for each datum in a series. It is this property
|
||||
* which makes domains distinct from ranges, as it makes these values
|
||||
* appropriate and meaningful for use to sort and bound a series.
|
||||
*
|
||||
* @typedef TelemetryDomainMetadata
|
||||
* @property {string} key machine-readable identifier for this range
|
||||
* @property {string} name human-readable name for this range
|
||||
* @property {string} [system] machine-readable identifier for the
|
||||
* time/date system associated with this domain;
|
||||
* used by {@link DateService}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A telemetry capability provides a means of requesting telemetry
|
||||
* for a specific object, and for unwrapping the response (to get
|
||||
|
@ -22,14 +22,13 @@
|
||||
/*global define,moment*/
|
||||
|
||||
define(
|
||||
['moment'],
|
||||
function (moment) {
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
// Date format to use for domain values; in particular,
|
||||
// use day-of-year instead of month/day
|
||||
var DATE_FORMAT = "YYYY-DDD HH:mm:ss",
|
||||
VALUE_FORMAT_DIGITS = 3;
|
||||
var VALUE_FORMAT_DIGITS = 3;
|
||||
|
||||
/**
|
||||
* The TelemetryFormatter is responsible for formatting (as text
|
||||
@ -37,22 +36,31 @@ define(
|
||||
* the range (usually value) of a data series.
|
||||
* @memberof platform/telemetry
|
||||
* @constructor
|
||||
* @param {FormatService} formatService the service to user to format
|
||||
* domain values
|
||||
* @param {string} defaultFormatKey the format to request when no
|
||||
* format has been otherwise specified
|
||||
*/
|
||||
function TelemetryFormatter() {
|
||||
function TelemetryFormatter(formatService, defaultFormatKey) {
|
||||
this.formatService = formatService;
|
||||
this.defaultFormat = formatService.getFormat(defaultFormatKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a domain value.
|
||||
* @param {number} v the domain value; a timestamp
|
||||
* @param {number} v the domain value; usually, a timestamp
|
||||
* in milliseconds since start of 1970
|
||||
* @param {string} [key] the key which identifies the
|
||||
* domain; if unspecified or unknown, this will
|
||||
* be treated as a standard timestamp.
|
||||
* @param {string} [key] a key which identifies the format
|
||||
* to use
|
||||
* @returns {string} a textual representation of the
|
||||
* data and time, suitable for display.
|
||||
*/
|
||||
TelemetryFormatter.prototype.formatDomainValue = function (v, key) {
|
||||
return isNaN(v) ? "" : moment.utc(v).format(DATE_FORMAT);
|
||||
var formatter = (key === undefined) ?
|
||||
this.defaultFormat :
|
||||
this.formatService.getFormat(key);
|
||||
|
||||
return isNaN(v) ? "" : formatter.format(v);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user