Merge branch 'master' of github.com:nasa/openmct into open967
This commit is contained in:
@@ -90,7 +90,9 @@ define(
|
||||
// Ensure there is always a "save in" section
|
||||
if (includeLocation) {
|
||||
sections.push({
|
||||
name: 'Location', rows: [{
|
||||
name: 'Location',
|
||||
cssclass: "grows",
|
||||
rows: [{
|
||||
name: "Save In",
|
||||
control: "locator",
|
||||
validate: validateLocation,
|
||||
|
||||
@@ -50,10 +50,7 @@ define(
|
||||
$scope.rootObject =
|
||||
(context && context.getRoot()) || $scope.rootObject;
|
||||
}, 0);
|
||||
} else if (!contextRoot) {
|
||||
//If no context root is available, default to the root
|
||||
// object
|
||||
$scope.rootObject = undefined;
|
||||
} else if (!contextRoot && !$scope.rootObject) {
|
||||
// Update the displayed tree on a timeout to avoid
|
||||
// an infinite digest exception.
|
||||
objectService.getObjects(['ROOT'])
|
||||
|
||||
@@ -138,23 +138,34 @@ define(
|
||||
});
|
||||
});
|
||||
describe("when no context is available", function () {
|
||||
var defaultRoot = "DEFAULT_ROOT";
|
||||
|
||||
beforeEach(function () {
|
||||
mockContext.getRoot.andReturn(undefined);
|
||||
getObjectsPromise.then.andCallFake(function (callback) {
|
||||
callback({'ROOT': defaultRoot});
|
||||
});
|
||||
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
|
||||
});
|
||||
|
||||
it("provides a default context where none is available", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockScope.rootObject).toBe(defaultRoot);
|
||||
var defaultRoot = "DEFAULT_ROOT";
|
||||
|
||||
beforeEach(function () {
|
||||
mockContext.getRoot.andReturn(undefined);
|
||||
getObjectsPromise.then.andCallFake(function (callback) {
|
||||
callback({'ROOT': defaultRoot});
|
||||
});
|
||||
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
|
||||
});
|
||||
|
||||
it("provides a default context where none is available", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockScope.rootObject).toBe(defaultRoot);
|
||||
});
|
||||
|
||||
it("does not issue redundant requests for the root object", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
mockScope.$watch.mostRecentCall.args[1](undefined);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockObjectService.getObjects.calls.length)
|
||||
.toEqual(1);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
.form {
|
||||
margin-bottom: $interiorMarginSm;
|
||||
padding-bottom: $interiorMarginLg;
|
||||
.form-section {
|
||||
.l-section-body {
|
||||
margin-bottom: 0;
|
||||
&:not(.first) {
|
||||
border-top: 1px solid $colorFormLines;
|
||||
|
||||
@@ -25,11 +25,21 @@
|
||||
|
||||
.form {
|
||||
color: $colorFormText;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.form-section {
|
||||
position: relative;
|
||||
margin-bottom: $interiorMarginLg * 2;
|
||||
}
|
||||
|
||||
.l-form-section {
|
||||
position: relative;
|
||||
&.grows {
|
||||
.l-section-body,
|
||||
.form-row {
|
||||
@include flex(1 1 auto);
|
||||
.wrapper {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
border-radius: $basicCr;
|
||||
@@ -43,10 +53,14 @@
|
||||
.form-row {
|
||||
$m: $interiorMargin;
|
||||
box-sizing: border-box;
|
||||
@include clearfix;
|
||||
border-top: 1px solid $colorFormLines;
|
||||
margin-bottom: $interiorMarginLg * 2;
|
||||
padding: $formTBPad 0;
|
||||
position: relative;
|
||||
//&ng-form {
|
||||
// display: block;
|
||||
//}
|
||||
|
||||
&.first {
|
||||
border-top: none;
|
||||
}
|
||||
@@ -92,17 +106,14 @@
|
||||
.selector-list {
|
||||
// Used in create overlay to display tree view
|
||||
@include nice-input();
|
||||
$h: 150px;
|
||||
padding: $interiorMargin;
|
||||
position: relative;
|
||||
height: $h;
|
||||
min-height: 150px;
|
||||
height: 100%;
|
||||
>.wrapper {
|
||||
$p: $interiorMargin;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
top: $p;
|
||||
right: $p;
|
||||
bottom: $p;
|
||||
left: $p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
*****************************************************************************/
|
||||
|
||||
//************************************************* GENERAL
|
||||
.bubble-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
//************************************************* LAYOUT
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
@include phone {
|
||||
.overlay > .holder {
|
||||
//@include test(orange); // This works!
|
||||
$m: 0;
|
||||
border-radius: $m;
|
||||
top: $m;
|
||||
@@ -38,36 +37,30 @@
|
||||
overflow: auto;
|
||||
@include transform(none);
|
||||
|
||||
.editor .form .form-row {
|
||||
> .label,
|
||||
> .controls {
|
||||
//@include test(blue);
|
||||
display: block;
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
> .label {
|
||||
&:after {
|
||||
float: none;
|
||||
.editor .form .form-row.l-flex-row {
|
||||
// Display elements in a columnar view
|
||||
@include flex-direction(column);
|
||||
> .flex-elem {
|
||||
&:not(:first-child) {
|
||||
margin-top: $interiorMargin;
|
||||
}
|
||||
&.label {
|
||||
width: 100%;
|
||||
}
|
||||
&.controls {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contents {
|
||||
.abs.top-bar,
|
||||
.abs.editor,
|
||||
.abs.message-body,
|
||||
.abs.bottom-bar {
|
||||
//@include test(orange);
|
||||
top: auto; right: auto; bottom: auto; left: auto;
|
||||
height: auto; width: auto;
|
||||
margin-bottom: $interiorMarginLg * 2;
|
||||
|
||||
&.validates > .label:before {
|
||||
position: relative;
|
||||
right: auto;
|
||||
line-height: inherit;
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
.t-dialog-sm .overlay > .holder {
|
||||
//@include test(blue);
|
||||
height: auto; max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,10 @@ define([
|
||||
function link(scope, element) {
|
||||
var treeView = new TreeView(gestureService),
|
||||
unobserve = treeView.observe(function (domainObject) {
|
||||
scope.mctModel = domainObject;
|
||||
scope.$apply();
|
||||
if (scope.mctModel !== domainObject) {
|
||||
scope.mctModel = domainObject;
|
||||
scope.$apply();
|
||||
}
|
||||
});
|
||||
|
||||
element.append(angular.element(treeView.elements()));
|
||||
|
||||
@@ -29,6 +29,18 @@ define([
|
||||
mockExpr,
|
||||
mctTree;
|
||||
|
||||
function makeMockDomainObject(id) {
|
||||
var mockDomainObject = jasmine.createSpyObj('domainObject-' + id, [
|
||||
'getId',
|
||||
'getModel',
|
||||
'getCapability',
|
||||
'hasCapability'
|
||||
]);
|
||||
mockDomainObject.getId.andReturn(id);
|
||||
mockDomainObject.getModel.andReturn({});
|
||||
return mockDomainObject;
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockGestureService = jasmine.createSpyObj(
|
||||
'gestureService',
|
||||
@@ -56,7 +68,8 @@ define([
|
||||
testAttrs;
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj('$scope', ['$watch', '$on']);
|
||||
mockScope =
|
||||
jasmine.createSpyObj('$scope', ['$watch', '$on', '$apply']);
|
||||
mockElement = jasmine.createSpyObj('element', ['append']);
|
||||
testAttrs = { mctModel: "some-expression" };
|
||||
mockScope.$parent =
|
||||
@@ -88,6 +101,27 @@ define([
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
// https://github.com/nasa/openmct/issues/1114
|
||||
it("does not trigger $apply during $watches", function () {
|
||||
mockScope.mctObject = makeMockDomainObject('root');
|
||||
mockScope.mctMode = makeMockDomainObject('selection');
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
call.args[1](mockScope[call.args[0]]);
|
||||
});
|
||||
expect(mockScope.$apply).not.toHaveBeenCalled();
|
||||
});
|
||||
it("does trigger $apply from other value changes", function () {
|
||||
// White-boxy; we know this is the setter for the tree's value
|
||||
var treeValueFn = mockScope.$watch.calls[0].args[1];
|
||||
|
||||
mockScope.mctObject = makeMockDomainObject('root');
|
||||
mockScope.mctMode = makeMockDomainObject('selection');
|
||||
|
||||
treeValueFn(makeMockDomainObject('other'));
|
||||
|
||||
expect(mockScope.$apply).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
define({
|
||||
BUBBLE_TEMPLATE: "<mct-container key=\"bubble\" " +
|
||||
"bubble-title=\"{{bubbleTitle}}\" " +
|
||||
"bubble-layout=\"{{bubbleLayout}}\" " +
|
||||
"class=\"bubble-container\">" +
|
||||
"bubble-layout=\"{{bubbleLayout}}\">" +
|
||||
"<mct-include key=\"bubbleTemplate\" " +
|
||||
"ng-model=\"bubbleModel\">" +
|
||||
"</mct-include>" +
|
||||
|
||||
@@ -95,7 +95,7 @@ define(
|
||||
this.locationService = locationService;
|
||||
this.composeService = composeService;
|
||||
this.verb = verb || "Compose";
|
||||
this.suffix = suffix || "to a new location";
|
||||
this.suffix = suffix || "To a New Location";
|
||||
}
|
||||
|
||||
AbstractComposeAction.prototype.cloneContext = function () {
|
||||
|
||||
@@ -54,7 +54,7 @@ define(
|
||||
copyService,
|
||||
context,
|
||||
"Duplicate",
|
||||
"to a location"
|
||||
"To a Location"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ define(
|
||||
sections: [
|
||||
{
|
||||
name: 'Location',
|
||||
cssclass: "grows",
|
||||
rows: [
|
||||
{
|
||||
name: label,
|
||||
|
||||
@@ -150,7 +150,7 @@ define(
|
||||
it("prompts for location", function () {
|
||||
expect(locationService.getLocationFromUser)
|
||||
.toHaveBeenCalledWith(
|
||||
"Compose selectedObject to a new location",
|
||||
"Compose selectedObject To a New Location",
|
||||
"Compose To",
|
||||
jasmine.any(Function),
|
||||
currentParent
|
||||
|
||||
@@ -173,7 +173,7 @@ define(
|
||||
it("prompts for location", function () {
|
||||
expect(locationService.getLocationFromUser)
|
||||
.toHaveBeenCalledWith(
|
||||
"Duplicate selectedObject to a location",
|
||||
"Duplicate selectedObject To a Location",
|
||||
"Duplicate To",
|
||||
jasmine.any(Function),
|
||||
currentParent
|
||||
|
||||
@@ -126,7 +126,7 @@ define(
|
||||
it("prompts for location", function () {
|
||||
expect(locationService.getLocationFromUser)
|
||||
.toHaveBeenCalledWith(
|
||||
"Link selectedObject to a new location",
|
||||
"Link selectedObject To a New Location",
|
||||
"Link To",
|
||||
jasmine.any(Function),
|
||||
currentParent
|
||||
|
||||
@@ -126,7 +126,7 @@ define(
|
||||
it("prompts for location", function () {
|
||||
expect(locationService.getLocationFromUser)
|
||||
.toHaveBeenCalledWith(
|
||||
"Move selectedObject to a new location",
|
||||
"Move selectedObject To a New Location",
|
||||
"Move To",
|
||||
jasmine.any(Function),
|
||||
currentParent
|
||||
|
||||
@@ -139,6 +139,7 @@ define([
|
||||
"dialog": {
|
||||
"control": "textfield",
|
||||
"name": "Image URL",
|
||||
"cssclass": "l-input-lg",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
@@ -213,12 +214,12 @@ define([
|
||||
{
|
||||
"name": "Horizontal grid (px)",
|
||||
"control": "textfield",
|
||||
"cssclass": "l-small l-numeric"
|
||||
"cssclass": "l-input-sm l-numeric"
|
||||
},
|
||||
{
|
||||
"name": "Vertical grid (px)",
|
||||
"control": "textfield",
|
||||
"cssclass": "l-small l-numeric"
|
||||
"cssclass": "l-input-sm l-numeric"
|
||||
}
|
||||
],
|
||||
"pattern": "^(\\d*[1-9]\\d*)?$",
|
||||
|
||||
@@ -169,6 +169,7 @@ define([
|
||||
"dialog": {
|
||||
"control": "textfield",
|
||||
"name": "Image URL",
|
||||
"cssclass": "l-input-lg",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
@@ -329,12 +330,12 @@ define([
|
||||
{
|
||||
"name": "Horizontal grid (px)",
|
||||
"control": "textfield",
|
||||
"cssclass": "l-small l-numeric"
|
||||
"cssclass": "l-input-sm l-numeric"
|
||||
},
|
||||
{
|
||||
"name": "Vertical grid (px)",
|
||||
"control": "textfield",
|
||||
"cssclass": "l-small l-numeric"
|
||||
"cssclass": "l-input-sm l-numeric"
|
||||
}
|
||||
],
|
||||
"pattern": "^(\\d*[1-9]\\d*)?$",
|
||||
|
||||
@@ -55,6 +55,7 @@ define(
|
||||
key: "url",
|
||||
control: "textfield",
|
||||
name: "Image URL",
|
||||
"cssclass": "l-input-lg",
|
||||
required: true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -19,39 +19,39 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<form name="mctForm" novalidate class="form">
|
||||
<span ng-repeat="section in structure.sections">
|
||||
<div class="section-header" ng-if="section.name">
|
||||
<form name="mctForm" novalidate class="form l-flex-col">
|
||||
<span ng-repeat="section in structure.sections"
|
||||
class="l-form-section l-flex-col flex-elem {{ section.cssclass }}">
|
||||
<div class="section-header flex-elem" ng-if="section.name">
|
||||
{{section.name}}
|
||||
</div>
|
||||
<div class="form-section" ng-class="{ first:$index < 1 }">
|
||||
<ng-form name="mctFormInner" ng-repeat="row in section.rows">
|
||||
<div class="form-row validates l-flex-row"
|
||||
ng-class="{
|
||||
req: row.required,
|
||||
valid: mctFormInner.$dirty && mctFormInner.$valid,
|
||||
invalid: mctFormInner.$dirty && !mctFormInner.$valid,
|
||||
first: $index < 1,
|
||||
'l-controls-first': row.layout === 'control-first',
|
||||
'l-controls-under': row.layout === 'controls-under'
|
||||
}">
|
||||
<div class='label flex-elem' title="{{row.description}}">
|
||||
{{row.name}}
|
||||
</div>
|
||||
<div class='controls flex-elem'>
|
||||
<div class="wrapper" ng-if="row.control">
|
||||
<mct-control key="row.control"
|
||||
ng-model="ngModel"
|
||||
ng-required="row.required"
|
||||
ng-pattern="getRegExp(row.pattern)"
|
||||
options="row.options"
|
||||
structure="row"
|
||||
field="row.key">
|
||||
</mct-control>
|
||||
</div>
|
||||
</div>
|
||||
<ng-form class="form-row validates l-flex-row flex-elem {{ section.cssclass }}"
|
||||
ng-class="{
|
||||
first:$index < 1,
|
||||
req: row.required,
|
||||
valid: mctFormInner.$dirty && mctFormInner.$valid,
|
||||
invalid: mctFormInner.$dirty && !mctFormInner.$valid,
|
||||
first: $index < 1,
|
||||
'l-controls-first': row.layout === 'control-first',
|
||||
'l-controls-under': row.layout === 'controls-under'
|
||||
}"
|
||||
name="mctFormInner"
|
||||
ng-repeat="row in section.rows">
|
||||
<div class='label flex-elem' title="{{row.description}}">
|
||||
{{row.name}}
|
||||
</div>
|
||||
<div class='controls flex-elem'>
|
||||
<div class="wrapper" ng-if="row.control">
|
||||
<mct-control key="row.control"
|
||||
ng-model="ngModel"
|
||||
ng-required="row.required"
|
||||
ng-pattern="getRegExp(row.pattern)"
|
||||
options="row.options"
|
||||
structure="row"
|
||||
field="row.key">
|
||||
</mct-control>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
</div>
|
||||
</ng-form>
|
||||
</span>
|
||||
</form>
|
||||
@@ -80,7 +80,7 @@ define(function () {
|
||||
// If there's still nothing in the filters string, there are no
|
||||
// filters selected
|
||||
if ($scope.ngModel.filtersString === '') {
|
||||
$scope.ngModel.filtersString = 'NONE';
|
||||
$scope.ngModel.checkAll = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,12 +95,11 @@ define(function () {
|
||||
$scope.ngModel.checked[type] = false;
|
||||
});
|
||||
|
||||
// Change the filters string depending on checkAll status
|
||||
if ($scope.ngModel.checkAll) {
|
||||
// This setting will make the filters display hidden
|
||||
$scope.ngModel.filtersString = '';
|
||||
} else {
|
||||
$scope.ngModel.filtersString = 'NONE';
|
||||
// This setting will make the filters display hidden
|
||||
$scope.ngModel.filtersString = '';
|
||||
// Do not let checkAll become unchecked when it is the only checked filter
|
||||
if (!$scope.ngModel.checkAll) {
|
||||
$scope.ngModel.checkAll = true;
|
||||
}
|
||||
|
||||
// Re-filter results
|
||||
|
||||
@@ -76,14 +76,16 @@ define(
|
||||
expect(mockScope.ngModel.filtersString).not.toEqual('');
|
||||
});
|
||||
|
||||
it("changing checkAll status updates the filter string", function () {
|
||||
it("changing checkAll status sets checkAll to true", function () {
|
||||
controller.checkAll();
|
||||
expect(mockScope.ngModel.checkAll).toEqual(true);
|
||||
expect(mockScope.ngModel.filtersString).toEqual('');
|
||||
|
||||
mockScope.ngModel.checkAll = false;
|
||||
|
||||
controller.checkAll();
|
||||
expect(mockScope.ngModel.filtersString).toEqual('NONE');
|
||||
expect(mockScope.ngModel.checkAll).toEqual(true);
|
||||
expect(mockScope.ngModel.filtersString).toEqual('');
|
||||
});
|
||||
|
||||
it("checking checkAll option resets other options", function () {
|
||||
@@ -97,7 +99,7 @@ define(
|
||||
});
|
||||
});
|
||||
|
||||
it("tells the user when no options are checked", function () {
|
||||
it("checks checkAll when no options are checked", function () {
|
||||
Object.keys(mockScope.ngModel.checked).forEach(function (type) {
|
||||
mockScope.ngModel.checked[type] = false;
|
||||
});
|
||||
@@ -105,7 +107,8 @@ define(
|
||||
|
||||
controller.updateOptions();
|
||||
|
||||
expect(mockScope.ngModel.filtersString).toEqual('NONE');
|
||||
expect(mockScope.ngModel.filtersString).toEqual('');
|
||||
expect(mockScope.ngModel.checkAll).toEqual(true);
|
||||
});
|
||||
|
||||
it("tells the user when options are checked", function () {
|
||||
@@ -116,7 +119,6 @@ define(
|
||||
|
||||
controller.updateOptions();
|
||||
|
||||
expect(mockScope.ngModel.filtersString).not.toEqual('NONE');
|
||||
expect(mockScope.ngModel.filtersString).not.toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user