mirror of
https://github.com/nasa/openmct.git
synced 2025-06-26 03:00:13 +00:00
Compare commits
35 Commits
adding-uni
...
open933-fr
Author | SHA1 | Date | |
---|---|---|---|
4087b9cdde | |||
43a804eef4 | |||
b3a4f52fe2 | |||
671e3016d4 | |||
379828315f | |||
8c5538ec4d | |||
8b694ef337 | |||
e193e3dfba | |||
8214c8e895 | |||
33b2225d10 | |||
14463d39a8 | |||
fcfda50e73 | |||
06af84c161 | |||
5238aa2731 | |||
fd29473664 | |||
97f3fd516b | |||
088416905d | |||
2056d87453 | |||
64ce8a2b2a | |||
585da38a16 | |||
bf0e85a94c | |||
84b7a9dc2f | |||
11caa8396a | |||
0017b77439 | |||
7b7b21d748 | |||
788483ec13 | |||
7b19f91ce6 | |||
5cc81ba12a | |||
0a0bc55f5f | |||
4e7b69c4df | |||
cf83040c4b | |||
32f7bc86af | |||
e230b92946 | |||
58ed500ecf | |||
bca5eb0fdb |
@ -18,6 +18,8 @@
|
|||||||
"node-uuid": "^1.4.7",
|
"node-uuid": "^1.4.7",
|
||||||
"comma-separated-values": "^3.6.4",
|
"comma-separated-values": "^3.6.4",
|
||||||
"FileSaver.js": "^0.0.2",
|
"FileSaver.js": "^0.0.2",
|
||||||
"zepto": "^1.1.6"
|
"zepto": "^1.1.6",
|
||||||
|
"eventemitter3": "^1.2.0",
|
||||||
|
"d3": "~4.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
main.js
11
main.js
@ -28,13 +28,15 @@ requirejs.config({
|
|||||||
"angular-route": "bower_components/angular-route/angular-route.min",
|
"angular-route": "bower_components/angular-route/angular-route.min",
|
||||||
"csv": "bower_components/comma-separated-values/csv.min",
|
"csv": "bower_components/comma-separated-values/csv.min",
|
||||||
"es6-promise": "bower_components/es6-promise/promise.min",
|
"es6-promise": "bower_components/es6-promise/promise.min",
|
||||||
|
"EventEmitter": "bower_components/eventemitter3/index",
|
||||||
"moment": "bower_components/moment/moment",
|
"moment": "bower_components/moment/moment",
|
||||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||||
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
||||||
"screenfull": "bower_components/screenfull/dist/screenfull.min",
|
"screenfull": "bower_components/screenfull/dist/screenfull.min",
|
||||||
"text": "bower_components/text/text",
|
"text": "bower_components/text/text",
|
||||||
"uuid": "bower_components/node-uuid/uuid",
|
"uuid": "bower_components/node-uuid/uuid",
|
||||||
"zepto": "bower_components/zepto/zepto.min"
|
"zepto": "bower_components/zepto/zepto.min",
|
||||||
|
"d3": "bower_components/d3/d3.min"
|
||||||
},
|
},
|
||||||
"shim": {
|
"shim": {
|
||||||
"angular": {
|
"angular": {
|
||||||
@ -43,6 +45,9 @@ requirejs.config({
|
|||||||
"angular-route": {
|
"angular-route": {
|
||||||
"deps": ["angular"]
|
"deps": ["angular"]
|
||||||
},
|
},
|
||||||
|
"EventEmitter": {
|
||||||
|
"exports": "EventEmitter"
|
||||||
|
},
|
||||||
"moment-duration-format": {
|
"moment-duration-format": {
|
||||||
"deps": ["moment"]
|
"deps": ["moment"]
|
||||||
},
|
},
|
||||||
@ -51,6 +56,9 @@ requirejs.config({
|
|||||||
},
|
},
|
||||||
"zepto": {
|
"zepto": {
|
||||||
"exports": "Zepto"
|
"exports": "Zepto"
|
||||||
|
},
|
||||||
|
"d3": {
|
||||||
|
"exports": "d3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -82,6 +90,7 @@ define([
|
|||||||
'./platform/features/pages/bundle',
|
'./platform/features/pages/bundle',
|
||||||
'./platform/features/plot/bundle',
|
'./platform/features/plot/bundle',
|
||||||
'./platform/features/timeline/bundle',
|
'./platform/features/timeline/bundle',
|
||||||
|
'./platform/features/conductor-v2/bundle',
|
||||||
'./platform/features/table/bundle',
|
'./platform/features/table/bundle',
|
||||||
'./platform/forms/bundle',
|
'./platform/forms/bundle',
|
||||||
'./platform/identity/bundle',
|
'./platform/identity/bundle',
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
</mct-representation>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="holder l-flex-col flex-elem grows l-object-wrapper">
|
<div class="holder l-flex-col flex-elem grows l-object-wrapper l-controls-visible l-time-controller-visible">
|
||||||
<div class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
|
<div class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
|
||||||
<!-- Toolbar and Save/Cancel buttons -->
|
<!-- Toolbar and Save/Cancel buttons -->
|
||||||
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
|
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
|
||||||
@ -59,4 +59,9 @@
|
|||||||
</mct-representation>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- put time conductor in here? -->
|
||||||
|
<mct-representation mct-object="domainObject"
|
||||||
|
key="'time-conductor'"
|
||||||
|
class="abs holder flex-elem flex-fixed l-flex-row l-time-conductor-holder">
|
||||||
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,14 +36,14 @@
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="pane right menu-item-description">
|
<div class="pane right menu-item-description l-flex-col">
|
||||||
<div class="desc-area ui-symbol icon type-icon">
|
<div class="desc-area flex-elem holder ui-symbol icon type-icon">
|
||||||
{{representation.activeMetadata.glyph}}
|
{{representation.activeMetadata.glyph}}
|
||||||
</div>
|
</div>
|
||||||
<div class="desc-area title">
|
<div class="desc-area flex-elem holder title">
|
||||||
{{representation.activeMetadata.name}}
|
{{representation.activeMetadata.name}}
|
||||||
</div>
|
</div>
|
||||||
<div class="desc-area description">
|
<div class="desc-area flex-elem holder description">
|
||||||
{{representation.activeMetadata.description}}
|
{{representation.activeMetadata.description}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,10 +23,12 @@
|
|||||||
define([
|
define([
|
||||||
"./src/FormatProvider",
|
"./src/FormatProvider",
|
||||||
"./src/UTCTimeFormat",
|
"./src/UTCTimeFormat",
|
||||||
|
"./src/DurationFormat",
|
||||||
'legacyRegistry'
|
'legacyRegistry'
|
||||||
], function (
|
], function (
|
||||||
FormatProvider,
|
FormatProvider,
|
||||||
UTCTimeFormat,
|
UTCTimeFormat,
|
||||||
|
DurationFormat,
|
||||||
legacyRegistry
|
legacyRegistry
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -48,6 +50,10 @@ define([
|
|||||||
{
|
{
|
||||||
"key": "utc",
|
"key": "utc",
|
||||||
"implementation": UTCTimeFormat
|
"implementation": UTCTimeFormat
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "duration",
|
||||||
|
"implementation": DurationFormat
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"constants": [
|
"constants": [
|
||||||
|
60
platform/commonUI/formats/src/DurationFormat.js
Normal file
60
platform/commonUI/formats/src/DurationFormat.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define([
|
||||||
|
'moment'
|
||||||
|
], function (
|
||||||
|
moment
|
||||||
|
) {
|
||||||
|
|
||||||
|
var DATE_FORMAT = "HH:mm:ss",
|
||||||
|
DATE_FORMATS = [
|
||||||
|
DATE_FORMAT
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formatter for UTC timestamps. Interprets numeric values as
|
||||||
|
* milliseconds since the start of 1970. Displays only the utc time. Can
|
||||||
|
* be used, with care, for specifying time intervals.
|
||||||
|
*
|
||||||
|
* @implements {Format}
|
||||||
|
* @constructor
|
||||||
|
* @memberof platform/commonUI/formats
|
||||||
|
*/
|
||||||
|
function DurationFormat() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DurationFormat.prototype.format = function (value) {
|
||||||
|
return moment.utc(value).format(DATE_FORMAT);
|
||||||
|
};
|
||||||
|
|
||||||
|
DurationFormat.prototype.parse = function (text) {
|
||||||
|
return moment.duration(text).asMilliseconds();
|
||||||
|
};
|
||||||
|
|
||||||
|
DurationFormat.prototype.validate = function (text) {
|
||||||
|
return moment.utc(text, DATE_FORMATS).isValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
return DurationFormat;
|
||||||
|
});
|
91
platform/commonUI/general/res/sass/_animations.scss
Normal file
91
platform/commonUI/general/res/sass/_animations.scss
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
@include keyframes(rotation) {
|
||||||
|
100% { @include transform(rotate(360deg)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@include keyframes(rotation-centered) {
|
||||||
|
0% { @include transform(translate(-50%, -50%) rotate(0deg)); }
|
||||||
|
100% { @include transform(translate(-50%, -50%) rotate(360deg)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@include keyframes(clock-hands) {
|
||||||
|
0% { @include transform(translate(-50%, -50%) rotate(0deg)); }
|
||||||
|
100% { @include transform(translate(-50%, -50%) rotate(360deg)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@include keyframes(clock-hands-sticky) {
|
||||||
|
0% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(0deg));
|
||||||
|
}
|
||||||
|
7% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(0deg));
|
||||||
|
}
|
||||||
|
8% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(30deg));
|
||||||
|
}
|
||||||
|
15% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(30deg));
|
||||||
|
}
|
||||||
|
16% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(60deg));
|
||||||
|
}
|
||||||
|
24% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(60deg));
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(90deg));
|
||||||
|
}
|
||||||
|
32% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(90deg));
|
||||||
|
}
|
||||||
|
33% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(120deg));
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(120deg));
|
||||||
|
}
|
||||||
|
41% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(150deg));
|
||||||
|
}
|
||||||
|
49% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(150deg));
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(180deg));
|
||||||
|
}
|
||||||
|
57% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(180deg));
|
||||||
|
}
|
||||||
|
58% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(210deg));
|
||||||
|
}
|
||||||
|
65% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(210deg));
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(240deg));
|
||||||
|
}
|
||||||
|
74% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(240deg));
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(270deg));
|
||||||
|
}
|
||||||
|
82% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(270deg));
|
||||||
|
}
|
||||||
|
83% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(300deg));
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(300deg));
|
||||||
|
}
|
||||||
|
91% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(330deg));
|
||||||
|
}
|
||||||
|
99% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(330deg));
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
@include transform(translate(-50%, -50%) rotate(360deg));
|
||||||
|
}
|
||||||
|
}
|
@ -108,6 +108,9 @@
|
|||||||
&.grows {
|
&.grows {
|
||||||
@include flex(1 1 auto);
|
@include flex(1 1 auto);
|
||||||
}
|
}
|
||||||
|
&.contents-align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.flex-container {
|
.flex-container {
|
||||||
// Apply to wrapping elements, mct-includes, etc.
|
// Apply to wrapping elements, mct-includes, etc.
|
||||||
@ -121,17 +124,18 @@
|
|||||||
.l-flex-row {
|
.l-flex-row {
|
||||||
@include flex-direction(row);
|
@include flex-direction(row);
|
||||||
&.flex-elem { @include flex(1 1 auto); }
|
&.flex-elem { @include flex(1 1 auto); }
|
||||||
.flex-elem {
|
> .flex-elem {
|
||||||
height: inherit;
|
height: inherit;
|
||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
&.holder:not(:last-child) { margin-right: $interiorMargin; }
|
||||||
}
|
}
|
||||||
.flex-container { @include flex-direction(row); }
|
.flex-container { @include flex-direction(row); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.l-flex-col {
|
.l-flex-col {
|
||||||
@include flex-direction(column);
|
@include flex-direction(column);
|
||||||
.flex-elem {
|
> .flex-elem {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
&.holder:not(:last-child) { margin-bottom: $interiorMarginLg; }
|
&.holder:not(:last-child) { margin-bottom: $interiorMarginLg; }
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ $uePaneMiniTabW: 10px;
|
|||||||
$uePaneMiniTabCollapsedW: 11px;
|
$uePaneMiniTabCollapsedW: 11px;
|
||||||
$ueEditLeftPaneW: 75%;
|
$ueEditLeftPaneW: 75%;
|
||||||
$treeSearchInputBarH: 25px;
|
$treeSearchInputBarH: 25px;
|
||||||
$ueTimeControlH: (33px, 18px, 20px);
|
$ueTimeControlH: (25px, 6px, 20px);
|
||||||
/*************** Panes */
|
/*************** Panes */
|
||||||
$ueBrowseLeftPaneTreeMinW: 150px;
|
$ueBrowseLeftPaneTreeMinW: 150px;
|
||||||
$ueBrowseLeftPaneTreeMaxW: 35%;
|
$ueBrowseLeftPaneTreeMaxW: 35%;
|
||||||
@ -108,6 +108,7 @@ $bubbleMaxW: 300px;
|
|||||||
$reqSymbolW: 15px;
|
$reqSymbolW: 15px;
|
||||||
$reqSymbolM: $interiorMargin * 2;
|
$reqSymbolM: $interiorMargin * 2;
|
||||||
$reqSymbolFontSize: 0.7em;
|
$reqSymbolFontSize: 0.7em;
|
||||||
|
$inputTextP: 3px 5px;
|
||||||
/*************** Wait Spinner Defaults */
|
/*************** Wait Spinner Defaults */
|
||||||
$waitSpinnerD: 32px;
|
$waitSpinnerD: 32px;
|
||||||
$waitSpinnerTreeD: 20px;
|
$waitSpinnerTreeD: 20px;
|
||||||
|
@ -66,7 +66,7 @@ input, textarea {
|
|||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="search"] {
|
input[type="search"] {
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
padding: 3px 5px;
|
padding: $inputTextP;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3 {
|
h1, h2, h3 {
|
||||||
|
@ -66,8 +66,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.menu .type-icon,
|
.menu .type-icon,
|
||||||
.tree-item .type-icon,
|
.tree-item .type-icon {
|
||||||
.super-menu.menu .type-icon {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@import "effects";
|
@import "effects";
|
||||||
@import "global";
|
@import "global";
|
||||||
|
@import "animations";
|
||||||
@import "archetypes";
|
@import "archetypes";
|
||||||
@import "about";
|
@import "about";
|
||||||
@import "text";
|
@import "text";
|
||||||
@ -40,7 +41,7 @@
|
|||||||
@import "controls/lists";
|
@import "controls/lists";
|
||||||
@import "controls/menus";
|
@import "controls/menus";
|
||||||
@import "controls/messages";
|
@import "controls/messages";
|
||||||
@import "controls/time-controller";
|
@import "controls/time-conductor";
|
||||||
@import "mobile/controls/menus";
|
@import "mobile/controls/menus";
|
||||||
|
|
||||||
/********************************* FORMS */
|
/********************************* FORMS */
|
||||||
|
@ -185,21 +185,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mixin sliderTrack($bg: $scrollbarTrackColorBg) {
|
@mixin sliderTrack($bg: $scrollbarTrackColorBg) {
|
||||||
//$b: 1px solid lighten($bg, 30%);
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@include boxIncised(0.7);
|
@include boxIncised(0.7);
|
||||||
background-color: $bg;
|
background-color: $bg;
|
||||||
//border-bottom: $b;
|
|
||||||
//border-right: $b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin controlGrippy($b, $direction: horizontal, $w: 1px, $style: dotted) {
|
@mixin controlGrippy($b, $direction: horizontal, $w: 1px, $style: dotted) {
|
||||||
//&:before {
|
|
||||||
//@include trans-prop-nice("border-color", 25ms);
|
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
//height: auto;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
@ -305,7 +299,6 @@
|
|||||||
border-radius: $controlCr;
|
border-radius: $controlCr;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: $fg;
|
color: $fg;
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin btnBase($bg: $colorBodyBg, $bgHovColor: none, $fg: $colorBodyFg, $ic: $colorBtnIcon) {
|
@mixin btnBase($bg: $colorBodyBg, $bgHovColor: none, $fg: $colorBodyFg, $ic: $colorBtnIcon) {
|
||||||
|
@ -33,6 +33,7 @@ $pad: $interiorMargin * $baseRatio;
|
|||||||
|
|
||||||
.s-btn {
|
.s-btn {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
padding: 0 $pad;
|
padding: 0 $pad;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
@ -420,6 +420,63 @@ input[type="search"] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin sliderKnob() {
|
||||||
|
$h: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: floor($h/1.75);
|
||||||
|
height: $h;
|
||||||
|
margin-top: 1 + floor($h/2) * -1;
|
||||||
|
@include btnSubtle(pullForward($colorBtnBg, 10%));
|
||||||
|
//border-radius: 50% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin sliderKnobRound() {
|
||||||
|
$h: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: $h;
|
||||||
|
height: $h;
|
||||||
|
margin-top: 1 + floor($h/2) * -1;
|
||||||
|
@include btnSubtle(pullForward($colorBtnBg, 10%));
|
||||||
|
border-radius: 50% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"] {
|
||||||
|
// HTML5 range inputs
|
||||||
|
|
||||||
|
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
|
||||||
|
background: transparent; /* Otherwise white in Chrome */
|
||||||
|
&:focus {
|
||||||
|
outline: none; /* Removes the blue border. */
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thumb
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
@include sliderKnobRound();
|
||||||
|
}
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
border: none;
|
||||||
|
@include sliderKnobRound();
|
||||||
|
}
|
||||||
|
&::-ms-thumb {
|
||||||
|
border: none;
|
||||||
|
@include sliderKnobRound();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track
|
||||||
|
&::-webkit-slider-runnable-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 3px;
|
||||||
|
@include sliderTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-range-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 3px;
|
||||||
|
@include sliderTrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************** DATETIME PICKER */
|
/******************************************************** DATETIME PICKER */
|
||||||
.l-datetime-picker {
|
.l-datetime-picker {
|
||||||
$r1H: 15px;
|
$r1H: 15px;
|
||||||
|
@ -167,7 +167,7 @@
|
|||||||
}
|
}
|
||||||
.pane {
|
.pane {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
&.left {
|
&.menu-items {
|
||||||
border-right: 1px solid pullForward($colorMenuBg, 10%);
|
border-right: 1px solid pullForward($colorMenuBg, 10%);
|
||||||
left: 0;
|
left: 0;
|
||||||
padding-right: $interiorMargin;
|
padding-right: $interiorMargin;
|
||||||
@ -183,38 +183,53 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.right {
|
&.menu-item-description {
|
||||||
left: auto;
|
left: auto;
|
||||||
right: 0;
|
right: 0;
|
||||||
padding: $interiorMargin * 5;
|
padding: $interiorMargin * 5;
|
||||||
width: $prw;
|
width: $prw;
|
||||||
|
.desc-area {
|
||||||
|
&.icon {
|
||||||
|
color: $colorCreateMenuLgIcon;
|
||||||
|
font-size: 8em;
|
||||||
|
margin-bottom: $interiorMargin * 3;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&.title {
|
||||||
|
color: $colorCreateMenuText;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin-bottom: $interiorMargin * 2;
|
||||||
|
}
|
||||||
|
&.description {
|
||||||
|
color: pushBack($colorCreateMenuText, 20%);
|
||||||
|
font-size: 0.8em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.menu-item-description {
|
|
||||||
.desc-area {
|
&.mini {
|
||||||
&.icon {
|
width: 400px;
|
||||||
$h: 150px;
|
height: 300px;
|
||||||
color: $colorCreateMenuLgIcon;
|
.pane {
|
||||||
position: relative;
|
&.menu-items {
|
||||||
font-size: 8em;
|
font-size: 0.8em;
|
||||||
left: 0;
|
}
|
||||||
height: $h;
|
&.menu-item-description {
|
||||||
line-height: $h;
|
padding: $interiorMargin * 3;
|
||||||
margin-bottom: $interiorMargin * 5;
|
.desc-area {
|
||||||
text-align: center;
|
&.icon {
|
||||||
}
|
font-size: 4em;
|
||||||
&.title {
|
}
|
||||||
color: $colorCreateMenuText;
|
&.title {
|
||||||
font-size: 1.2em;
|
font-size: 1em;
|
||||||
margin-bottom: 0.5em;
|
}
|
||||||
}
|
}
|
||||||
&.description {
|
}
|
||||||
color: $colorCreateMenuText;
|
}
|
||||||
font-size: 0.8em;
|
}
|
||||||
line-height: 1.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.context-menu {
|
.context-menu {
|
||||||
font-size: 0.80rem;
|
font-size: 0.80rem;
|
||||||
@ -251,3 +266,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menus-up .menu {
|
||||||
|
bottom: $btnStdH; top: auto;
|
||||||
|
}
|
||||||
|
376
platform/commonUI/general/res/sass/controls/_time-conductor.scss
Normal file
376
platform/commonUI/general/res/sass/controls/_time-conductor.scss
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
@mixin toiLineHovEffects() {
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
background-color: $timeControllerToiLineColorHov;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-time-conductor-holder {
|
||||||
|
$minW: 500px;
|
||||||
|
border-top: 1px solid $colorInteriorBorder;
|
||||||
|
min-width: $minW;
|
||||||
|
padding-top: $interiorMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-conductor-icon {
|
||||||
|
$c: $colorObjHdrIc;
|
||||||
|
$d: 20px;
|
||||||
|
background: $c;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: $d !important;
|
||||||
|
width: $d;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
// Icon shape: brackets
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
background: $colorBodyBg;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
&:before {
|
||||||
|
$in: 7px;
|
||||||
|
left: $in;
|
||||||
|
top: 0;
|
||||||
|
right: $in;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
$in: 4px;
|
||||||
|
left: $in;
|
||||||
|
top: $in;
|
||||||
|
right: $in;
|
||||||
|
bottom: $in;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clock hands
|
||||||
|
div[class*="hand"] {
|
||||||
|
$handW: 2px;
|
||||||
|
$handH: 8px;
|
||||||
|
@include transform(translate(-50%, -50%));
|
||||||
|
@include animation-iteration-count(infinite);
|
||||||
|
@include animation-timing-function(linear);
|
||||||
|
position: absolute;
|
||||||
|
height: $handW;
|
||||||
|
width: $handW;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
z-index: 2;
|
||||||
|
&:before {
|
||||||
|
background-color: $c;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
bottom: -1px;
|
||||||
|
}
|
||||||
|
&.hand-little {
|
||||||
|
z-index: 2;
|
||||||
|
@include animation-duration(12s);
|
||||||
|
&:before {
|
||||||
|
//background: red;
|
||||||
|
height: ceil($handH * 0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.hand-big {
|
||||||
|
z-index: 1;
|
||||||
|
@include animation-duration(1s);
|
||||||
|
&:before {
|
||||||
|
height: $handH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-time-conductor {
|
||||||
|
$knobHOffset: 0px;
|
||||||
|
$rangeValPad: $interiorMargin;
|
||||||
|
$rangeValOffset: $sliderKnobW + $interiorMargin;
|
||||||
|
$r1H: nth($ueTimeControlH, 1);
|
||||||
|
$r2H: nth($ueTimeControlH, 2);
|
||||||
|
$r3H: nth($ueTimeControlH, 3);
|
||||||
|
|
||||||
|
// Glyphs Todo: replace with refactored CSS approach when that is merged into master
|
||||||
|
$glyphIconFixed: '\e604';
|
||||||
|
$glyphIconRealtime: '\43';
|
||||||
|
$glyphIconLatest: '\44';
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> .l-row-elem {
|
||||||
|
// First order row elements
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-selector .s-menu-btn,
|
||||||
|
.time-delta {
|
||||||
|
&:before {
|
||||||
|
@extend .ui-symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-delta {
|
||||||
|
&:before {
|
||||||
|
color: $colorTimeCondKeyBg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-time-conductor-inputs-holder,
|
||||||
|
.l-time-conductor-ticks,
|
||||||
|
.l-time-conductor-zoom-w {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-time-conductor-inputs-holder {
|
||||||
|
$trInputW: 180px;
|
||||||
|
$hmInputW: 60px;
|
||||||
|
$ticksBlockerFadeW: 50px;
|
||||||
|
$iconCalendarW: 16px;
|
||||||
|
$wBgColor: $colorBodyBg;
|
||||||
|
|
||||||
|
height: $r1H;
|
||||||
|
z-index: 1;
|
||||||
|
.l-time-range-w {
|
||||||
|
// Wraps a datetime text input field
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
&.start-w {
|
||||||
|
@include background-image(linear-gradient(270deg, transparent, $wBgColor $ticksBlockerFadeW));
|
||||||
|
padding-right: $ticksBlockerFadeW;
|
||||||
|
}
|
||||||
|
&.end-w {
|
||||||
|
@include background-image(linear-gradient(90deg, transparent, $wBgColor $ticksBlockerFadeW));
|
||||||
|
padding-left: $ticksBlockerFadeW;
|
||||||
|
right: 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
input[type="text"] {
|
||||||
|
@include trans-prop-nice(padding, 250ms);
|
||||||
|
}
|
||||||
|
.time-range-input input {
|
||||||
|
width: $trInputW;
|
||||||
|
}
|
||||||
|
.hrs-min-input input {
|
||||||
|
width: $hmInputW;
|
||||||
|
}
|
||||||
|
.icon-calendar {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-time-conductor-ticks {
|
||||||
|
$c: $colorTick;
|
||||||
|
height: $r1H;
|
||||||
|
mct-conductor-axis {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.l-axis-holder {
|
||||||
|
height: $r1H;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
svg {
|
||||||
|
text-rendering: geometricPrecision;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
> g {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
path {
|
||||||
|
// Line beneath ticks
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
line {
|
||||||
|
// Tick marks
|
||||||
|
stroke: $c;
|
||||||
|
}
|
||||||
|
text {
|
||||||
|
// Tick labels
|
||||||
|
fill: $c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.l-data-visualization {
|
||||||
|
background: $colorTimeCondDataVisBg;
|
||||||
|
height: $r2H;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-time-conductor-controls {
|
||||||
|
align-items: center;
|
||||||
|
margin-top: $interiorMargin;
|
||||||
|
.l-time-conductor-zoom-w {
|
||||||
|
@include justify-content(flex-end);
|
||||||
|
.time-conductor-zoom {
|
||||||
|
height: $r3H;
|
||||||
|
min-width: 100px;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
.time-conductor-zoom-current-range {
|
||||||
|
color: $colorTick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Fixed
|
||||||
|
&.fixed-mode {
|
||||||
|
.time-conductor-icon div[class*="hand"] {
|
||||||
|
&.hand-little {
|
||||||
|
@include transform(rotate(120deg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Realtime, latest modes
|
||||||
|
&.realtime-mode,
|
||||||
|
&.latest-mode {
|
||||||
|
.time-conductor-icon {
|
||||||
|
background: $colorTimeCondKeyBg;
|
||||||
|
div[class*="hand"] {
|
||||||
|
@include animation-name(clock-hands);
|
||||||
|
&:before {
|
||||||
|
background: $colorTimeCondKeyBg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-time-conductor-inputs-holder {
|
||||||
|
.l-time-range-input-w {
|
||||||
|
input[type="text"]:not(.error) {
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
@include nice-input();
|
||||||
|
padding: $inputTextP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.start-date {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.icon-calendar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&.end-date {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.realtime-mode .time-conductor-icon div[class*="hand"] { @include animation-name(clock-hands); }
|
||||||
|
&.latest-mode .time-conductor-icon div[class*="hand"] {
|
||||||
|
@include animation-name(clock-hands-sticky);
|
||||||
|
&.hand-big { @include animation-duration(5s); }
|
||||||
|
&.hand-little { @include animation-duration(60s); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-data-visualization {
|
||||||
|
background: $colorTimeCondDataVisRtBg !important
|
||||||
|
}
|
||||||
|
.mode-selector .s-menu-btn {
|
||||||
|
@include btnSubtle($colorTimeCondKeyBg, pullForward($colorTimeCondKeyBg, $ltGamma), $colorTimeCondKeyFg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.fixed-mode {
|
||||||
|
$i: $glyphIconFixed;
|
||||||
|
.mode-selector .s-menu-btn:before {
|
||||||
|
content: $i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.realtime-mode {
|
||||||
|
$i: $glyphIconRealtime;
|
||||||
|
.time-delta:before {
|
||||||
|
content: $i;
|
||||||
|
}
|
||||||
|
.mode-selector .s-menu-btn:before {
|
||||||
|
content: $i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.latest-mode {
|
||||||
|
$i: $glyphIconLatest;
|
||||||
|
.time-delta:before {
|
||||||
|
content: $i;
|
||||||
|
}
|
||||||
|
.mode-selector .s-menu-btn:before {
|
||||||
|
content: $i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-time-range-val {
|
||||||
|
border-radius: $controlCr;
|
||||||
|
background-color: $colorInputBg;
|
||||||
|
padding: 1px 1px 0 $interiorMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************** MOBILE */
|
||||||
|
|
||||||
|
@include phoneandtablet {
|
||||||
|
.l-time-conductor {
|
||||||
|
min-width: 0;
|
||||||
|
.l-time-range-slider-holder,
|
||||||
|
.l-time-conductor-ticks {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include phone {
|
||||||
|
.l-time-conductor {
|
||||||
|
.l-time-conductor-inputs-holder {
|
||||||
|
&.l-flex-row,
|
||||||
|
.l-flex-row {
|
||||||
|
@include align-items(flex-start);
|
||||||
|
}
|
||||||
|
.l-time-range-inputs-elem {
|
||||||
|
&.type-icon {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.l-time-conductor-inputs-holder {
|
||||||
|
@include flex-direction(column);
|
||||||
|
.l-time-range-input-w:not(:first-child) {
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-top: $interiorMargin;
|
||||||
|
}
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.l-time-range-inputs-elem {
|
||||||
|
&.lbl {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include phonePortrait {
|
||||||
|
.l-time-conductor {
|
||||||
|
.l-time-conductor-inputs-holder {
|
||||||
|
.l-time-conductor-inputs-holder {
|
||||||
|
@include flex(1 1 auto);
|
||||||
|
padding-top: 25px; // Make room for the ever lovin' Time Domain Selector
|
||||||
|
.flex-elem {
|
||||||
|
@include flex(1 1 auto);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.l-time-domain-selector {
|
||||||
|
right: auto;
|
||||||
|
left: 20px;
|
||||||
|
}
|
||||||
|
}
|
@ -1,266 +0,0 @@
|
|||||||
@mixin toiLineHovEffects() {
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
background-color: $timeControllerToiLineColorHov;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.l-time-controller {
|
|
||||||
$minW: 500px;
|
|
||||||
$knobHOffset: 0px;
|
|
||||||
$knobM: ($sliderKnobW + $knobHOffset) * -1;
|
|
||||||
$rangeValPad: $interiorMargin;
|
|
||||||
$rangeValOffset: $sliderKnobW + $interiorMargin;
|
|
||||||
$timeRangeSliderLROffset: 150px + ($sliderKnobW * 2);
|
|
||||||
$r1H: nth($ueTimeControlH,1); // Not currently used
|
|
||||||
$r2H: nth($ueTimeControlH,2);
|
|
||||||
$r3H: nth($ueTimeControlH,3);
|
|
||||||
|
|
||||||
min-width: $minW;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
|
|
||||||
.l-time-range-inputs-holder,
|
|
||||||
.l-time-range-slider-holder,
|
|
||||||
.l-time-range-ticks-holder
|
|
||||||
{
|
|
||||||
box-sizing: border-box;
|
|
||||||
position: relative;
|
|
||||||
&:not(:first-child) {
|
|
||||||
margin-top: $interiorMargin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.l-time-range-slider,
|
|
||||||
.l-time-range-ticks {
|
|
||||||
@include absPosDefault(0, visible);
|
|
||||||
left: $timeRangeSliderLROffset; right: $timeRangeSliderLROffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.l-time-range-inputs-holder {
|
|
||||||
border-top: 1px solid $colorInteriorBorder;
|
|
||||||
padding-top: $interiorMargin;
|
|
||||||
&.l-flex-row,
|
|
||||||
.l-flex-row {
|
|
||||||
@include align-items(center);
|
|
||||||
.flex-elem {
|
|
||||||
height: auto;
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.type-icon {
|
|
||||||
font-size: 120%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.l-time-range-input-w,
|
|
||||||
.l-time-range-inputs-elem {
|
|
||||||
margin-right: $interiorMargin;
|
|
||||||
.lbl {
|
|
||||||
color: $colorPlotLabelFg;
|
|
||||||
}
|
|
||||||
.ui-symbol.icon {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.l-time-range-input-w {
|
|
||||||
// Wraps a datetime text input field
|
|
||||||
position: relative;
|
|
||||||
input[type="text"] {
|
|
||||||
width: 200px;
|
|
||||||
&.picker-icon {
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.icon-calendar {
|
|
||||||
position: absolute;
|
|
||||||
right: 5px;
|
|
||||||
top: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.l-time-range-slider-holder {
|
|
||||||
height: $r2H;
|
|
||||||
.range-holder {
|
|
||||||
box-shadow: none;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
.range {
|
|
||||||
.toi-line {
|
|
||||||
$myC: $timeControllerToiLineColor;
|
|
||||||
$myW: 8px;
|
|
||||||
@include transform(translateX(50%));
|
|
||||||
position: absolute;
|
|
||||||
top: 0; right: 0; bottom: 0px; left: auto;
|
|
||||||
width: $myW;
|
|
||||||
height: auto;
|
|
||||||
z-index: 2;
|
|
||||||
&:before {
|
|
||||||
// Vert line
|
|
||||||
background-color: $myC;
|
|
||||||
position: absolute;
|
|
||||||
content: "";
|
|
||||||
top: 0; right: auto; bottom: -10px; left: floor($myW/2) - 1;
|
|
||||||
width: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:hover .toi-line {
|
|
||||||
@include toiLineHovEffects;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:not(:active) {
|
|
||||||
.knob,
|
|
||||||
.range {
|
|
||||||
@include transition-property(left, right);
|
|
||||||
@include transition-duration(500ms);
|
|
||||||
@include transition-timing-function(ease-in-out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.l-time-range-ticks-holder {
|
|
||||||
height: $r3H;
|
|
||||||
.l-time-range-ticks {
|
|
||||||
border-top: 1px solid $colorTick;
|
|
||||||
.tick {
|
|
||||||
background-color: $colorTick;
|
|
||||||
border:none;
|
|
||||||
height: 5px;
|
|
||||||
width: 1px;
|
|
||||||
margin-left: -1px;
|
|
||||||
position: absolute;
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
.l-time-range-tick-label {
|
|
||||||
@include webkitProp(transform, translateX(-50%));
|
|
||||||
color: $colorPlotLabelFg;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 0.7rem;
|
|
||||||
position: absolute;
|
|
||||||
top: 5px;
|
|
||||||
white-space: nowrap;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.knob {
|
|
||||||
z-index: 2;
|
|
||||||
&:before {
|
|
||||||
$mTB: 2px;
|
|
||||||
$grippyW: 3px;
|
|
||||||
$mLR: ($sliderKnobW - $grippyW)/2;
|
|
||||||
@include bgStripes($c: pullForward($sliderColorKnob, 20%), $a: 1, $bgsize: 4px, $angle: 0deg);
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: $mTB; right: $mLR; bottom: $mTB; left: $mLR;
|
|
||||||
}
|
|
||||||
.range-value {
|
|
||||||
@include trans-prop-nice-fade(.25s);
|
|
||||||
font-size: 0.7rem;
|
|
||||||
position: absolute;
|
|
||||||
height: $r2H;
|
|
||||||
line-height: $r2H;
|
|
||||||
white-space: nowrap;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
.range-value {
|
|
||||||
color: $sliderColorKnobHov;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.knob-l {
|
|
||||||
margin-left: $knobM;
|
|
||||||
.range-value {
|
|
||||||
text-align: right;
|
|
||||||
right: $rangeValOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.knob-r {
|
|
||||||
margin-right: $knobM;
|
|
||||||
.range-value {
|
|
||||||
left: $rangeValOffset;
|
|
||||||
}
|
|
||||||
&:hover + .range-holder .range .toi-line {
|
|
||||||
@include toiLineHovEffects;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.l-time-domain-selector {
|
|
||||||
position: absolute;
|
|
||||||
right: 0px;
|
|
||||||
top: $interiorMargin;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.s-time-range-val {
|
|
||||||
border-radius: $controlCr;
|
|
||||||
background-color: $colorInputBg;
|
|
||||||
padding: 1px 1px 0 $interiorMargin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************** MOBILE */
|
|
||||||
|
|
||||||
@include phoneandtablet {
|
|
||||||
.l-time-controller {
|
|
||||||
min-width: 0;
|
|
||||||
.l-time-range-slider-holder,
|
|
||||||
.l-time-range-ticks-holder {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include phone {
|
|
||||||
.l-time-controller {
|
|
||||||
.l-time-range-inputs-holder {
|
|
||||||
&.l-flex-row,
|
|
||||||
.l-flex-row {
|
|
||||||
@include align-items(flex-start);
|
|
||||||
}
|
|
||||||
.l-time-range-inputs-elem {
|
|
||||||
&.type-icon {
|
|
||||||
margin-top: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.t-inputs-w {
|
|
||||||
@include flex-direction(column);
|
|
||||||
.l-time-range-input-w:not(:first-child) {
|
|
||||||
&:not(:first-child) {
|
|
||||||
margin-top: $interiorMargin;
|
|
||||||
}
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
.l-time-range-inputs-elem {
|
|
||||||
&.lbl { display: none; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include phonePortrait {
|
|
||||||
.l-time-controller {
|
|
||||||
.l-time-range-inputs-holder {
|
|
||||||
.t-inputs-w {
|
|
||||||
@include flex(1 1 auto);
|
|
||||||
padding-top: 25px; // Make room for the ever lovin' Time Domain Selector
|
|
||||||
.flex-elem {
|
|
||||||
@include flex(1 1 auto);
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
input[type="text"] {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.l-time-domain-selector {
|
|
||||||
right: auto;
|
|
||||||
left: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,15 +19,6 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@include keyframes(rotation) {
|
|
||||||
100% { @include transform(rotate(360deg)); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@include keyframes(rotation-centered) {
|
|
||||||
0% { @include transform(translate(-50%, -50%) rotate(0deg)); }
|
|
||||||
100% { @include transform(translate(-50%, -50%) rotate(360deg)); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin spinner($b: 5px, $c: $colorKey) {
|
@mixin spinner($b: 5px, $c: $colorKey) {
|
||||||
@include transform-origin(center);
|
@include transform-origin(center);
|
||||||
@include animation-name(rotation-centered);
|
@include animation-name(rotation-centered);
|
||||||
|
@ -129,6 +129,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.primary-pane {
|
.primary-pane {
|
||||||
|
// Clip element that have min-widths
|
||||||
|
overflow: hidden;
|
||||||
// Need to lift up this pane to ensure that 'collapsed' panes don't block user interactions
|
// Need to lift up this pane to ensure that 'collapsed' panes don't block user interactions
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<input type="text"
|
<input type="text"
|
||||||
ng-model="textValue"
|
ng-model="textValue"
|
||||||
ng-blur="restoreTextValue(); ngBlur()"
|
ng-blur="restoreTextValue(); ngBlur()"
|
||||||
|
ng-mouseup="ngMouseup()"
|
||||||
ng-class="{
|
ng-class="{
|
||||||
error: textInvalid ||
|
error: textInvalid ||
|
||||||
(structure.validate &&
|
(structure.validate &&
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<div ng-controller="TimeRangeController as trCtrl" class="l-flex-col">
|
<div ng-controller="TimeRangeController as trCtrl" class="l-flex-col">
|
||||||
<form class="l-time-range-inputs-holder l-flex-row flex-elem"
|
<form class="l-time-conductor-inputs-holder l-flex-row flex-elem"
|
||||||
ng-submit="trCtrl.updateBoundsFromForm()">
|
ng-submit="trCtrl.updateBoundsFromForm()">
|
||||||
<span class="l-time-range-inputs-elem ui-symbol type-icon flex-elem">C</span>
|
<span class="l-time-range-inputs-elem ui-symbol type-icon flex-elem">C</span>
|
||||||
<span class="l-time-range-inputs-elem t-inputs-w l-flex-row flex-elem">
|
<span class="l-time-range-inputs-elem l-flex-row flex-elem">
|
||||||
<span class="l-time-range-input-w flex-elem">
|
<span class="l-time-range-input-w flex-elem">
|
||||||
<mct-control key="'datetime-field'"
|
<mct-control key="'datetime-field'"
|
||||||
structure="{
|
structure="{
|
||||||
@ -86,7 +86,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="l-time-range-ticks-holder flex-elem">
|
<div class="l-time-conductor-ticks flex-elem">
|
||||||
<div class="l-time-range-ticks">
|
<div class="l-time-range-ticks">
|
||||||
<div
|
<div
|
||||||
ng-repeat="tick in ticks track by $index"
|
ng-repeat="tick in ticks track by $index"
|
||||||
|
@ -52,7 +52,7 @@ $colorGridLines: rgba(#fff, 0.05);
|
|||||||
$colorInvokeMenu: #fff;
|
$colorInvokeMenu: #fff;
|
||||||
$colorObjHdrTxt: $colorBodyFg;
|
$colorObjHdrTxt: $colorBodyFg;
|
||||||
$colorObjHdrIc: pullForward($colorObjHdrTxt, 20%);
|
$colorObjHdrIc: pullForward($colorObjHdrTxt, 20%);
|
||||||
$colorTick: rgba(white, 0.2);
|
$colorTick: pullForward($colorBodyBg, 20%);
|
||||||
|
|
||||||
// Menu colors
|
// Menu colors
|
||||||
$colorMenuBg: pullForward($colorBodyBg, 23%);
|
$colorMenuBg: pullForward($colorBodyBg, 23%);
|
||||||
@ -207,4 +207,10 @@ $colorAboutLink: #84b3ff;
|
|||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
$colorLoadingFg: $colorAlt1;
|
$colorLoadingFg: $colorAlt1;
|
||||||
$colorLoadingBg: rgba($colorBodyFg, 0.2);
|
$colorLoadingBg: rgba($colorBodyFg, 0.2);
|
||||||
|
|
||||||
|
// Time Conductor
|
||||||
|
$colorTimeCondKeyBg: #4e70dc;
|
||||||
|
$colorTimeCondKeyFg: #fff;
|
||||||
|
$colorTimeCondDataVisBg: pullForward($colorBodyBg, 10%);
|
||||||
|
$colorTimeCondDataVisRtBg: pushBack($colorTimeCondKeyBg, 10%);
|
@ -52,7 +52,7 @@ $colorGridLines: rgba(#000, 0.05);
|
|||||||
$colorInvokeMenu: #fff;
|
$colorInvokeMenu: #fff;
|
||||||
$colorObjHdrTxt: $colorBodyFg;
|
$colorObjHdrTxt: $colorBodyFg;
|
||||||
$colorObjHdrIc: pushBack($colorObjHdrTxt, 30%);
|
$colorObjHdrIc: pushBack($colorObjHdrTxt, 30%);
|
||||||
$colorTick: rgba(black, 0.2);
|
$colorTick: pullForward($colorBodyBg, 30%);
|
||||||
|
|
||||||
// Menu colors
|
// Menu colors
|
||||||
$colorMenuBg: pushBack($colorBodyBg, 10%);
|
$colorMenuBg: pushBack($colorBodyBg, 10%);
|
||||||
@ -185,6 +185,7 @@ $scrollbarThumbColorOverlayHov: $scrollbarThumbColorHov;
|
|||||||
// Splitter
|
// Splitter
|
||||||
$splitterD: 16px; // splitterD and $splitterHandleD should both be odd, or even
|
$splitterD: 16px; // splitterD and $splitterHandleD should both be odd, or even
|
||||||
$splitterHandleD: 2px;
|
$splitterHandleD: 2px;
|
||||||
|
$splitterDSm: 16px; // Smaller splitter, used inside elements like a Timeline view
|
||||||
$colorSplitterBg: pullForward($colorBodyBg, 10%);
|
$colorSplitterBg: pullForward($colorBodyBg, 10%);
|
||||||
$splitterShdw: none;
|
$splitterShdw: none;
|
||||||
$splitterEndCr: none;
|
$splitterEndCr: none;
|
||||||
@ -207,3 +208,9 @@ $colorAboutLink: #84b3ff;
|
|||||||
// Loading
|
// Loading
|
||||||
$colorLoadingFg: $colorAlt1;
|
$colorLoadingFg: $colorAlt1;
|
||||||
$colorLoadingBg: rgba($colorLoadingFg, 0.1);
|
$colorLoadingBg: rgba($colorLoadingFg, 0.1);
|
||||||
|
|
||||||
|
// Time Conductor
|
||||||
|
$colorTimeCondKeyBg: #6178dc;
|
||||||
|
$colorTimeCondKeyFg: #fff;
|
||||||
|
$colorTimeCondDataVisBg: pullForward($colorBodyBg, 10%);
|
||||||
|
$colorTimeCondDataVisRtBg: pushBack($colorTimeCondKeyBg, 30%);
|
||||||
|
85
platform/features/conductor-v2/bundle.js
Normal file
85
platform/features/conductor-v2/bundle.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define([
|
||||||
|
"./src/TimeConductor",
|
||||||
|
"./src/TimeConductorController",
|
||||||
|
"./src/MCTConductorAxis",
|
||||||
|
"text!./res/templates/time-conductor.html",
|
||||||
|
"text!./res/templates/mode-selector/mode-selector.html",
|
||||||
|
"text!./res/templates/mode-selector/mode-menu.html",
|
||||||
|
'legacyRegistry'
|
||||||
|
], function (
|
||||||
|
TimeConductor,
|
||||||
|
TimeConductorController,
|
||||||
|
MCTConductorAxis,
|
||||||
|
timeConductorTemplate,
|
||||||
|
modeSelectorTemplate,
|
||||||
|
modeMenuTemplate,
|
||||||
|
legacyRegistry
|
||||||
|
) {
|
||||||
|
|
||||||
|
legacyRegistry.register("platform/features/conductor-v2", {
|
||||||
|
"extensions": {
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"key": "timeConductor",
|
||||||
|
"implementation": TimeConductor
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"controllers": [
|
||||||
|
{
|
||||||
|
"key": "TimeConductorController",
|
||||||
|
"implementation": TimeConductorController,
|
||||||
|
"depends": [
|
||||||
|
"$scope",
|
||||||
|
"$timeout",
|
||||||
|
"timeConductor"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
{
|
||||||
|
"key": "mctConductorAxis",
|
||||||
|
"implementation": MCTConductorAxis,
|
||||||
|
"depends": [
|
||||||
|
"timeConductor"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"representations": [
|
||||||
|
{
|
||||||
|
"key": "time-conductor",
|
||||||
|
"template": timeConductorTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "mode-selector",
|
||||||
|
"template": modeSelectorTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "mode-menu",
|
||||||
|
"template": modeMenuTemplate
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,49 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<div class="contents">
|
||||||
|
<div class="pane left menu-items">
|
||||||
|
<ul>
|
||||||
|
<li ng-repeat="(selected, option) in ngModel.options"
|
||||||
|
ng-click="ngModel.selected=selected">
|
||||||
|
<a
|
||||||
|
ng-mouseover="representation.activeMetadata = option"
|
||||||
|
ng-mouseleave="representation.activeMetadata = undefined">
|
||||||
|
<span class="ui-symbol icon type-icon">
|
||||||
|
{{option.glyph}}
|
||||||
|
</span>
|
||||||
|
{{option.name}}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="pane right menu-item-description">
|
||||||
|
<div class="desc-area ui-symbol icon type-icon">
|
||||||
|
{{representation.activeMetadata.glyph}}
|
||||||
|
</div>
|
||||||
|
<div class="desc-area title">
|
||||||
|
{{representation.activeMetadata.name}}
|
||||||
|
</div>
|
||||||
|
<div class="desc-area description">
|
||||||
|
{{representation.activeMetadata.description}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
<!--
|
||||||
|
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 ng-controller="ClickAwayController as modeController">
|
||||||
|
<div class="s-menu-btn"
|
||||||
|
ng-click="modeController.toggle()">
|
||||||
|
<span class="title-label">{{ngModel.options[ngModel.selected].label}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="menu super-menu mini mode-selector-menu"
|
||||||
|
ng-show="modeController.isActive()">
|
||||||
|
<mct-representation mct-object="domainObject"
|
||||||
|
key="'mode-menu'"
|
||||||
|
ng-model="ngModel">
|
||||||
|
</mct-representation>
|
||||||
|
</div>
|
||||||
|
</span>
|
115
platform/features/conductor-v2/res/templates/time-conductor.html
Normal file
115
platform/features/conductor-v2/res/templates/time-conductor.html
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<!-- Parent holder for time conductor. follow-mode | fixed-mode -->
|
||||||
|
<div ng-controller="TimeConductorController as tcController"
|
||||||
|
class="holder grows flex-elem l-flex-row l-time-conductor {{modeModel.selected}}-mode">
|
||||||
|
|
||||||
|
<div class="flex-elem holder time-conductor-icon">
|
||||||
|
<div class="hand-little"></div>
|
||||||
|
<div class="hand-big"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-elem holder grows l-flex-col l-time-conductor-inner">
|
||||||
|
<!-- Holds inputs and ticks -->
|
||||||
|
<div class="l-time-conductor-ticks l-row-elem l-flex-row flex-elem no-margin">
|
||||||
|
<form class="abs l-time-conductor-inputs-holder"
|
||||||
|
ng-submit="tcController.updateBoundsFromForm(formModel)">
|
||||||
|
<span class="l-time-range-w start-w">
|
||||||
|
<span class="l-time-range-input-w start-date">
|
||||||
|
<mct-control key="'datetime-field'"
|
||||||
|
structure="{
|
||||||
|
format: 'utc',
|
||||||
|
validate: tcController.validateStart
|
||||||
|
}"
|
||||||
|
ng-model="formModel"
|
||||||
|
ng-mouseup="tcController.changing['start'] = true"
|
||||||
|
ng-blur="tcController.changing['start'] = false; tcController.updateBoundsFromForm(formModel)"
|
||||||
|
field="'start'"
|
||||||
|
class="time-range-input">
|
||||||
|
</mct-control>
|
||||||
|
</span>
|
||||||
|
<span class="l-time-range-input-w time-delta start-delta"
|
||||||
|
ng-class="{'hide':(modeModel.selected === 'fixed')}">
|
||||||
|
-
|
||||||
|
<mct-control key="'datetime-field'"
|
||||||
|
structure="{
|
||||||
|
format: 'duration',
|
||||||
|
validate: tcController.validateStartDelta
|
||||||
|
}"
|
||||||
|
ng-model="formModel"
|
||||||
|
ng-mouseup="tcController.changing['startDelta'] = true"
|
||||||
|
ng-blur="tcController.changing['startDelta'] = false; tcController.updateDeltasFromForm(formModel)"
|
||||||
|
field="'startDelta'"
|
||||||
|
class="hrs-min-input">
|
||||||
|
</mct-control>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
|
||||||
|
<span class="l-time-range-w end-w">
|
||||||
|
<span class="l-time-range-input-w time-delta end-delta"
|
||||||
|
ng-class="{'hide':(modeModel.selected === 'fixed')}">
|
||||||
|
+
|
||||||
|
<mct-control key="'datetime-field'"
|
||||||
|
structure="{
|
||||||
|
format: 'duration',
|
||||||
|
validate: tcController.validateEndDelta
|
||||||
|
}"
|
||||||
|
ng-model="formModel"
|
||||||
|
ng-mouseup="tcController.changing['endDelta'] = true"
|
||||||
|
ng-blur="tcController.changing['endDelta'] = false; tcController.updateDeltasFromForm(formModel)"
|
||||||
|
field="'endDelta'"
|
||||||
|
class="hrs-min-input">
|
||||||
|
</mct-control>
|
||||||
|
</span>
|
||||||
|
<span class="l-time-range-input-w end-date"
|
||||||
|
ng-controller="ToggleController as t2">
|
||||||
|
<mct-control key="'datetime-field'"
|
||||||
|
structure="{
|
||||||
|
format: 'utc',
|
||||||
|
validate: tcController.validateEnd
|
||||||
|
}"
|
||||||
|
ng-model="formModel"
|
||||||
|
ng-mouseup="tcController.changing['end'] = true"
|
||||||
|
ng-blur="tcController.changing['end'] = false; tcController.updateBoundsFromForm(formModel)"
|
||||||
|
field="'end'"
|
||||||
|
class="time-range-input">
|
||||||
|
</mct-control>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<input type="submit" class="hidden">
|
||||||
|
</form>
|
||||||
|
<mct-conductor-axis></mct-conductor-axis>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Holds data availability, time of interest -->
|
||||||
|
<div class="l-data-visualization l-row-elem l-flex-row flex-elem"></div>
|
||||||
|
|
||||||
|
<!-- Holds time system and session selectors, and zoom control -->
|
||||||
|
<div class="l-time-conductor-controls l-row-elem l-flex-row flex-elem">
|
||||||
|
<mct-representation
|
||||||
|
key="'mode-selector'"
|
||||||
|
mct-object="domainObject"
|
||||||
|
ng-model="modeModel"
|
||||||
|
class="holder flex-elem menus-up mode-selector">
|
||||||
|
</mct-representation>
|
||||||
|
<mct-control
|
||||||
|
key="'menu-button'"
|
||||||
|
class="holder flex-elem menus-up time-system"
|
||||||
|
ng-model="conductorModel.timeSystem"
|
||||||
|
structure="{
|
||||||
|
text: 'UTC',
|
||||||
|
options: [
|
||||||
|
{name: 'UTC', key:'utc', glyph:'\u0043'},
|
||||||
|
{name: 'SCET', key:'scet', glyph:'\u0043'},
|
||||||
|
{name: 'SCLK', key:'sclk', glyph:'\u0043'}
|
||||||
|
]}">
|
||||||
|
</mct-control>
|
||||||
|
<!-- Zoom control -->
|
||||||
|
<div class="l-time-conductor-zoom-w grows flex-elem l-flex-row">
|
||||||
|
<span class="time-conductor-zoom-current-range flex-elem flex-fixed holder">Mars Minutes</span>
|
||||||
|
<input class="time-conductor-zoom flex-elem" type="range" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
100
platform/features/conductor-v2/src/MctConductorAxis.js
Normal file
100
platform/features/conductor-v2/src/MctConductorAxis.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
"zepto",
|
||||||
|
"d3"
|
||||||
|
],
|
||||||
|
function ($, d3) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mct-control will dynamically include the control
|
||||||
|
* for a form element based on a symbolic key. Individual
|
||||||
|
* controls are defined under the extension category
|
||||||
|
* `controls`; this allows plug-ins to introduce new form
|
||||||
|
* control types while still making use of the form
|
||||||
|
* generator to ensure an overall consistent form style.
|
||||||
|
* @constructor
|
||||||
|
* @memberof platform/forms
|
||||||
|
*/
|
||||||
|
function MCTConductorAxis(conductor) {
|
||||||
|
|
||||||
|
function link(scope, element, attrs, ngModelController) {
|
||||||
|
var target = element[0].firstChild,
|
||||||
|
height = target.offsetHeight,
|
||||||
|
padding = 1;
|
||||||
|
|
||||||
|
var vis = d3.select(target)
|
||||||
|
.append('svg:svg')
|
||||||
|
.attr('width', '100%')
|
||||||
|
.attr('height', height);
|
||||||
|
var xScale = d3.scaleUtc();
|
||||||
|
var xAxis = d3.axisTop();
|
||||||
|
// draw x axis with labels and move to the bottom of the chart area
|
||||||
|
var axisElement = vis.append("g")
|
||||||
|
.attr("transform", "translate(0," + (height - padding) + ")");
|
||||||
|
|
||||||
|
function setScale(start, end) {
|
||||||
|
var width = target.offsetWidth;
|
||||||
|
xScale.domain([new Date(start), new Date(end)])
|
||||||
|
.range([padding, width - padding * 2]);
|
||||||
|
xAxis.scale(xScale);
|
||||||
|
axisElement.call(xAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.resize = function () {
|
||||||
|
setScale(conductor.bounds().start, conductor.bounds().end);
|
||||||
|
};
|
||||||
|
|
||||||
|
conductor.on('bounds', function (bounds) {
|
||||||
|
setScale(bounds.start, bounds.end);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Set initial scale.
|
||||||
|
setScale(conductor.bounds().start, conductor.bounds().end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// Only show at the element level
|
||||||
|
restrict: "E",
|
||||||
|
|
||||||
|
template: "<div class=\"l-axis-holder\" mct-resize=\"resize()\"></div>",
|
||||||
|
|
||||||
|
// ngOptions is terminal, so we need to be higher priority
|
||||||
|
priority: 1000,
|
||||||
|
|
||||||
|
// Link function
|
||||||
|
link: link,
|
||||||
|
|
||||||
|
// Pass through Angular's normal input field attributes
|
||||||
|
scope: {
|
||||||
|
// Used to choose which form control to use
|
||||||
|
start: "=",
|
||||||
|
end: "="
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return MCTConductorAxis;
|
||||||
|
}
|
||||||
|
);
|
183
platform/features/conductor-v2/src/TimeConductor.js
Normal file
183
platform/features/conductor-v2/src/TimeConductor.js
Normal file
@ -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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define(['EventEmitter'], function (EventEmitter) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public API for setting and querying time conductor state. The
|
||||||
|
* time conductor is the means by which the temporal bounds of a view
|
||||||
|
* are controlled. Time-sensitive views will typically respond to
|
||||||
|
* changes to bounds or other properties of the time conductor and
|
||||||
|
* update the data displayed based on the time conductor state.
|
||||||
|
*
|
||||||
|
* The TimeConductor extends the EventEmitter class. A number of events are
|
||||||
|
* fired when properties of the time conductor change, which are
|
||||||
|
* documented below.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function TimeConductor() {
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
//The Time System
|
||||||
|
this.system = undefined;
|
||||||
|
//The Time Of Interest
|
||||||
|
this.toi = undefined;
|
||||||
|
|
||||||
|
this.boundsVal = {
|
||||||
|
start: undefined,
|
||||||
|
end: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
//Default to fixed mode
|
||||||
|
this.followMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeConductor.prototype = Object.create(EventEmitter.prototype);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the given bounds. This can be used for pre-validation of
|
||||||
|
* bounds, for example by views validating user inputs.
|
||||||
|
* @param bounds The start and end time of the conductor.
|
||||||
|
* @returns {string | true} A validation error, or true if valid
|
||||||
|
*/
|
||||||
|
TimeConductor.prototype.validateBounds = function (bounds) {
|
||||||
|
if ((bounds.start === undefined) ||
|
||||||
|
(bounds.end === undefined) ||
|
||||||
|
isNaN(bounds.start) ||
|
||||||
|
isNaN(bounds.end)
|
||||||
|
) {
|
||||||
|
return "Start and end must be specified as integer values";
|
||||||
|
} else if (bounds.start > bounds.end) {
|
||||||
|
return "Specified start date exceeds end bound";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
function throwOnError(validationResult) {
|
||||||
|
if (validationResult !== true) {
|
||||||
|
throw new Error(validationResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or set the follow mode of the time conductor. In follow mode the
|
||||||
|
* time conductor ticks, regularly updating the bounds from a timing
|
||||||
|
* source appropriate to the selected time system and mode of the time
|
||||||
|
* conductor.
|
||||||
|
* @fires TimeConductor#follow
|
||||||
|
* @param {boolean} followMode
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
TimeConductor.prototype.follow = function (followMode) {
|
||||||
|
if (arguments.length > 0) {
|
||||||
|
this.followMode = followMode;
|
||||||
|
/**
|
||||||
|
* @event TimeConductor#follow The TimeConductor has toggled
|
||||||
|
* into or out of follow mode.
|
||||||
|
* @property {boolean} followMode true if follow mode is
|
||||||
|
* enabled, otherwise false.
|
||||||
|
*/
|
||||||
|
this.emit('follow', this.followMode);
|
||||||
|
}
|
||||||
|
return this.followMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} TimeConductorBounds
|
||||||
|
* @property {number} start The start time displayed by the time conductor in ms since epoch. Epoch determined by current time system
|
||||||
|
* @property {number} end The end time displayed by the time conductor in ms since epoch.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Get or set the start and end time of the time conductor. Basic validation
|
||||||
|
* of bounds is performed.
|
||||||
|
*
|
||||||
|
* @param {TimeConductorBounds} newBounds
|
||||||
|
* @throws {Error} Validation error
|
||||||
|
* @fires TimeConductor#bounds
|
||||||
|
* @returns {TimeConductorBounds}
|
||||||
|
*/
|
||||||
|
TimeConductor.prototype.bounds = function (newBounds) {
|
||||||
|
if (arguments.length > 0) {
|
||||||
|
throwOnError(this.validateBounds(newBounds));
|
||||||
|
this.boundsVal = newBounds;
|
||||||
|
/**
|
||||||
|
* @event TimeConductor#bounds The start time, end time, or
|
||||||
|
* both have been updated
|
||||||
|
* @property {TimeConductorBounds} bounds
|
||||||
|
*/
|
||||||
|
this.emit('bounds', this.boundsVal);
|
||||||
|
}
|
||||||
|
return this.boundsVal;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or set the time system of the TimeConductor. Time systems determine
|
||||||
|
* units, epoch, and other aspects of time representation. When changing
|
||||||
|
* the time system in use, new valid bounds must also be provided.
|
||||||
|
* @param {TimeSystem} newTimeSystem
|
||||||
|
* @param {TimeConductorBounds} bounds
|
||||||
|
* @fires TimeConductor#timeSystem
|
||||||
|
* @returns {TimeSystem} The currently applied time system
|
||||||
|
*/
|
||||||
|
TimeConductor.prototype.timeSystem = function (newTimeSystem, bounds) {
|
||||||
|
if (arguments.length >= 2) {
|
||||||
|
this.system = newTimeSystem;
|
||||||
|
/**
|
||||||
|
* @event TimeConductor#timeSystem The time system used by the time
|
||||||
|
* conductor has changed. A change in Time System will always be
|
||||||
|
* followed by a bounds event specifying new query bounds
|
||||||
|
* @property {TimeSystem} The value of the currently applied
|
||||||
|
* Time System
|
||||||
|
* */
|
||||||
|
this.emit('timeSystem', this.system);
|
||||||
|
// Do something with bounds here. Try and convert between
|
||||||
|
// time systems? Or just set defaults when time system changes?
|
||||||
|
// eg.
|
||||||
|
this.bounds(bounds);
|
||||||
|
} else if (arguments.length === 1) {
|
||||||
|
throw new Error('Must set bounds when changing time system');
|
||||||
|
}
|
||||||
|
return this.system;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or set the Time of Interest. The Time of Interest is the temporal
|
||||||
|
* focus of the current view. It can be manipulated by the user from the
|
||||||
|
* time conductor or from other views.
|
||||||
|
* @fires TimeConductor#timeOfInterest
|
||||||
|
* @param newTOI
|
||||||
|
* @returns {number} the current time of interest
|
||||||
|
*/
|
||||||
|
TimeConductor.prototype.timeOfInterest = function (newTOI) {
|
||||||
|
if (arguments.length > 0) {
|
||||||
|
this.toi = newTOI;
|
||||||
|
/**
|
||||||
|
* @event TimeConductor#timeOfInterest The Time of Interest has moved.
|
||||||
|
* @property {number} Current time of interest
|
||||||
|
*/
|
||||||
|
this.emit('timeOfInterest', this.toi);
|
||||||
|
}
|
||||||
|
return this.toi;
|
||||||
|
};
|
||||||
|
|
||||||
|
return TimeConductor;
|
||||||
|
});
|
205
platform/features/conductor-v2/src/TimeConductorController.js
Normal file
205
platform/features/conductor-v2/src/TimeConductorController.js
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
|
||||||
|
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
||||||
|
|
||||||
|
function TimeConductorController($scope, $timeout, conductor) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.$timeout = $timeout;
|
||||||
|
this.conductor = conductor;
|
||||||
|
this.startDelta = FIFTEEN_MINUTES;
|
||||||
|
this.endDelta = 0;
|
||||||
|
|
||||||
|
this.changing = {
|
||||||
|
'start': false,
|
||||||
|
'end': false
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.formModel = {
|
||||||
|
startDelta: this.startDelta,
|
||||||
|
endDelta: this.endDelta
|
||||||
|
};
|
||||||
|
|
||||||
|
conductor.on('bounds', function (bounds) {
|
||||||
|
if (!self.changing['start']) {
|
||||||
|
$scope.formModel.start = bounds.start;
|
||||||
|
}
|
||||||
|
if (!self.changing['end']) {
|
||||||
|
$scope.formModel.end = bounds.end;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
conductor.on('follow', function (follow){
|
||||||
|
$scope.followMode = follow;
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(TimeConductorController.prototype).filter(function (key) {
|
||||||
|
return typeof TimeConductorController.prototype[key] === 'function';
|
||||||
|
}).forEach(function (key) {
|
||||||
|
self[key] = self[key].bind(self);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$watch('modeModel.selected', this.switchMode);
|
||||||
|
|
||||||
|
$scope.modeModel = {
|
||||||
|
selected: 'fixed',
|
||||||
|
options: {
|
||||||
|
'fixed': {
|
||||||
|
glyph: '\ue604',
|
||||||
|
label: 'Fixed',
|
||||||
|
name: 'Fixed Timespan Mode',
|
||||||
|
description: 'Query and explore data that falls between two fixed datetimes.'
|
||||||
|
},
|
||||||
|
'realtime': {
|
||||||
|
glyph: '\u0043',
|
||||||
|
label: 'Real-time',
|
||||||
|
name: 'Real-time Mode',
|
||||||
|
description: 'Monitor real-time streaming data as it comes in. The Time Conductor and displays will automatically advance themselves based on a UTC clock.'
|
||||||
|
},
|
||||||
|
'latest': {
|
||||||
|
glyph: '\u0044',
|
||||||
|
label: 'LAD',
|
||||||
|
name: 'LAD Mode',
|
||||||
|
description: 'Latest Available Data mode monitors real-time streaming data as it comes in. The Time Conductor and displays will only advance when data becomes available.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function() {
|
||||||
|
if (self.mode) {
|
||||||
|
self.mode();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeConductorController.prototype.initialize = function () {
|
||||||
|
var now = Math.ceil(Date.now() / 1000) * 1000;
|
||||||
|
//Set the time conductor to some default
|
||||||
|
this.conductor.bounds({start: now - FIFTEEN_MINUTES, end: now});
|
||||||
|
|
||||||
|
this.$scope.modeModel.selected = 'fixed';
|
||||||
|
this.conductor.follow(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.validateStart = function (start) {
|
||||||
|
var bounds = this.conductor.bounds();
|
||||||
|
return this.conductor.validateBounds({start: start, end: bounds.end}) === true;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.validateEnd = function (end) {
|
||||||
|
var bounds = this.conductor.bounds();
|
||||||
|
return this.conductor.validateBounds({start: bounds.start, end: end}) === true;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.updateBoundsFromForm = function (formModel) {
|
||||||
|
var newBounds = {start: formModel.start, end: formModel.end};
|
||||||
|
|
||||||
|
if (this.conductor.validateBounds(newBounds) === true) {
|
||||||
|
this.conductor.bounds(newBounds);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.validateStartDelta = function (startDelta) {
|
||||||
|
return startDelta > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.validateEndDelta = function (endDelta) {
|
||||||
|
return endDelta >= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.validateDeltas = function (formModel) {
|
||||||
|
// Validate that start Delta is some non-zero value, and that end
|
||||||
|
// delta is zero or positive (ie. 'now' or some time in the future).
|
||||||
|
return this.validateStartDelta(formModel.startDelta) && this.validateEndDelta(formModel.endDelta);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.updateDeltasFromForm = function (formModel) {
|
||||||
|
|
||||||
|
if (this.validateDeltas(formModel)) {
|
||||||
|
//Calculate the previous 'true' end value (without delta)
|
||||||
|
var oldEnd = this.conductor.bounds().end - this.endDelta || 0;
|
||||||
|
|
||||||
|
this.startDelta = formModel.startDelta;
|
||||||
|
this.endDelta = formModel.endDelta;
|
||||||
|
|
||||||
|
var newBounds = {
|
||||||
|
start: oldEnd - this.startDelta,
|
||||||
|
end: oldEnd + this.endDelta
|
||||||
|
};
|
||||||
|
|
||||||
|
this.conductor.bounds(newBounds);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.prototype.switchMode = function (newMode) {
|
||||||
|
if (this.mode) {
|
||||||
|
this.mode();
|
||||||
|
}
|
||||||
|
this.mode = TimeConductorController.modes[newMode].call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorController.modes = {
|
||||||
|
'fixed': function () {
|
||||||
|
this.conductor.follow(false);
|
||||||
|
},
|
||||||
|
'realtime': function () {
|
||||||
|
var tickInterval = 1000;
|
||||||
|
var conductor = this.conductor;
|
||||||
|
var $timeout = this.$timeout;
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
conductor.follow(true);
|
||||||
|
setBoundsToNow(self.startDelta, self.endDelta);
|
||||||
|
|
||||||
|
var timeoutPromise = $timeout(tick, tickInterval);
|
||||||
|
|
||||||
|
function setBoundsToNow(startDelta, endDelta) {
|
||||||
|
var now = Math.ceil(Date.now() / 1000) * 1000;
|
||||||
|
conductor.bounds({start: now - startDelta, end: now + endDelta});
|
||||||
|
}
|
||||||
|
|
||||||
|
function tick() {
|
||||||
|
setBoundsToNow(self.startDelta, self.endDelta);
|
||||||
|
timeoutPromise = $timeout(tick, tickInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
return function destroy() {
|
||||||
|
$timeout.cancel(timeoutPromise);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'latest': function () {
|
||||||
|
//Don't know what to do here yet...
|
||||||
|
this.conductor.follow(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return TimeConductorController;
|
||||||
|
}
|
||||||
|
);
|
110
platform/features/conductor-v2/src/TimeConductorSpec.js
Normal file
110
platform/features/conductor-v2/src/TimeConductorSpec.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define(['./TimeConductor'], function (TimeConductor) {
|
||||||
|
describe("The Time Conductor", function () {
|
||||||
|
var tc,
|
||||||
|
timeSystem,
|
||||||
|
bounds,
|
||||||
|
eventListener,
|
||||||
|
toi,
|
||||||
|
follow;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
tc = new TimeConductor();
|
||||||
|
timeSystem = {};
|
||||||
|
bounds = {start: 0, end: 0};
|
||||||
|
eventListener = jasmine.createSpy("eventListener");
|
||||||
|
toi = 111;
|
||||||
|
follow = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Supports setting and querying of time of interest and and follow mode", function () {
|
||||||
|
expect(tc.timeOfInterest()).not.toBe(toi);
|
||||||
|
tc.timeOfInterest(toi);
|
||||||
|
expect(tc.timeOfInterest()).toBe(toi);
|
||||||
|
|
||||||
|
expect(tc.follow()).not.toBe(follow);
|
||||||
|
tc.follow(follow);
|
||||||
|
expect(tc.follow()).toBe(follow);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Allows setting of valid bounds", function () {
|
||||||
|
bounds = {start: 0, end: 1};
|
||||||
|
expect(tc.bounds()).not.toBe(bounds);
|
||||||
|
expect(tc.bounds.bind(tc, bounds)).not.toThrow();
|
||||||
|
expect(tc.bounds()).toBe(bounds);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Disallows setting of invalid bounds", function () {
|
||||||
|
bounds = {start: 1, end: 0};
|
||||||
|
expect(tc.bounds()).not.toBe(bounds);
|
||||||
|
expect(tc.bounds.bind(tc, bounds)).toThrow();
|
||||||
|
expect(tc.bounds()).not.toBe(bounds);
|
||||||
|
|
||||||
|
bounds = {start: 1};
|
||||||
|
expect(tc.bounds()).not.toBe(bounds);
|
||||||
|
expect(tc.bounds.bind(tc, bounds)).toThrow();
|
||||||
|
expect(tc.bounds()).not.toBe(bounds);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Allows setting of time system with bounds", function () {
|
||||||
|
expect(tc.timeSystem()).not.toBe(timeSystem);
|
||||||
|
expect(tc.timeSystem.bind(tc, timeSystem, bounds)).not.toThrow();
|
||||||
|
expect(tc.timeSystem()).toBe(timeSystem);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Disallows setting of time system without bounds", function () {
|
||||||
|
expect(tc.timeSystem()).not.toBe(timeSystem);
|
||||||
|
expect(tc.timeSystem.bind(tc, timeSystem)).toThrow();
|
||||||
|
expect(tc.timeSystem()).not.toBe(timeSystem);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Emits an event when time system changes", function () {
|
||||||
|
expect(eventListener).not.toHaveBeenCalled();
|
||||||
|
tc.on("timeSystem", eventListener);
|
||||||
|
tc.timeSystem(timeSystem, bounds);
|
||||||
|
expect(eventListener).toHaveBeenCalledWith(timeSystem);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Emits an event when time of interest changes", function () {
|
||||||
|
expect(eventListener).not.toHaveBeenCalled();
|
||||||
|
tc.on("timeOfInterest", eventListener);
|
||||||
|
tc.timeOfInterest(toi);
|
||||||
|
expect(eventListener).toHaveBeenCalledWith(toi);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Emits an event when bounds change", function () {
|
||||||
|
expect(eventListener).not.toHaveBeenCalled();
|
||||||
|
tc.on("bounds", eventListener);
|
||||||
|
tc.bounds(bounds);
|
||||||
|
expect(eventListener).toHaveBeenCalledWith(bounds);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Emits an event when follow mode changes", function () {
|
||||||
|
expect(eventListener).not.toHaveBeenCalled();
|
||||||
|
tc.on("follow", eventListener);
|
||||||
|
tc.follow(follow);
|
||||||
|
expect(eventListener).toHaveBeenCalledWith(follow);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -71,6 +71,9 @@ define(
|
|||||||
// Allow controls to trigger blur-like events
|
// Allow controls to trigger blur-like events
|
||||||
ngBlur: "&",
|
ngBlur: "&",
|
||||||
|
|
||||||
|
// Allow controls to trigger blur-like events
|
||||||
|
ngMouseup: "&",
|
||||||
|
|
||||||
// The state of the form value itself
|
// The state of the form value itself
|
||||||
ngModel: "=",
|
ngModel: "=",
|
||||||
|
|
||||||
|
@ -48,13 +48,14 @@ requirejs.config({
|
|||||||
"angular-route": "bower_components/angular-route/angular-route.min",
|
"angular-route": "bower_components/angular-route/angular-route.min",
|
||||||
"csv": "bower_components/comma-separated-values/csv.min",
|
"csv": "bower_components/comma-separated-values/csv.min",
|
||||||
"es6-promise": "bower_components/es6-promise/promise.min",
|
"es6-promise": "bower_components/es6-promise/promise.min",
|
||||||
|
"EventEmitter": "bower_components/eventemitter3/index",
|
||||||
"moment": "bower_components/moment/moment",
|
"moment": "bower_components/moment/moment",
|
||||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||||
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
||||||
"screenfull": "bower_components/screenfull/dist/screenfull.min",
|
"screenfull": "bower_components/screenfull/dist/screenfull.min",
|
||||||
"text": "bower_components/text/text",
|
"text": "bower_components/text/text",
|
||||||
"uuid": "bower_components/node-uuid/uuid",
|
"uuid": "bower_components/node-uuid/uuid",
|
||||||
"zepto": "bower_components/zepto/zepto.min"
|
"zepto": "bower_components/zepto/zepto.min",
|
||||||
},
|
},
|
||||||
|
|
||||||
"shim": {
|
"shim": {
|
||||||
@ -64,6 +65,9 @@ requirejs.config({
|
|||||||
"angular-route": {
|
"angular-route": {
|
||||||
"deps": [ "angular" ]
|
"deps": [ "angular" ]
|
||||||
},
|
},
|
||||||
|
"EventEmitter": {
|
||||||
|
"exports": "EventEmitter"
|
||||||
|
},
|
||||||
"moment-duration-format": {
|
"moment-duration-format": {
|
||||||
"deps": [ "moment" ]
|
"deps": [ "moment" ]
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user