mirror of
https://github.com/nasa/openmct.git
synced 2025-06-14 05:08:15 +00:00
Merge branch 'master' into open460
This commit is contained in:
@ -119,6 +119,12 @@ define([
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"implementation": "filters/ReverseFilter.js",
|
||||||
|
"key": "reverse"
|
||||||
|
}
|
||||||
|
],
|
||||||
"stylesheets": [
|
"stylesheets": [
|
||||||
{
|
{
|
||||||
"stylesheetUrl": "css/normalize.min.css",
|
"stylesheetUrl": "css/normalize.min.css",
|
||||||
|
@ -266,6 +266,8 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
|||||||
|
|
||||||
.gl-plot-tick,
|
.gl-plot-tick,
|
||||||
.tick-label {
|
.tick-label {
|
||||||
|
direction: rtl;
|
||||||
|
unicode-bidi:bidi-override;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -24,7 +24,11 @@
|
|||||||
<input type="text"
|
<input type="text"
|
||||||
ng-model="textValue"
|
ng-model="textValue"
|
||||||
ng-blur="restoreTextValue(); ngBlur()"
|
ng-blur="restoreTextValue(); ngBlur()"
|
||||||
ng-class="{ error: textInvalid }">
|
ng-class="{
|
||||||
|
error: textInvalid ||
|
||||||
|
(structure.validate &&
|
||||||
|
!structure.validate(ngModel[field]))
|
||||||
|
}">
|
||||||
</input>
|
</input>
|
||||||
<a class="ui-symbol icon icon-calendar"
|
<a class="ui-symbol icon icon-calendar"
|
||||||
ng-if="structure.format === 'utc' || !structure.format"
|
ng-if="structure.format === 'utc' || !structure.format"
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<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">
|
<span class="l-time-range-input">
|
||||||
<mct-control key="'datetime-field'"
|
<mct-control key="'datetime-field'"
|
||||||
structure="{ format: parameters.format }"
|
structure="{ format: parameters.format, validate: validateStart }"
|
||||||
ng-model="formModel"
|
ng-model="formModel"
|
||||||
ng-blur="updateBoundsFromForm()"
|
ng-blur="updateBoundsFromForm()"
|
||||||
field="'start'"
|
field="'start'"
|
||||||
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
<span class="l-time-range-input" ng-controller="ToggleController as t2">
|
<span class="l-time-range-input" ng-controller="ToggleController as t2">
|
||||||
<mct-control key="'datetime-field'"
|
<mct-control key="'datetime-field'"
|
||||||
structure="{ format: parameters.format }"
|
structure="{ format: parameters.format, validate: validateEnd }"
|
||||||
ng-model="formModel"
|
ng-model="formModel"
|
||||||
ng-blur="updateBoundsFromForm()"
|
ng-blur="updateBoundsFromForm()"
|
||||||
field="'end'"
|
field="'end'"
|
||||||
|
@ -43,7 +43,7 @@ define(
|
|||||||
function TimeRangeController($scope, formatService, defaultFormat, now) {
|
function TimeRangeController($scope, formatService, defaultFormat, now) {
|
||||||
var tickCount = 2,
|
var tickCount = 2,
|
||||||
innerMinimumSpan = 1000, // 1 second
|
innerMinimumSpan = 1000, // 1 second
|
||||||
outerMinimumSpan = 1000 * 60 * 60, // 1 hour
|
outerMinimumSpan = 1000, // 1 second
|
||||||
initialDragValue,
|
initialDragValue,
|
||||||
formatter = formatService.getFormat(defaultFormat);
|
formatter = formatService.getFormat(defaultFormat);
|
||||||
|
|
||||||
@ -185,13 +185,6 @@ 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.start + outerMinimumSpan,
|
|
||||||
ngModel.outer.end
|
|
||||||
);
|
|
||||||
|
|
||||||
ngModel.inner.start =
|
ngModel.inner.start =
|
||||||
Math.max(ngModel.outer.start, ngModel.inner.start);
|
Math.max(ngModel.outer.start, ngModel.inner.start);
|
||||||
ngModel.inner.end = Math.max(
|
ngModel.inner.end = Math.max(
|
||||||
@ -207,13 +200,6 @@ define(
|
|||||||
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.end - outerMinimumSpan,
|
|
||||||
ngModel.outer.start
|
|
||||||
);
|
|
||||||
|
|
||||||
ngModel.inner.end =
|
ngModel.inner.end =
|
||||||
Math.min(ngModel.outer.end, ngModel.inner.end);
|
Math.min(ngModel.outer.end, ngModel.inner.end);
|
||||||
ngModel.inner.start = Math.min(
|
ngModel.inner.start = Math.min(
|
||||||
@ -233,11 +219,20 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateBoundsFromForm() {
|
function updateBoundsFromForm() {
|
||||||
$scope.ngModel = $scope.ngModel || {};
|
var start = $scope.formModel.start,
|
||||||
$scope.ngModel.outer = {
|
end = $scope.formModel.end;
|
||||||
start: $scope.formModel.start,
|
if (end >= start + outerMinimumSpan) {
|
||||||
end: $scope.formModel.end
|
$scope.ngModel = $scope.ngModel || {};
|
||||||
};
|
$scope.ngModel.outer = { start: start, end: end };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateStart(startValue) {
|
||||||
|
return startValue <= $scope.formModel.end - outerMinimumSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateEnd(endValue) {
|
||||||
|
return endValue >= $scope.formModel.start + outerMinimumSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.startLeftDrag = startLeftDrag;
|
$scope.startLeftDrag = startLeftDrag;
|
||||||
@ -249,6 +244,9 @@ define(
|
|||||||
|
|
||||||
$scope.updateBoundsFromForm = updateBoundsFromForm;
|
$scope.updateBoundsFromForm = updateBoundsFromForm;
|
||||||
|
|
||||||
|
$scope.validateStart = validateStart;
|
||||||
|
$scope.validateEnd = validateEnd;
|
||||||
|
|
||||||
$scope.ticks = [];
|
$scope.ticks = [];
|
||||||
|
|
||||||
// Initialize scope to defaults
|
// Initialize scope to defaults
|
||||||
|
44
platform/commonUI/general/src/filters/ReverseFilter.js
Normal file
44
platform/commonUI/general/src/filters/ReverseFilter.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the `reverse` filter, which reverses text strings.
|
||||||
|
* Useful in cases where text should be reversed for presentational
|
||||||
|
* reasons (e.g. in conjunction with CSS tricks involing text direction),
|
||||||
|
* allowing such behavior to be handled independently from the controller
|
||||||
|
* layer.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @memberof platform/commonUI/general
|
||||||
|
*/
|
||||||
|
function ReverseFilter() {
|
||||||
|
return function reverse(value) {
|
||||||
|
return value && value.toString().split('').reverse().join('');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReverseFilter;
|
||||||
|
});
|
@ -91,6 +91,24 @@ define(
|
|||||||
.toHaveBeenCalledWith("ngModel", jasmine.any(Function));
|
.toHaveBeenCalledWith("ngModel", jasmine.any(Function));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("exposes start time validator", function () {
|
||||||
|
var testValue = 42000000;
|
||||||
|
mockScope.formModel = { end: testValue };
|
||||||
|
expect(mockScope.validateStart(testValue + 1))
|
||||||
|
.toBe(false);
|
||||||
|
expect(mockScope.validateStart(testValue - 60 * 60 * 1000 - 1))
|
||||||
|
.toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("exposes end time validator", function () {
|
||||||
|
var testValue = 42000000;
|
||||||
|
mockScope.formModel = { start: testValue };
|
||||||
|
expect(mockScope.validateEnd(testValue - 1))
|
||||||
|
.toBe(false);
|
||||||
|
expect(mockScope.validateEnd(testValue + 60 * 60 * 1000 + 1))
|
||||||
|
.toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
describe("when changes are made via form entry", function () {
|
describe("when changes are made via form entry", function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockScope.ngModel = {
|
mockScope.ngModel = {
|
||||||
@ -194,26 +212,6 @@ define(
|
|||||||
fireWatchCollection("ngModel", mockScope.ngModel);
|
fireWatchCollection("ngModel", mockScope.ngModel);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("enforces a minimum outer span", function () {
|
|
||||||
mockScope.ngModel.outer.end =
|
|
||||||
mockScope.ngModel.outer.start - DAY * 100;
|
|
||||||
fireWatch(
|
|
||||||
"ngModel.outer.end",
|
|
||||||
mockScope.ngModel.outer.end
|
|
||||||
);
|
|
||||||
expect(mockScope.ngModel.outer.end)
|
|
||||||
.toBeGreaterThan(mockScope.ngModel.outer.start);
|
|
||||||
|
|
||||||
mockScope.ngModel.outer.start =
|
|
||||||
mockScope.ngModel.outer.end + DAY * 100;
|
|
||||||
fireWatch(
|
|
||||||
"ngModel.outer.start",
|
|
||||||
mockScope.ngModel.outer.start
|
|
||||||
);
|
|
||||||
expect(mockScope.ngModel.outer.end)
|
|
||||||
.toBeGreaterThan(mockScope.ngModel.outer.start);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("enforces a minimum inner span when outer span changes", function () {
|
it("enforces a minimum inner span when outer span changes", function () {
|
||||||
mockScope.ngModel.outer.end =
|
mockScope.ngModel.outer.end =
|
||||||
mockScope.ngModel.outer.start - DAY * 100;
|
mockScope.ngModel.outer.start - DAY * 100;
|
||||||
|
45
platform/commonUI/general/test/filters/ReverseFilterSpec.js
Normal file
45
platform/commonUI/general/test/filters/ReverseFilterSpec.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
['../../src/filters/ReverseFilter'],
|
||||||
|
function (ReverseFilter) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe("The reverse filter", function () {
|
||||||
|
var reverse;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
reverse = new ReverseFilter();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reverses text", function () {
|
||||||
|
expect(reverse('foo')).toEqual('oof');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns undefined for undefined inputs", function () {
|
||||||
|
expect(reverse(undefined)).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -20,6 +20,7 @@
|
|||||||
"directives/MCTScroll",
|
"directives/MCTScroll",
|
||||||
"directives/MCTSplitPane",
|
"directives/MCTSplitPane",
|
||||||
"directives/MCTSplitter",
|
"directives/MCTSplitter",
|
||||||
|
"filters/ReverseFilter",
|
||||||
"services/Popup",
|
"services/Popup",
|
||||||
"services/PopupService",
|
"services/PopupService",
|
||||||
"services/UrlService",
|
"services/UrlService",
|
||||||
|
@ -4299,10 +4299,10 @@ textarea {
|
|||||||
.field-hints,
|
.field-hints,
|
||||||
.fields {
|
.fields {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.field-hints {
|
.field-hints {
|
||||||
|
|
||||||
}
|
}
|
||||||
*/ }
|
*/ }
|
||||||
/* line 30, ../../../../general/res/sass/forms/_datetime.scss */
|
/* line 30, ../../../../general/res/sass/forms/_datetime.scss */
|
||||||
@ -7329,6 +7329,8 @@ table {
|
|||||||
/* line 267, ../../../../general/res/sass/plots/_plots-main.scss */
|
/* line 267, ../../../../general/res/sass/plots/_plots-main.scss */
|
||||||
.gl-plot-tick,
|
.gl-plot-tick,
|
||||||
.tick-label {
|
.tick-label {
|
||||||
|
direction: rtl;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -4196,10 +4196,10 @@ textarea {
|
|||||||
.field-hints,
|
.field-hints,
|
||||||
.fields {
|
.fields {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.field-hints {
|
.field-hints {
|
||||||
|
|
||||||
}
|
}
|
||||||
*/ }
|
*/ }
|
||||||
/* line 30, ../../../../general/res/sass/forms/_datetime.scss */
|
/* line 30, ../../../../general/res/sass/forms/_datetime.scss */
|
||||||
@ -7202,6 +7202,8 @@ table {
|
|||||||
/* line 267, ../../../../general/res/sass/plots/_plots-main.scss */
|
/* line 267, ../../../../general/res/sass/plots/_plots-main.scss */
|
||||||
.gl-plot-tick,
|
.gl-plot-tick,
|
||||||
.tick-label {
|
.tick-label {
|
||||||
|
direction: rtl;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
<div ng-repeat="tick in subplot.getRangeTicks()"
|
<div ng-repeat="tick in subplot.getRangeTicks()"
|
||||||
class="gl-plot-tick gl-plot-y-tick-label"
|
class="gl-plot-tick gl-plot-y-tick-label"
|
||||||
ng-style="{ bottom: (100 * $index / (subplot.getRangeTicks().length - 1)) + '%' }">
|
ng-style="{ bottom: (100 * $index / (subplot.getRangeTicks().length - 1)) + '%' }">
|
||||||
{{tick.label}}
|
{{tick.label | reverse}}
|
||||||
</div>
|
</div>
|
||||||
<div class="gl-plot-y-options gl-plot-local-controls"
|
<div class="gl-plot-y-options gl-plot-local-controls"
|
||||||
ng-if="axes[1].options.length > 1">
|
ng-if="axes[1].options.length > 1">
|
||||||
@ -125,7 +125,7 @@
|
|||||||
class="gl-plot-tick gl-plot-x-tick-label"
|
class="gl-plot-tick gl-plot-x-tick-label"
|
||||||
ng-show="$index > 0 && $index < (subplot.getDomainTicks().length - 1)"
|
ng-show="$index > 0 && $index < (subplot.getDomainTicks().length - 1)"
|
||||||
ng-style="{ left: (100 * $index / (subplot.getDomainTicks().length - 1)) + '%' }">
|
ng-style="{ left: (100 * $index / (subplot.getDomainTicks().length - 1)) + '%' }">
|
||||||
{{tick.label}}
|
{{tick.label | reverse}}
|
||||||
</div>
|
</div>
|
||||||
<div class="gl-plot-label gl-plot-x-label">
|
<div class="gl-plot-label gl-plot-x-label">
|
||||||
{{axes[0].active.name}}
|
{{axes[0].active.name}}
|
||||||
|
@ -221,6 +221,13 @@ define(
|
|||||||
CustomRegistrars.prototype.services =
|
CustomRegistrars.prototype.services =
|
||||||
mapUpon(customRegistrar("service"));
|
mapUpon(customRegistrar("service"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Angular filters.
|
||||||
|
* @param {Array} extensions the resolved extensions
|
||||||
|
*/
|
||||||
|
CustomRegistrars.prototype.filters =
|
||||||
|
mapUpon(customRegistrar("filter"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register functions which will run after bootstrapping.
|
* Register functions which will run after bootstrapping.
|
||||||
* @param {Array} extensions the resolved extensions
|
* @param {Array} extensions the resolved extensions
|
||||||
|
Reference in New Issue
Block a user