Compare commits
14 Commits
remove-con
...
create-new
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a53a669154 | ||
|
|
0602613b6e | ||
|
|
7620432388 | ||
|
|
fc8663c049 | ||
|
|
adfe30a891 | ||
|
|
5218e350c3 | ||
|
|
88615e92d2 | ||
|
|
12477a220b | ||
|
|
9582fb2b06 | ||
|
|
3c075b7ff2 | ||
|
|
081edfbd70 | ||
|
|
04cc8f7aa2 | ||
|
|
a1d206bfc3 | ||
|
|
ef9c6d5fed |
@@ -33,6 +33,7 @@ define([
|
|||||||
"./src/actions/SaveAndStopEditingAction",
|
"./src/actions/SaveAndStopEditingAction",
|
||||||
"./src/actions/SaveAsAction",
|
"./src/actions/SaveAsAction",
|
||||||
"./src/actions/CancelAction",
|
"./src/actions/CancelAction",
|
||||||
|
"./src/actions/CreateNewFolderAction",
|
||||||
"./src/policies/EditActionPolicy",
|
"./src/policies/EditActionPolicy",
|
||||||
"./src/policies/EditPersistableObjectsPolicy",
|
"./src/policies/EditPersistableObjectsPolicy",
|
||||||
"./src/policies/EditableLinkPolicy",
|
"./src/policies/EditableLinkPolicy",
|
||||||
@@ -71,6 +72,7 @@ define([
|
|||||||
SaveAndStopEditingAction,
|
SaveAndStopEditingAction,
|
||||||
SaveAsAction,
|
SaveAsAction,
|
||||||
CancelAction,
|
CancelAction,
|
||||||
|
CreateNewFolderAction,
|
||||||
EditActionPolicy,
|
EditActionPolicy,
|
||||||
EditPersistableObjectsPolicy,
|
EditPersistableObjectsPolicy,
|
||||||
EditableLinkPolicy,
|
EditableLinkPolicy,
|
||||||
@@ -145,7 +147,10 @@ define([
|
|||||||
"depends": [
|
"depends": [
|
||||||
"$scope",
|
"$scope",
|
||||||
"$timeout",
|
"$timeout",
|
||||||
"objectService"
|
"objectService",
|
||||||
|
"typeService",
|
||||||
|
"policyService",
|
||||||
|
"instantiate"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -188,6 +193,7 @@ define([
|
|||||||
"name": "Remove",
|
"name": "Remove",
|
||||||
"description": "Remove this object from its containing object.",
|
"description": "Remove this object from its containing object.",
|
||||||
"depends": [
|
"depends": [
|
||||||
|
"dialogService",
|
||||||
"navigationService"
|
"navigationService"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -241,6 +247,14 @@ define([
|
|||||||
"cssClass": "icon-x no-label",
|
"cssClass": "icon-x no-label",
|
||||||
"description": "Discard changes made to these objects.",
|
"description": "Discard changes made to these objects.",
|
||||||
"depends": []
|
"depends": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "create-new-folder",
|
||||||
|
"implementation": CreateNewFolderAction,
|
||||||
|
"description": "Creates a new folder.",
|
||||||
|
"depends": [
|
||||||
|
"typeService"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"policies": [
|
"policies": [
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<!--span
|
||||||
|
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
Administration. All rights reserved.
|
||||||
|
|
||||||
|
Open MCT 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 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 name="newFolder" ng-controller="LocatorController">
|
||||||
|
<div ng-if="!createNewFolder">
|
||||||
|
<a class="s-button icon-folder-new" ng-click="createNewFolderClickHandler()" >
|
||||||
|
<span class="title-label">New Folder</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div ng-if="createNewFolder">
|
||||||
|
<span><input type="text" ng-model="newFolderName" name="newFolderName"></span>
|
||||||
|
<a class="s-button" ng-click="createClickHandler()">Create</a>
|
||||||
|
<a class="s-button icon-x" ng-click="cancelClickHandler()"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
Open MCT, Copyright (c) 2014-2017, United States Government
|
||||||
as represented by the Administrator of the National Aeronautics and Space
|
as represented by the Administrator of the National Aeronautics and Space
|
||||||
Administration. All rights reserved.
|
Administration. All rights reserved.
|
||||||
|
|
||||||
@@ -26,4 +26,22 @@
|
|||||||
ng-model="treeModel">
|
ng-model="treeModel">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Create New Folder Action -->
|
||||||
|
<div class="newFolderCreation" style="margin-top:10px; position:absolute; left:0px;">
|
||||||
|
|
||||||
|
<!-- New folder button, triggers create new folder action. -->
|
||||||
|
<div ng-show="!newFolderCreationTriggered">
|
||||||
|
<a class="s-button icon-folder-new" ng-class="{disabled: !validParent()}" ng-click="newFolderButtonClickHandler()">
|
||||||
|
<span class="text-label">New Folder</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Get folder name -->
|
||||||
|
<div ng-show="newFolderCreationTriggered">
|
||||||
|
<input type="text" ng-model="newFolderNameInput">
|
||||||
|
<a class="s-button" ng-class="{ disabled: !validParent() || !validFolderName() }" ng-click="newFolderCreateButtonClickHandler()">Create</a>
|
||||||
|
<a class="s-button icon-x" ng-click="newFolderCancelButtonClickHandler()"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
89
platform/commonUI/edit/src/actions/CreateNewFolderAction.js
Normal file
89
platform/commonUI/edit/src/actions/CreateNewFolderAction.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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 (
|
||||||
|
|
||||||
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CreateNewFolderAction; action is triggered by the new folder button in the locator.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @implements {Action}
|
||||||
|
* @memberof platform/commonUI/edit
|
||||||
|
*/
|
||||||
|
function CreateNewFolderAction(
|
||||||
|
typeService,
|
||||||
|
context
|
||||||
|
) {
|
||||||
|
this.parent = (context || {}).domainObject;
|
||||||
|
this.typeService = typeService;
|
||||||
|
this.type = typeService.getType('folder');
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateNewFolderAction.prototype.perform = function (folderName) {
|
||||||
|
var parent = this.parent,
|
||||||
|
typeService = this.typeService,
|
||||||
|
newModel = this.type.getInitialModel(),
|
||||||
|
folderType = typeService.getType('folder');
|
||||||
|
|
||||||
|
newModel.type = folderType.getKey();
|
||||||
|
newModel.name = folderName;
|
||||||
|
|
||||||
|
function instantiateObject() {
|
||||||
|
var newObject = parent.useCapability('instantiation', newModel);
|
||||||
|
newObject.useCapability('mutation', function () {
|
||||||
|
newModel.location = parent.getId();
|
||||||
|
});
|
||||||
|
return addToParentAndReturn(newObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addToParentAndReturn(newObject) {
|
||||||
|
return parent.getCapability('composition').add(newObject)
|
||||||
|
.then(function () {
|
||||||
|
return newObject;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return instantiateObject(newModel, parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this action is applicable in a given context.
|
||||||
|
* This will ensure that a domain object is present in the context,
|
||||||
|
* and that this domain object is in Edit mode.
|
||||||
|
* @returns true if applicable
|
||||||
|
*/
|
||||||
|
CreateNewFolderAction.appliesTo = function (context) {
|
||||||
|
var parent = (context || {}).domainObject;
|
||||||
|
return parent && parent.hasCapability('editor');
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return CreateNewFolderAction;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
@@ -23,111 +23,119 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining RemoveAction. Created by vwoeltje on 11/17/14.
|
* Module defining RemoveAction. Created by vwoeltje on 11/17/14.
|
||||||
*/
|
*/
|
||||||
define(
|
define([
|
||||||
[],
|
'./RemoveDialog'
|
||||||
function () {
|
], function (
|
||||||
|
RemoveDialog
|
||||||
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an action which will remove the provided object manifestation.
|
* Construct an action which will remove the provided object manifestation.
|
||||||
* The object will be removed from its parent's composition; the parent
|
* The object will be removed from its parent's composition; the parent
|
||||||
* is looked up via the "context" capability (so this will be the
|
* is looked up via the "context" capability (so this will be the
|
||||||
* immediate ancestor by which this specific object was reached.)
|
* immediate ancestor by which this specific object was reached.)
|
||||||
*
|
*
|
||||||
* @param {DomainObject} object the object to be removed
|
* @param {DialogService} dialogService a service which will show the dialog
|
||||||
* @param {ActionContext} context the context in which this action is performed
|
* @param {NavigationService} navigationService a service that maintains the current navigation state
|
||||||
* @memberof platform/commonUI/edit
|
* @param {ActionContext} context the context in which this action is performed
|
||||||
* @constructor
|
* @memberof platform/commonUI/edit
|
||||||
* @implements {Action}
|
* @constructor
|
||||||
|
* @implements {Action}
|
||||||
|
*/
|
||||||
|
function RemoveAction(dialogService, navigationService, context) {
|
||||||
|
this.domainObject = (context || {}).domainObject;
|
||||||
|
this.dialogService = dialogService;
|
||||||
|
this.navigationService = navigationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform this action.
|
||||||
|
*/
|
||||||
|
RemoveAction.prototype.perform = function () {
|
||||||
|
var dialog,
|
||||||
|
dialogService = this.dialogService,
|
||||||
|
domainObject = this.domainObject,
|
||||||
|
navigationService = this.navigationService;
|
||||||
|
/*
|
||||||
|
* Check whether an object ID matches the ID of the object being
|
||||||
|
* removed (used to filter a parent's composition to handle the
|
||||||
|
* removal.)
|
||||||
*/
|
*/
|
||||||
function RemoveAction(navigationService, context) {
|
function isNotObject(otherObjectId) {
|
||||||
this.domainObject = (context || {}).domainObject;
|
return otherObjectId !== domainObject.getId();
|
||||||
this.navigationService = navigationService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Perform this action.
|
* Mutate a parent object such that it no longer contains the object
|
||||||
* @return {Promise} a promise which will be
|
* which is being removed.
|
||||||
* fulfilled when the action has completed.
|
|
||||||
*/
|
*/
|
||||||
RemoveAction.prototype.perform = function () {
|
function doMutate(model) {
|
||||||
var navigationService = this.navigationService,
|
model.composition = model.composition.filter(isNotObject);
|
||||||
domainObject = this.domainObject;
|
}
|
||||||
/*
|
|
||||||
* Check whether an object ID matches the ID of the object being
|
|
||||||
* removed (used to filter a parent's composition to handle the
|
|
||||||
* removal.)
|
|
||||||
*/
|
|
||||||
function isNotObject(otherObjectId) {
|
|
||||||
return otherObjectId !== domainObject.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mutate a parent object such that it no longer contains the object
|
* Checks current object and ascendants of current
|
||||||
* which is being removed.
|
* object with object being removed, if the current
|
||||||
*/
|
* object or any in the current object's path is being removed,
|
||||||
function doMutate(model) {
|
* navigate back to parent of removed object.
|
||||||
model.composition = model.composition.filter(isNotObject);
|
*/
|
||||||
}
|
function checkObjectNavigation(object, parentObject) {
|
||||||
|
// Traverse object starts at current location
|
||||||
|
var traverseObject = (navigationService).getNavigation(),
|
||||||
|
context;
|
||||||
|
|
||||||
/*
|
// Stop when object is not defined (above ROOT)
|
||||||
* Checks current object and ascendants of current
|
while (traverseObject) {
|
||||||
* object with object being removed, if the current
|
// If object currently traversed to is object being removed
|
||||||
* object or any in the current object's path is being removed,
|
// navigate to parent of current object and then exit loop
|
||||||
* navigate back to parent of removed object.
|
if (traverseObject.getId() === object.getId()) {
|
||||||
*/
|
navigationService.setNavigation(parentObject);
|
||||||
function checkObjectNavigation(object, parentObject) {
|
return;
|
||||||
// Traverse object starts at current location
|
|
||||||
var traverseObject = (navigationService).getNavigation(),
|
|
||||||
context;
|
|
||||||
|
|
||||||
// Stop when object is not defined (above ROOT)
|
|
||||||
while (traverseObject) {
|
|
||||||
// If object currently traversed to is object being removed
|
|
||||||
// navigate to parent of current object and then exit loop
|
|
||||||
if (traverseObject.getId() === object.getId()) {
|
|
||||||
navigationService.setNavigation(parentObject);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Traverses to parent of current object, moving
|
|
||||||
// up the ascendant path
|
|
||||||
context = traverseObject.getCapability('context');
|
|
||||||
traverseObject = context && context.getParent();
|
|
||||||
}
|
}
|
||||||
|
// Traverses to parent of current object, moving
|
||||||
|
// up the ascendant path
|
||||||
|
context = traverseObject.getCapability('context');
|
||||||
|
traverseObject = context && context.getParent();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the object from its parent, as identified by its context
|
* Remove the object from its parent, as identified by its context
|
||||||
* capability. Based on object's location and selected object's location
|
* capability. Based on object's location and selected object's location
|
||||||
* user may be navigated to existing parent object
|
* user may be navigated to existing parent object
|
||||||
*/
|
*/
|
||||||
function removeFromContext(object) {
|
function removeFromContext(object) {
|
||||||
var contextCapability = object.getCapability('context'),
|
var contextCapability = object.getCapability('context'),
|
||||||
parent = contextCapability.getParent();
|
parent = contextCapability.getParent();
|
||||||
|
|
||||||
// If currently within path of removed object(s),
|
// If currently within path of removed object(s),
|
||||||
// navigates to existing object up tree
|
// navigates to existing object up tree
|
||||||
checkObjectNavigation(object, parent);
|
checkObjectNavigation(object, parent);
|
||||||
|
|
||||||
return parent.useCapability('mutation', doMutate);
|
return parent.useCapability('mutation', doMutate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return removeFromContext(domainObject);
|
/*
|
||||||
};
|
* Pass in the function to remove the domain object so it can be
|
||||||
|
* associated with an 'OK' button press
|
||||||
|
*/
|
||||||
|
dialog = new RemoveDialog(dialogService, domainObject, removeFromContext);
|
||||||
|
dialog.show();
|
||||||
|
};
|
||||||
|
|
||||||
// Object needs to have a parent for Remove to be applicable
|
// Object needs to have a parent for Remove to be applicable
|
||||||
RemoveAction.appliesTo = function (context) {
|
RemoveAction.appliesTo = function (context) {
|
||||||
var object = (context || {}).domainObject,
|
var object = (context || {}).domainObject,
|
||||||
contextCapability = object && object.getCapability("context"),
|
contextCapability = object && object.getCapability("context"),
|
||||||
parent = contextCapability && contextCapability.getParent(),
|
parent = contextCapability && contextCapability.getParent(),
|
||||||
parentType = parent && parent.getCapability('type'),
|
parentType = parent && parent.getCapability('type'),
|
||||||
parentCreatable = parentType && parentType.hasFeature('creation');
|
parentCreatable = parentType && parentType.hasFeature('creation');
|
||||||
|
|
||||||
// Only creatable types should be modifiable
|
// Only creatable types should be modifiable
|
||||||
return parent !== undefined &&
|
return parent !== undefined &&
|
||||||
Array.isArray(parent.getModel().composition) &&
|
Array.isArray(parent.getModel().composition) &&
|
||||||
parentCreatable;
|
parentCreatable;
|
||||||
};
|
};
|
||||||
|
|
||||||
return RemoveAction;
|
return RemoveAction;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|||||||
77
platform/commonUI/edit/src/actions/RemoveDialog.js
Normal file
77
platform/commonUI/edit/src/actions/RemoveDialog.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2017, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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 () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @callback removeCallback
|
||||||
|
* @param {DomainObject} domainObject the domain object to be removed
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new Remove dialog.
|
||||||
|
*
|
||||||
|
* @param {DialogService} dialogService the service that shows the dialog
|
||||||
|
* @param {DomainObject} domainObject the domain object to be removed
|
||||||
|
* @param {removeCallback} removeCallback callback that handles removal of the domain object
|
||||||
|
* @memberof platform/commonUI/edit
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function RemoveDialog(dialogService, domainObject, removeCallback) {
|
||||||
|
this.dialogService = dialogService;
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.removeCallback = removeCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a dialog to confirm the removal of a domain object.
|
||||||
|
*/
|
||||||
|
RemoveDialog.prototype.show = function () {
|
||||||
|
var dialog,
|
||||||
|
domainObject = this.domainObject,
|
||||||
|
removeCallback = this.removeCallback,
|
||||||
|
model = {
|
||||||
|
title: 'Remove ' + domainObject.getModel().name,
|
||||||
|
actionText: 'Warning! This action will permanently remove this object. Are you sure you want to continue?',
|
||||||
|
severity: 'alert',
|
||||||
|
primaryOption: {
|
||||||
|
label: 'OK',
|
||||||
|
callback: function () {
|
||||||
|
removeCallback(domainObject);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Cancel',
|
||||||
|
callback: function () {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog = this.dialogService.showBlockingMessage(model);
|
||||||
|
};
|
||||||
|
|
||||||
|
return RemoveDialog;
|
||||||
|
});
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
* Open MCT, Copyright (c) 2014-2017, United States Government
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
* Administration. All rights reserved.
|
* Administration. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -31,7 +31,7 @@ define(
|
|||||||
* @memberof platform/commonUI/browse
|
* @memberof platform/commonUI/browse
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function LocatorController($scope, $timeout, objectService) {
|
function LocatorController($scope, $timeout, objectService, typeService, policyService, instantiate) {
|
||||||
// Populate values needed by the locator control. These are:
|
// Populate values needed by the locator control. These are:
|
||||||
// * rootObject: The top-level object, since we want to show
|
// * rootObject: The top-level object, since we want to show
|
||||||
// the full tree
|
// the full tree
|
||||||
@@ -66,8 +66,8 @@ define(
|
|||||||
|
|
||||||
// Restrict which locations can be selected
|
// Restrict which locations can be selected
|
||||||
if (domainObject &&
|
if (domainObject &&
|
||||||
$scope.structure &&
|
$scope.structure &&
|
||||||
$scope.structure.validate) {
|
$scope.structure.validate) {
|
||||||
if (!$scope.structure.validate(domainObject)) {
|
if (!$scope.structure.validate(domainObject)) {
|
||||||
setLocatingObject(priorObject, undefined);
|
setLocatingObject(priorObject, undefined);
|
||||||
return;
|
return;
|
||||||
@@ -81,11 +81,64 @@ define(
|
|||||||
!!$scope.treeModel.selectedObject
|
!!$scope.treeModel.selectedObject
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if create new folder is a valid action for selected object
|
||||||
|
$scope.validParent = function () {
|
||||||
|
if ($scope.treeModel.selectedObject) {
|
||||||
|
return policyService.allow(
|
||||||
|
"composition",
|
||||||
|
$scope.treeModel.selectedObject,
|
||||||
|
instantiate(typeService.getType('folder').getInitialModel())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.newFolderButtonClickHandler = function () {
|
||||||
|
$scope.newFolderCreationTriggered = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.newFolderCancelButtonClickHandler = function () {
|
||||||
|
$scope.newFolderCreationTriggered = false;
|
||||||
|
resetNewFolderNameInput();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get expected input pattern for folder name
|
||||||
|
var folderNamePattern = new RegExp(
|
||||||
|
typeService.getType('folder').getProperties()[0].propertyDefinition.pattern
|
||||||
|
);
|
||||||
|
|
||||||
|
// Validate folder name externally to avoid affecting overall form validation
|
||||||
|
$scope.validFolderName = function () {
|
||||||
|
return $scope.newFolderNameInput && folderNamePattern.test($scope.newFolderNameInput);
|
||||||
|
};
|
||||||
|
|
||||||
|
function selectAndScrollToNewFolder(newFolder) {
|
||||||
|
$scope.treeModel.selectedObject = newFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetNewFolderNameInput() {
|
||||||
|
$scope.newFolderNameInput = "Unnamed Folder";
|
||||||
|
$scope.newFolderCreationTriggered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create new folder, update selection to new folder and reset new folder button
|
||||||
|
$scope.newFolderCreateButtonClickHandler = function () {
|
||||||
|
var createNewFolderAction = $scope.treeModel.selectedObject.getCapability('action').getActions('create-new-folder')[0];
|
||||||
|
createNewFolderAction.perform($scope.newFolderNameInput)
|
||||||
|
.then(selectAndScrollToNewFolder)
|
||||||
|
.then(resetNewFolderNameInput);
|
||||||
|
};
|
||||||
|
|
||||||
// Initial state for the tree's model
|
// Initial state for the tree's model
|
||||||
$scope.treeModel =
|
$scope.treeModel = { selectedObject: $scope.ngModel[$scope.field] };
|
||||||
{ selectedObject: $scope.ngModel[$scope.field] };
|
|
||||||
|
//Initial values for new folder action
|
||||||
|
$scope.newFolderNameInput = "Unnamed Folder";
|
||||||
|
$scope.newFolderCreationTriggered = false;
|
||||||
|
|
||||||
// Watch for changes from the tree
|
// Watch for changes from the tree
|
||||||
$scope.$watch("treeModel.selectedObject", setLocatingObject);
|
$scope.$watch("treeModel.selectedObject", setLocatingObject);
|
||||||
|
|||||||
117
platform/commonUI/edit/test/actions/CreateNewFolderActionSpec.js
Normal file
117
platform/commonUI/edit/test/actions/CreateNewFolderActionSpec.js
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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/actions/CreateNewFolderAction'],
|
||||||
|
function (CreateNewFolderAction) {
|
||||||
|
|
||||||
|
describe("The Create New Folder Action", function () {
|
||||||
|
var mockDomainObject,
|
||||||
|
mockNewObject,
|
||||||
|
mockType,
|
||||||
|
testModel,
|
||||||
|
mockFolderName,
|
||||||
|
mockTypeService,
|
||||||
|
mockActionContext,
|
||||||
|
mockCompositionCapability,
|
||||||
|
action;
|
||||||
|
function mockPromise(value) {
|
||||||
|
return (value && value.then) ? value : {
|
||||||
|
then: function (callback) {
|
||||||
|
return mockPromise(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[
|
||||||
|
"getCapability",
|
||||||
|
"useCapability",
|
||||||
|
"hasCapability",
|
||||||
|
"getId"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockNewObject = jasmine.createSpyObj(
|
||||||
|
"newObject",
|
||||||
|
[
|
||||||
|
"getCapability",
|
||||||
|
"useCapability",
|
||||||
|
"hasCapability",
|
||||||
|
"getId"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockType = jasmine.createSpyObj(
|
||||||
|
"type",
|
||||||
|
[
|
||||||
|
"getKey",
|
||||||
|
"getInitialModel"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
testModel = {
|
||||||
|
type: mockType,
|
||||||
|
name: "Name",
|
||||||
|
location: "someLocation"
|
||||||
|
};
|
||||||
|
mockFolderName = "Name";
|
||||||
|
mockTypeService = jasmine.createSpyObj(
|
||||||
|
"typeService",
|
||||||
|
["getType"]
|
||||||
|
);
|
||||||
|
mockActionContext = { domainObject: mockDomainObject };
|
||||||
|
mockCompositionCapability = jasmine.createSpyObj(
|
||||||
|
"composition",
|
||||||
|
["add"]
|
||||||
|
);
|
||||||
|
mockType.getKey.and.returnValue("test");
|
||||||
|
mockType.getInitialModel.and.returnValue(testModel);
|
||||||
|
mockDomainObject.getCapability.and.callFake(function (capability) {
|
||||||
|
return (capability === 'composition') && mockCompositionCapability;
|
||||||
|
});
|
||||||
|
mockDomainObject.hasCapability.and.returnValue(true);
|
||||||
|
mockCompositionCapability.add.and.returnValue(mockPromise(true));
|
||||||
|
mockDomainObject.useCapability.and.callFake(function (capability) {
|
||||||
|
return (capability === 'instantiation') && mockNewObject;
|
||||||
|
});
|
||||||
|
mockTypeService.getType.and.returnValue(mockType);
|
||||||
|
mockDomainObject.getId.and.returnValue("id");
|
||||||
|
action = new CreateNewFolderAction(mockTypeService, mockActionContext);
|
||||||
|
});
|
||||||
|
it("uses the instantiation capability when performed", function () {
|
||||||
|
action.perform(mockFolderName);
|
||||||
|
expect(mockDomainObject.useCapability)
|
||||||
|
.toHaveBeenCalledWith("instantiation", jasmine.any(Object));
|
||||||
|
});
|
||||||
|
it("adds new objects to the parent's composition", function () {
|
||||||
|
action.perform(mockFolderName);
|
||||||
|
expect(mockDomainObject.getCapability).toHaveBeenCalledWith("composition");
|
||||||
|
expect(mockCompositionCapability.add).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
it("is only applicable when a domain object is in context", function () {
|
||||||
|
expect(CreateNewFolderAction.appliesTo(mockActionContext)).toBeTruthy();
|
||||||
|
expect(CreateNewFolderAction.appliesTo({})).toBeFalsy();
|
||||||
|
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith('editor');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
@@ -25,50 +25,37 @@ define(
|
|||||||
function (RemoveAction) {
|
function (RemoveAction) {
|
||||||
|
|
||||||
describe("The Remove action", function () {
|
describe("The Remove action", function () {
|
||||||
var mockQ,
|
var action,
|
||||||
mockNavigationService,
|
|
||||||
mockDomainObject,
|
|
||||||
mockParent,
|
|
||||||
mockChildObject,
|
|
||||||
mockGrandchildObject,
|
|
||||||
mockRootObject,
|
|
||||||
mockContext,
|
|
||||||
mockChildContext,
|
|
||||||
mockGrandchildContext,
|
|
||||||
mockRootContext,
|
|
||||||
mockMutation,
|
|
||||||
mockType,
|
|
||||||
actionContext,
|
actionContext,
|
||||||
model,
|
|
||||||
capabilities,
|
capabilities,
|
||||||
action;
|
mockContext,
|
||||||
|
mockDialogService,
|
||||||
function mockPromise(value) {
|
mockDomainObject,
|
||||||
return {
|
mockMutation,
|
||||||
then: function (callback) {
|
mockNavigationService,
|
||||||
return mockPromise(callback(value));
|
mockParent,
|
||||||
}
|
mockType,
|
||||||
};
|
model;
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
"domainObject",
|
"domainObject",
|
||||||
["getId", "getCapability"]
|
["getId", "getCapability", "getModel"]
|
||||||
);
|
);
|
||||||
mockChildObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
mockMutation = jasmine.createSpyObj("mutation", ["invoke"]);
|
||||||
["getId", "getCapability"]
|
mockType = jasmine.createSpyObj("type", ["hasFeature"]);
|
||||||
);
|
mockType.hasFeature.and.returnValue(true);
|
||||||
mockGrandchildObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
capabilities = {
|
||||||
["getId", "getCapability"]
|
mutation: mockMutation,
|
||||||
);
|
type: mockType
|
||||||
mockRootObject = jasmine.createSpyObj(
|
};
|
||||||
"domainObject",
|
|
||||||
["getId", "getCapability"]
|
model = {
|
||||||
);
|
composition: ["a", "test", "b"]
|
||||||
mockQ = { when: mockPromise };
|
};
|
||||||
|
|
||||||
mockParent = {
|
mockParent = {
|
||||||
getModel: function () {
|
getModel: function () {
|
||||||
return model;
|
return model;
|
||||||
@@ -80,12 +67,12 @@ define(
|
|||||||
return capabilities[k].invoke(v);
|
return capabilities[k].invoke(v);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mockContext = jasmine.createSpyObj("context", ["getParent"]);
|
|
||||||
mockChildContext = jasmine.createSpyObj("context", ["getParent"]);
|
mockDialogService = jasmine.createSpyObj(
|
||||||
mockGrandchildContext = jasmine.createSpyObj("context", ["getParent"]);
|
"dialogService",
|
||||||
mockRootContext = jasmine.createSpyObj("context", ["getParent"]);
|
["showBlockingMessage"]
|
||||||
mockMutation = jasmine.createSpyObj("mutation", ["invoke"]);
|
);
|
||||||
mockType = jasmine.createSpyObj("type", ["hasFeature"]);
|
|
||||||
mockNavigationService = jasmine.createSpyObj(
|
mockNavigationService = jasmine.createSpyObj(
|
||||||
"navigationService",
|
"navigationService",
|
||||||
[
|
[
|
||||||
@@ -97,23 +84,19 @@ define(
|
|||||||
);
|
);
|
||||||
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
|
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
|
||||||
|
|
||||||
|
mockContext = jasmine.createSpyObj("context", ["getParent"]);
|
||||||
|
mockContext.getParent.and.returnValue(mockParent);
|
||||||
|
|
||||||
mockDomainObject.getId.and.returnValue("test");
|
mockDomainObject.getId.and.returnValue("test");
|
||||||
mockDomainObject.getCapability.and.returnValue(mockContext);
|
mockDomainObject.getCapability.and.returnValue(mockContext);
|
||||||
|
mockDomainObject.getModel.and.returnValue({name: 'test object'});
|
||||||
|
|
||||||
mockContext.getParent.and.returnValue(mockParent);
|
mockContext.getParent.and.returnValue(mockParent);
|
||||||
mockType.hasFeature.and.returnValue(true);
|
mockType.hasFeature.and.returnValue(true);
|
||||||
|
|
||||||
capabilities = {
|
|
||||||
mutation: mockMutation,
|
|
||||||
type: mockType
|
|
||||||
};
|
|
||||||
model = {
|
|
||||||
composition: ["a", "test", "b"]
|
|
||||||
};
|
|
||||||
|
|
||||||
actionContext = { domainObject: mockDomainObject };
|
actionContext = { domainObject: mockDomainObject };
|
||||||
|
|
||||||
action = new RemoveAction(mockNavigationService, actionContext);
|
action = new RemoveAction(mockDialogService, mockNavigationService, actionContext);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("only applies to objects with parents", function () {
|
it("only applies to objects with parents", function () {
|
||||||
@@ -127,83 +110,146 @@ define(
|
|||||||
expect(mockType.hasFeature).toHaveBeenCalledWith('creation');
|
expect(mockType.hasFeature).toHaveBeenCalledWith('creation');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("mutates the parent when performed", function () {
|
it("shows a blocking message dialog", function () {
|
||||||
action.perform();
|
mockParent = jasmine.createSpyObj(
|
||||||
expect(mockMutation.invoke)
|
"parent",
|
||||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
["getModel", "getCapability", "useCapability"]
|
||||||
});
|
);
|
||||||
|
|
||||||
it("changes composition from its mutation function", function () {
|
|
||||||
var mutator, result;
|
|
||||||
action.perform();
|
|
||||||
mutator = mockMutation.invoke.calls.mostRecent().args[0];
|
|
||||||
result = mutator(model);
|
|
||||||
|
|
||||||
// Should not have cancelled the mutation
|
|
||||||
expect(result).not.toBe(false);
|
|
||||||
|
|
||||||
// Simulate mutate's behavior (remove can either return a
|
|
||||||
// new model or modify this one in-place)
|
|
||||||
result = result || model;
|
|
||||||
|
|
||||||
// Should have removed "test" - that was our
|
|
||||||
// mock domain object's id.
|
|
||||||
expect(result.composition).toEqual(["a", "b"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("removes parent of object currently navigated to", function () {
|
|
||||||
// Navigates to child object
|
|
||||||
mockNavigationService.getNavigation.and.returnValue(mockChildObject);
|
|
||||||
|
|
||||||
// Test is id of object being removed
|
|
||||||
// Child object has different id
|
|
||||||
mockDomainObject.getId.and.returnValue("test");
|
|
||||||
mockChildObject.getId.and.returnValue("not test");
|
|
||||||
|
|
||||||
// Sets context for the child and domainObject
|
|
||||||
mockDomainObject.getCapability.and.returnValue(mockContext);
|
|
||||||
mockChildObject.getCapability.and.returnValue(mockChildContext);
|
|
||||||
|
|
||||||
// Parents of child and domainObject are set
|
|
||||||
mockContext.getParent.and.returnValue(mockParent);
|
|
||||||
mockChildContext.getParent.and.returnValue(mockDomainObject);
|
|
||||||
|
|
||||||
mockType.hasFeature.and.returnValue(true);
|
|
||||||
|
|
||||||
action.perform();
|
action.perform();
|
||||||
|
|
||||||
// Expects navigation to parent of domainObject (removed object)
|
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
|
||||||
expect(mockNavigationService.setNavigation).toHaveBeenCalledWith(mockParent);
|
|
||||||
|
// Also check that no mutation happens at this point
|
||||||
|
expect(mockParent.useCapability).not.toHaveBeenCalledWith("mutation", jasmine.any(Function));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("checks if removing object not in ascendent path (reaches ROOT)", function () {
|
describe("after the remove callback is triggered", function () {
|
||||||
// Navigates to grandchild of ROOT
|
var mockChildContext,
|
||||||
mockNavigationService.getNavigation.and.returnValue(mockGrandchildObject);
|
mockChildObject,
|
||||||
|
mockDialogHandle,
|
||||||
|
mockGrandchildContext,
|
||||||
|
mockGrandchildObject,
|
||||||
|
mockRootContext,
|
||||||
|
mockRootObject;
|
||||||
|
|
||||||
// domainObject (grandparent) is set as ROOT, child and grandchild
|
beforeEach(function () {
|
||||||
// are set objects not being removed
|
mockChildObject = jasmine.createSpyObj(
|
||||||
mockDomainObject.getId.and.returnValue("test 1");
|
"domainObject",
|
||||||
mockRootObject.getId.and.returnValue("ROOT");
|
["getId", "getCapability"]
|
||||||
mockChildObject.getId.and.returnValue("not test 2");
|
);
|
||||||
mockGrandchildObject.getId.and.returnValue("not test 3");
|
|
||||||
|
|
||||||
// Sets context for the grandchild, child, and domainObject
|
mockDialogHandle = jasmine.createSpyObj(
|
||||||
mockRootObject.getCapability.and.returnValue(mockRootContext);
|
"dialogHandle",
|
||||||
mockChildObject.getCapability.and.returnValue(mockChildContext);
|
["dismiss"]
|
||||||
mockGrandchildObject.getCapability.and.returnValue(mockGrandchildContext);
|
);
|
||||||
|
|
||||||
// Parents of grandchild and child are set
|
mockGrandchildObject = jasmine.createSpyObj(
|
||||||
mockChildContext.getParent.and.returnValue(mockRootObject);
|
"domainObject",
|
||||||
mockGrandchildContext.getParent.and.returnValue(mockChildObject);
|
["getId", "getCapability"]
|
||||||
|
);
|
||||||
|
|
||||||
mockType.hasFeature.and.returnValue(true);
|
mockRootObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
["getId", "getCapability"]
|
||||||
|
);
|
||||||
|
|
||||||
action.perform();
|
mockChildContext = jasmine.createSpyObj("context", ["getParent"]);
|
||||||
|
mockGrandchildContext = jasmine.createSpyObj("context", ["getParent"]);
|
||||||
|
mockRootContext = jasmine.createSpyObj("context", ["getParent"]);
|
||||||
|
|
||||||
|
mockDialogService.showBlockingMessage.and.returnValue(mockDialogHandle);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("mutates the parent when performed", function () {
|
||||||
|
action.perform();
|
||||||
|
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
|
||||||
|
.primaryOption.callback();
|
||||||
|
|
||||||
|
expect(mockMutation.invoke)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("changes composition from its mutation function", function () {
|
||||||
|
var mutator, result;
|
||||||
|
|
||||||
|
action.perform();
|
||||||
|
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
|
||||||
|
.primaryOption.callback();
|
||||||
|
|
||||||
|
mutator = mockMutation.invoke.calls.mostRecent().args[0];
|
||||||
|
result = mutator(model);
|
||||||
|
|
||||||
|
// Should not have cancelled the mutation
|
||||||
|
expect(result).not.toBe(false);
|
||||||
|
|
||||||
|
// Simulate mutate's behavior (remove can either return a
|
||||||
|
// new model or modify this one in-place)
|
||||||
|
result = result || model;
|
||||||
|
|
||||||
|
// Should have removed "test" - that was our
|
||||||
|
// mock domain object's id.
|
||||||
|
expect(result.composition).toEqual(["a", "b"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes parent of object currently navigated to", function () {
|
||||||
|
// Navigates to child object
|
||||||
|
mockNavigationService.getNavigation.and.returnValue(mockChildObject);
|
||||||
|
|
||||||
|
// Test is id of object being removed
|
||||||
|
// Child object has different id
|
||||||
|
mockDomainObject.getId.and.returnValue("test");
|
||||||
|
mockChildObject.getId.and.returnValue("not test");
|
||||||
|
|
||||||
|
// Sets context for the child and domainObject
|
||||||
|
mockDomainObject.getCapability.and.returnValue(mockContext);
|
||||||
|
mockChildObject.getCapability.and.returnValue(mockChildContext);
|
||||||
|
|
||||||
|
// Parents of child and domainObject are set
|
||||||
|
mockContext.getParent.and.returnValue(mockParent);
|
||||||
|
mockChildContext.getParent.and.returnValue(mockDomainObject);
|
||||||
|
|
||||||
|
mockType.hasFeature.and.returnValue(true);
|
||||||
|
|
||||||
|
action.perform();
|
||||||
|
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
|
||||||
|
.primaryOption.callback();
|
||||||
|
|
||||||
|
// Expects navigation to parent of domainObject (removed object)
|
||||||
|
expect(mockNavigationService.setNavigation).toHaveBeenCalledWith(mockParent);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("checks if removing object not in ascendent path (reaches ROOT)", function () {
|
||||||
|
// Navigates to grandchild of ROOT
|
||||||
|
mockNavigationService.getNavigation.and.returnValue(mockGrandchildObject);
|
||||||
|
|
||||||
|
// domainObject (grandparent) is set as ROOT, child and grandchild
|
||||||
|
// are set objects not being removed
|
||||||
|
mockDomainObject.getId.and.returnValue("test 1");
|
||||||
|
mockRootObject.getId.and.returnValue("ROOT");
|
||||||
|
mockChildObject.getId.and.returnValue("not test 2");
|
||||||
|
mockGrandchildObject.getId.and.returnValue("not test 3");
|
||||||
|
|
||||||
|
// Sets context for the grandchild, child, and domainObject
|
||||||
|
mockRootObject.getCapability.and.returnValue(mockRootContext);
|
||||||
|
mockChildObject.getCapability.and.returnValue(mockChildContext);
|
||||||
|
mockGrandchildObject.getCapability.and.returnValue(mockGrandchildContext);
|
||||||
|
|
||||||
|
// Parents of grandchild and child are set
|
||||||
|
mockChildContext.getParent.and.returnValue(mockRootObject);
|
||||||
|
mockGrandchildContext.getParent.and.returnValue(mockChildObject);
|
||||||
|
|
||||||
|
mockType.hasFeature.and.returnValue(true);
|
||||||
|
|
||||||
|
action.perform();
|
||||||
|
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
|
||||||
|
.primaryOption.callback();
|
||||||
|
|
||||||
|
// Expects no navigation to occur
|
||||||
|
expect(mockNavigationService.setNavigation).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
// Expects no navigation to occur
|
|
||||||
expect(mockNavigationService.setNavigation).not.toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,26 +31,63 @@ define(
|
|||||||
var mockScope,
|
var mockScope,
|
||||||
mockTimeout,
|
mockTimeout,
|
||||||
mockDomainObject,
|
mockDomainObject,
|
||||||
|
mockFolderObject,
|
||||||
mockRootObject,
|
mockRootObject,
|
||||||
mockContext,
|
mockContext,
|
||||||
|
mockActions,
|
||||||
mockObjectService,
|
mockObjectService,
|
||||||
|
mockTypeService,
|
||||||
|
mockType,
|
||||||
|
mockInstantiate,
|
||||||
|
mockPolicyService,
|
||||||
getObjectsPromise,
|
getObjectsPromise,
|
||||||
|
testModel,
|
||||||
|
capabilities,
|
||||||
|
mockCreateNewFolderAction,
|
||||||
|
mockActionCapability,
|
||||||
|
mockProperties,
|
||||||
controller;
|
controller;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockScope = jasmine.createSpyObj(
|
mockScope = jasmine.createSpyObj(
|
||||||
"$scope",
|
"$scope",
|
||||||
["$watch"]
|
["$watch", "validParent"]
|
||||||
);
|
);
|
||||||
mockTimeout = jasmine.createSpy("$timeout");
|
mockTimeout = jasmine.createSpy("$timeout");
|
||||||
|
mockInstantiate = jasmine.createSpy("instantiate");
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
"domainObject",
|
"domainObject",
|
||||||
["getCapability"]
|
[
|
||||||
|
"useCapability",
|
||||||
|
"getModel",
|
||||||
|
"getCapability"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockFolderObject = jasmine.createSpyObj(
|
||||||
|
"folderObject",
|
||||||
|
[
|
||||||
|
"useCapability",
|
||||||
|
"getModel",
|
||||||
|
"getCapability"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockCreateNewFolderAction = jasmine.createSpyObj(
|
||||||
|
"createNewFolderAction",
|
||||||
|
[
|
||||||
|
"perform"
|
||||||
|
]
|
||||||
);
|
);
|
||||||
mockRootObject = jasmine.createSpyObj(
|
mockRootObject = jasmine.createSpyObj(
|
||||||
"rootObject",
|
"rootObject",
|
||||||
["getCapability"]
|
["getCapability"]
|
||||||
);
|
);
|
||||||
|
mockActionCapability = jasmine.createSpyObj(
|
||||||
|
"actionCapability",
|
||||||
|
[
|
||||||
|
"getActions",
|
||||||
|
"perform"
|
||||||
|
]
|
||||||
|
);
|
||||||
mockContext = jasmine.createSpyObj(
|
mockContext = jasmine.createSpyObj(
|
||||||
"context",
|
"context",
|
||||||
["getRoot"]
|
["getRoot"]
|
||||||
@@ -59,25 +96,70 @@ define(
|
|||||||
"objectService",
|
"objectService",
|
||||||
["getObjects"]
|
["getObjects"]
|
||||||
);
|
);
|
||||||
|
mockTypeService = jasmine.createSpyObj(
|
||||||
|
"typeService",
|
||||||
|
["getType"]
|
||||||
|
);
|
||||||
|
mockPolicyService = jasmine.createSpyObj(
|
||||||
|
"policyService",
|
||||||
|
["allow"]
|
||||||
|
);
|
||||||
getObjectsPromise = jasmine.createSpyObj(
|
getObjectsPromise = jasmine.createSpyObj(
|
||||||
"promise",
|
"promise",
|
||||||
["then"]
|
["then"]
|
||||||
);
|
);
|
||||||
|
mockType = jasmine.createSpyObj(
|
||||||
mockDomainObject.getCapability.and.returnValue(mockContext);
|
"type",
|
||||||
|
[
|
||||||
|
"getKey",
|
||||||
|
"getProperties",
|
||||||
|
"getInitialModel"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
testModel = { someKey: "some value" };
|
||||||
|
mockProperties = ['a', 'b', 'c'].map(function (k) {
|
||||||
|
var mockProperty = jasmine.createSpyObj(
|
||||||
|
'property-' + k,
|
||||||
|
['propertyDefinition']
|
||||||
|
);
|
||||||
|
mockProperty.propertyDefinition = {
|
||||||
|
key: "name",
|
||||||
|
pattern: "test"
|
||||||
|
};
|
||||||
|
return mockProperty;
|
||||||
|
});
|
||||||
|
capabilities = {
|
||||||
|
"action" : mockActionCapability,
|
||||||
|
"context": mockContext
|
||||||
|
};
|
||||||
|
mockActions = [mockCreateNewFolderAction];
|
||||||
mockContext.getRoot.and.returnValue(mockRootObject);
|
mockContext.getRoot.and.returnValue(mockRootObject);
|
||||||
mockObjectService.getObjects.and.returnValue(getObjectsPromise);
|
mockObjectService.getObjects.and.returnValue(getObjectsPromise);
|
||||||
|
mockTypeService.getType.and.callFake(function (typename) {
|
||||||
|
return mockType;
|
||||||
|
});
|
||||||
|
mockInstantiate.and.returnValue(mockFolderObject);
|
||||||
|
mockType.getKey.and.returnValue("test");
|
||||||
|
mockType.getInitialModel.and.returnValue(testModel);
|
||||||
|
mockType.getProperties.and.returnValue(mockProperties);
|
||||||
|
mockDomainObject.getCapability.and.callFake(function (capability) {
|
||||||
|
return capabilities[capability];
|
||||||
|
});
|
||||||
|
mockDomainObject.useCapability.and.returnValue();
|
||||||
|
mockDomainObject.getModel.and.returnValue(testModel);
|
||||||
|
mockFolderObject.getCapability.and.returnValue(capabilities);
|
||||||
|
mockFolderObject.useCapability.and.returnValue();
|
||||||
|
mockFolderObject.getModel.and.returnValue(testModel);
|
||||||
mockScope.ngModel = {};
|
mockScope.ngModel = {};
|
||||||
mockScope.field = "someField";
|
mockScope.field = "someField";
|
||||||
|
|
||||||
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
|
controller = new LocatorController(mockScope, mockTimeout, mockObjectService, mockTypeService, mockPolicyService, mockInstantiate);
|
||||||
});
|
});
|
||||||
describe("when context is available", function () {
|
describe("when context is available", function () {
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockContext.getRoot.and.returnValue(mockRootObject);
|
mockContext.getRoot.and.returnValue(mockRootObject);
|
||||||
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
|
controller = new LocatorController(mockScope, mockTimeout, mockObjectService, mockTypeService, mockPolicyService, mockInstantiate);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("adds a treeModel to scope", function () {
|
it("adds a treeModel to scope", function () {
|
||||||
@@ -145,7 +227,7 @@ define(
|
|||||||
getObjectsPromise.then.and.callFake(function (callback) {
|
getObjectsPromise.then.and.callFake(function (callback) {
|
||||||
callback({'ROOT': defaultRoot});
|
callback({'ROOT': defaultRoot});
|
||||||
});
|
});
|
||||||
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
|
controller = new LocatorController(mockScope, mockTimeout, mockObjectService, mockTypeService, mockPolicyService, mockInstantiate);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("provides a default context where none is available", function () {
|
it("provides a default context where none is available", function () {
|
||||||
@@ -169,3 +251,4 @@ define(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ define([
|
|||||||
|
|
||||||
this.listenTo(this, 'change:xKey', this.onXKeyChange, this);
|
this.listenTo(this, 'change:xKey', this.onXKeyChange, this);
|
||||||
this.listenTo(this, 'change:yKey', this.onYKeyChange, this);
|
this.listenTo(this, 'change:yKey', this.onYKeyChange, this);
|
||||||
|
this.persistedConfig = options.persistedConfig;
|
||||||
|
|
||||||
Model.apply(this, arguments);
|
Model.apply(this, arguments);
|
||||||
this.onXKeyChange(this.get('xKey'));
|
this.onXKeyChange(this.get('xKey'));
|
||||||
@@ -176,8 +177,7 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var valueMetadata = this.metadata.value(newKey);
|
var valueMetadata = this.metadata.value(newKey);
|
||||||
var persistedConfig = this.get('persistedConfiguration');
|
if (!this.persistedConfig || !this.persistedConfig.interpolate) {
|
||||||
if (!persistedConfig || !persistedConfig.interpolate) {
|
|
||||||
if (valueMetadata.format === 'enum') {
|
if (valueMetadata.format === 'enum') {
|
||||||
this.set('interpolate', 'stepAfter');
|
this.set('interpolate', 'stepAfter');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ define([
|
|||||||
domainObject.configuration.series.forEach(function (seriesConfig) {
|
domainObject.configuration.series.forEach(function (seriesConfig) {
|
||||||
var series = this.byIdentifier(seriesConfig.identifier);
|
var series = this.byIdentifier(seriesConfig.identifier);
|
||||||
if (series) {
|
if (series) {
|
||||||
series.set('persistedConfiguration', seriesConfig);
|
series.persistedConfig = seriesConfig;
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
@@ -90,7 +90,9 @@ define([
|
|||||||
model: seriesConfig,
|
model: seriesConfig,
|
||||||
domainObject: domainObject,
|
domainObject: domainObject,
|
||||||
collection: this,
|
collection: this,
|
||||||
openmct: this.openmct
|
openmct: this.openmct,
|
||||||
|
persistedConfig: this.plot
|
||||||
|
.getPersistedSeriesConfig(domainObject.identifier)
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
removeTelemetryObject: function (identifier) {
|
removeTelemetryObject: function (identifier) {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ define([
|
|||||||
|
|
||||||
PlotOptionsController.prototype.updateDomainObject = function (domainObject) {
|
PlotOptionsController.prototype.updateDomainObject = function (domainObject) {
|
||||||
this.domainObject = domainObject;
|
this.domainObject = domainObject;
|
||||||
|
this.$scope.formDomainObject = domainObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
PlotOptionsController.prototype.destroy = function () {
|
PlotOptionsController.prototype.destroy = function () {
|
||||||
@@ -63,8 +64,7 @@ define([
|
|||||||
this.config = this.$scope.config = config;
|
this.config = this.$scope.config = config;
|
||||||
this.$scope.plotSeries = [];
|
this.$scope.plotSeries = [];
|
||||||
|
|
||||||
this.domainObject = this.config.get('domainObject');
|
this.updateDomainObject(this.config.get('domainObject'));
|
||||||
this.$scope.formDomainObject = this.domainObject;
|
|
||||||
this.unlisten = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject.bind(this));
|
this.unlisten = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject.bind(this));
|
||||||
|
|
||||||
this.listenTo(this.$scope, '$destroy', this.destroy, this);
|
this.listenTo(this.$scope, '$destroy', this.destroy, this);
|
||||||
|
|||||||
@@ -181,7 +181,9 @@ define([
|
|||||||
};
|
};
|
||||||
this.config.xAxis.set('range', newRange);
|
this.config.xAxis.set('range', newRange);
|
||||||
if (!isTick) {
|
if (!isTick) {
|
||||||
|
this.skipReloadOnInteraction = true;
|
||||||
this.$scope.$broadcast('plot:clearHistory');
|
this.$scope.$broadcast('plot:clearHistory');
|
||||||
|
this.skipReloadOnInteraction = false;
|
||||||
this.loadMoreData(newRange, true);
|
this.loadMoreData(newRange, true);
|
||||||
} else {
|
} else {
|
||||||
// Drop any data that is more than 1x (max-min) before min.
|
// Drop any data that is more than 1x (max-min) before min.
|
||||||
@@ -234,7 +236,9 @@ define([
|
|||||||
var xDisplayRange = this.config.xAxis.get('displayRange');
|
var xDisplayRange = this.config.xAxis.get('displayRange');
|
||||||
var xRange = this.config.xAxis.get('range');
|
var xRange = this.config.xAxis.get('range');
|
||||||
|
|
||||||
this.loadMoreData(xDisplayRange);
|
if (!this.skipReloadOnInteraction) {
|
||||||
|
this.loadMoreData(xDisplayRange);
|
||||||
|
}
|
||||||
|
|
||||||
this.synchronized(xRange.min === xDisplayRange.min &&
|
this.synchronized(xRange.min === xDisplayRange.min &&
|
||||||
xRange.max === xDisplayRange.max);
|
xRange.max === xDisplayRange.max);
|
||||||
|
|||||||
Reference in New Issue
Block a user