mirror of
https://github.com/nasa/openmct.git
synced 2025-03-19 18:45:31 +00:00
Merge remote-tracking branch 'github-open/open181' into open-master
This commit is contained in:
commit
90828ef63d
@ -19,84 +19,90 @@
|
|||||||
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.
|
||||||
-->
|
-->
|
||||||
<!-- MINE -->
|
|
||||||
<div ng-controller="TimeRangeController">
|
<div ng-controller="TimeRangeController">
|
||||||
<div class="l-time-range-inputs-holder">
|
<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-inputs-elem ui-symbol type-icon">C</span>
|
||||||
<span class="l-time-range-input" ng-controller="ToggleController as t1">
|
<span class="l-time-range-input" ng-controller="ToggleController as t1">
|
||||||
<!--<span class="lbl">Start</span>-->
|
<!--<span class="lbl">Start</span>-->
|
||||||
<span class="s-btn time-range-start" ng-click="t1.toggle()">
|
<span class="s-btn time-range-start">
|
||||||
<span class="val">{{startOuterText}}</span>
|
<input type="text"
|
||||||
<a class="ui-symbol icon icon-calendar"></a>
|
ng-model="boundsModel.start"
|
||||||
<mct-popup ng-if="t1.isActive()">
|
ng-class="{ error: !boundsModel.startValid }">
|
||||||
<div mct-click-elsewhere="t1.setState(false)">
|
</input>
|
||||||
<mct-control key="'datetime-picker'"
|
<a class="ui-symbol icon icon-calendar" ng-click="t1.toggle()"></a>
|
||||||
ng-model="ngModel.outer"
|
<mct-popup ng-if="t1.isActive()">
|
||||||
field="'start'"
|
<div mct-click-elsewhere="t1.setState(false)">
|
||||||
options="{ hours: true }">
|
<mct-control key="'datetime-picker'"
|
||||||
</mct-control>
|
ng-model="ngModel.outer"
|
||||||
</div>
|
field="'start'"
|
||||||
</mct-popup>
|
options="{ hours: true }">
|
||||||
</span>
|
</mct-control>
|
||||||
</span>
|
</div>
|
||||||
|
</mct-popup>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
<span class="l-time-range-inputs-elem lbl">to</span>
|
<span class="l-time-range-inputs-elem lbl">to</span>
|
||||||
|
|
||||||
<span class="l-time-range-input" ng-controller="ToggleController as t2">
|
<span class="l-time-range-input" ng-controller="ToggleController as t2">
|
||||||
<!--<span class="lbl">End</span>-->
|
<!--<span class="lbl">End</span>-->
|
||||||
<span class="s-btn l-time-range-input" ng-click="t2.toggle()">
|
<span class="s-btn l-time-range-input">
|
||||||
<span class="val">{{endOuterText}}</span>
|
<input type="text"
|
||||||
<a class="ui-symbol icon icon-calendar"></a>
|
ng-model="boundsModel.end"
|
||||||
<mct-popup ng-if="t2.isActive()">
|
ng-class="{ error: !boundsModel.endValid }">
|
||||||
<div mct-click-elsewhere="t2.setState(false)">
|
</input>
|
||||||
<mct-control key="'datetime-picker'"
|
<a class="ui-symbol icon icon-calendar" ng-click="t2.toggle()">
|
||||||
ng-model="ngModel.outer"
|
</a>
|
||||||
field="'end'"
|
<mct-popup ng-if="t2.isActive()">
|
||||||
options="{ hours: true }">
|
<div mct-click-elsewhere="t2.setState(false)">
|
||||||
</mct-control>
|
<mct-control key="'datetime-picker'"
|
||||||
</div>
|
ng-model="ngModel.outer"
|
||||||
</mct-popup>
|
field="'end'"
|
||||||
</span>
|
options="{ hours: true }">
|
||||||
</span>
|
</mct-control>
|
||||||
</div>
|
</div>
|
||||||
|
</mct-popup>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="l-time-range-slider-holder">
|
<div class="l-time-range-slider-holder">
|
||||||
<div class="l-time-range-slider">
|
<div class="l-time-range-slider">
|
||||||
<div class="slider"
|
<div class="slider"
|
||||||
mct-resize="spanWidth = bounds.width">
|
mct-resize="spanWidth = bounds.width">
|
||||||
<div class="knob knob-l"
|
<div class="knob knob-l"
|
||||||
mct-drag-down="startLeftDrag()"
|
mct-drag-down="startLeftDrag()"
|
||||||
mct-drag="leftDrag(delta[0])"
|
mct-drag="leftDrag(delta[0])"
|
||||||
ng-style="{ left: startInnerPct }">
|
ng-style="{ left: startInnerPct }">
|
||||||
<div class="range-value">{{startInnerText}}</div>
|
<div class="range-value">{{startInnerText}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="knob knob-r"
|
<div class="knob knob-r"
|
||||||
mct-drag-down="startRightDrag()"
|
mct-drag-down="startRightDrag()"
|
||||||
mct-drag="rightDrag(delta[0])"
|
mct-drag="rightDrag(delta[0])"
|
||||||
ng-style="{ right: endInnerPct }">
|
ng-style="{ right: endInnerPct }">
|
||||||
<div class="range-value">{{endInnerText}}</div>
|
<div class="range-value">{{endInnerText}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="slot range-holder">
|
<div class="slot range-holder">
|
||||||
<div class="range"
|
<div class="range"
|
||||||
mct-drag-down="startMiddleDrag()"
|
mct-drag-down="startMiddleDrag()"
|
||||||
mct-drag="middleDrag(delta[0])"
|
mct-drag="middleDrag(delta[0])"
|
||||||
ng-style="{ left: startInnerPct, right: endInnerPct}">
|
ng-style="{ left: startInnerPct, right: endInnerPct}">
|
||||||
<div class="toi-line"></div>
|
<div class="toi-line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="l-time-range-ticks-holder">
|
<div class="l-time-range-ticks-holder">
|
||||||
<div class="l-time-range-ticks">
|
<div class="l-time-range-ticks">
|
||||||
<div
|
<div
|
||||||
ng-repeat="tick in ticks"
|
ng-repeat="tick in ticks"
|
||||||
ng-style="{ left: $index * (100 / (ticks.length - 1)) + '%' }"
|
ng-style="{ left: $index * (100 / (ticks.length - 1)) + '%' }"
|
||||||
class="tick tick-x"
|
class="tick tick-x"
|
||||||
>
|
>
|
||||||
<span class="l-time-range-tick-label">{{tick}}</span>
|
<span class="l-time-range-tick-label">{{tick}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,9 +26,8 @@ define(
|
|||||||
function (moment) {
|
function (moment) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var
|
var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss",
|
||||||
DATE_FORMAT = "YYYY-MM-DD HH:mm:ss",
|
TICK_SPACING_PX = 150;
|
||||||
TICK_SPACING_PX = 150;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @memberof platform/commonUI/general
|
* @memberof platform/commonUI/general
|
||||||
@ -44,6 +43,15 @@ define(
|
|||||||
return moment.utc(ts).format(DATE_FORMAT);
|
return moment.utc(ts).format(DATE_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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%"-"1%"
|
||||||
function toPercent(p) {
|
function toPercent(p) {
|
||||||
return (100 * p) + "%";
|
return (100 * p) + "%";
|
||||||
@ -93,6 +101,25 @@ define(
|
|||||||
return { start: bounds.start, end: bounds.end };
|
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) {
|
function updateViewFromModel(ngModel) {
|
||||||
var t = now();
|
var t = now();
|
||||||
|
|
||||||
@ -101,8 +128,7 @@ define(
|
|||||||
ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
|
ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
|
||||||
|
|
||||||
// First, dates for the date pickers for outer bounds
|
// First, dates for the date pickers for outer bounds
|
||||||
$scope.startOuterDate = new Date(ngModel.outer.start);
|
updateBoundsText(ngModel);
|
||||||
$scope.endOuterDate = new Date(ngModel.outer.end);
|
|
||||||
|
|
||||||
// Then various updates for the inner span
|
// Then various updates for the inner span
|
||||||
updateViewForInnerSpanFromModel(ngModel);
|
updateViewForInnerSpanFromModel(ngModel);
|
||||||
@ -178,6 +204,8 @@ define(
|
|||||||
function updateOuterStart(t) {
|
function updateOuterStart(t) {
|
||||||
var ngModel = $scope.ngModel;
|
var ngModel = $scope.ngModel;
|
||||||
|
|
||||||
|
ngModel.outer.start = t;
|
||||||
|
|
||||||
ngModel.outer.end = Math.max(
|
ngModel.outer.end = Math.max(
|
||||||
ngModel.outer.start + outerMinimumSpan,
|
ngModel.outer.start + outerMinimumSpan,
|
||||||
ngModel.outer.end
|
ngModel.outer.end
|
||||||
@ -190,14 +218,15 @@ define(
|
|||||||
ngModel.inner.end
|
ngModel.inner.end
|
||||||
);
|
);
|
||||||
|
|
||||||
$scope.startOuterText = formatTimestamp(t);
|
|
||||||
|
|
||||||
updateViewForInnerSpanFromModel(ngModel);
|
updateViewForInnerSpanFromModel(ngModel);
|
||||||
|
updateTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOuterEnd(t) {
|
function updateOuterEnd(t) {
|
||||||
var ngModel = $scope.ngModel;
|
var ngModel = $scope.ngModel;
|
||||||
|
|
||||||
|
ngModel.outer.end = t;
|
||||||
|
|
||||||
ngModel.outer.start = Math.min(
|
ngModel.outer.start = Math.min(
|
||||||
ngModel.outer.end - outerMinimumSpan,
|
ngModel.outer.end - outerMinimumSpan,
|
||||||
ngModel.outer.start
|
ngModel.outer.start
|
||||||
@ -210,9 +239,40 @@ define(
|
|||||||
ngModel.inner.start
|
ngModel.inner.start
|
||||||
);
|
);
|
||||||
|
|
||||||
$scope.endOuterText = formatTimestamp(t);
|
|
||||||
|
|
||||||
updateViewForInnerSpanFromModel(ngModel);
|
updateViewForInnerSpanFromModel(ngModel);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.startLeftDrag = startLeftDrag;
|
$scope.startLeftDrag = startLeftDrag;
|
||||||
@ -224,14 +284,17 @@ define(
|
|||||||
|
|
||||||
$scope.state = false;
|
$scope.state = false;
|
||||||
$scope.ticks = [];
|
$scope.ticks = [];
|
||||||
|
$scope.boundsModel = {};
|
||||||
|
|
||||||
// Initialize scope to defaults
|
// Initialize scope to defaults
|
||||||
updateViewFromModel($scope.ngModel);
|
updateViewFromModel($scope.ngModel);
|
||||||
|
|
||||||
$scope.$watchCollection("ngModel", updateViewFromModel);
|
$scope.$watchCollection("ngModel", updateViewFromModel);
|
||||||
$scope.$watch("spanWidth", updateSpanWidth);
|
$scope.$watch("spanWidth", updateSpanWidth);
|
||||||
$scope.$watch("ngModel.outer.start", updateOuterStart);
|
$scope.$watch("ngModel.outer.start", updateStartFromPicker);
|
||||||
$scope.$watch("ngModel.outer.end", updateOuterEnd);
|
$scope.$watch("ngModel.outer.end", updateEndFromPicker);
|
||||||
|
$scope.$watch("boundsModel.start", updateStartFromText);
|
||||||
|
$scope.$watch("boundsModel.end", updateEndFromText);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TimeConductorController;
|
return TimeConductorController;
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||||
|
|
||||||
define(
|
define(
|
||||||
["../../src/controllers/TimeRangeController"],
|
["../../src/controllers/TimeRangeController", "moment"],
|
||||||
function (TimeRangeController) {
|
function (TimeRangeController, moment) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var SEC = 1000,
|
var SEC = 1000,
|
||||||
@ -166,8 +166,72 @@ define(
|
|||||||
expect(mockScope.ngModel.inner.end)
|
expect(mockScope.ngModel.inner.end)
|
||||||
.toBeGreaterThan(mockScope.ngModel.inner.start);
|
.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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user