Compare commits
	
		
			6 Commits
		
	
	
		
			misc-ui-48
			...
			open824
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 23dbbf965c | ||
|   | a72f193e97 | ||
|   | 18e0aadfc1 | ||
|   | 64b3580cf6 | ||
|   | 08684fa14a | ||
|   | 56a5a30f56 | 
| @@ -25,11 +25,8 @@ | ||||
|  * Module defining CreateAction. Created by vwoeltje on 11/10/14. | ||||
|  */ | ||||
| define( | ||||
|     [ | ||||
|         './CreateWizard', | ||||
|         '../../../edit/src/objects/EditableDomainObject' | ||||
|     ], | ||||
|     function (CreateWizard, EditableDomainObject) { | ||||
|     [], | ||||
|     function () { | ||||
|         "use strict"; | ||||
|  | ||||
|         /** | ||||
| @@ -88,22 +85,19 @@ define( | ||||
|         CreateAction.prototype.perform = function () { | ||||
|             var newModel = this.type.getInitialModel(), | ||||
|                 parentObject = this.navigationService.getNavigation(), | ||||
|                 newObject, | ||||
|                 editableObject; | ||||
|                 newObject; | ||||
|  | ||||
|             newModel.type = this.type.getKey(); | ||||
|             newObject = parentObject.useCapability('instantiation', newModel); | ||||
|             editableObject = new EditableDomainObject(newObject, this.$q); | ||||
|             editableObject.setOriginalObject(parentObject); | ||||
|             editableObject.getCapability('status').set('editing', true); | ||||
|             editableObject.useCapability('mutation', function(model){ | ||||
|             newObject.useCapability('mutation', function(model){ | ||||
|                 model.location = parentObject.getId(); | ||||
|             }); | ||||
|  | ||||
|             if (countEditableViews(editableObject) > 0 && editableObject.hasCapability('composition')) { | ||||
|                 this.navigationService.setNavigation(editableObject); | ||||
|             if (countEditableViews(newObject) > 0 && newObject.hasCapability('composition')) { | ||||
|                 this.navigationService.setNavigation(newObject); | ||||
|                 newObject.getCapability("action").perform("edit"); | ||||
|             } else { | ||||
|                 return editableObject.getCapability('action').perform('save'); | ||||
|                 return newObject.getCapability('action').perform('save'); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|   | ||||
| @@ -40,6 +40,10 @@ define([ | ||||
|     "./src/policies/EditContextualActionPolicy", | ||||
|     "./src/representers/EditRepresenter", | ||||
|     "./src/representers/EditToolbarRepresenter", | ||||
|     "./src/capabilities/EditorCapability", | ||||
|     "./src/capabilities/TransactionDecorator", | ||||
|     "./src/services/TransactionService", | ||||
|     "./src/services/DirtyModelCache", | ||||
|     "text!./res/templates/library.html", | ||||
|     "text!./res/templates/edit-object.html", | ||||
|     "text!./res/templates/edit-action-buttons.html", | ||||
| @@ -65,6 +69,10 @@ define([ | ||||
|     EditContextualActionPolicy, | ||||
|     EditRepresenter, | ||||
|     EditToolbarRepresenter, | ||||
|     EditorCapability, | ||||
|     TransactionDecorator, | ||||
|     TransactionService, | ||||
|     DirtyModelCache, | ||||
|     libraryTemplate, | ||||
|     editObjectTemplate, | ||||
|     editActionButtonsTemplate, | ||||
| @@ -182,10 +190,7 @@ define([ | ||||
|                     "implementation": CancelAction, | ||||
|                     "name": "Cancel", | ||||
|                     "description": "Discard changes made to these objects.", | ||||
|                     "depends": [ | ||||
|                         "$injector", | ||||
|                         "navigationService" | ||||
|                     ] | ||||
|                     "depends": [] | ||||
|                 } | ||||
|             ], | ||||
|             "policies": [ | ||||
| @@ -252,6 +257,35 @@ define([ | ||||
|                     "template": topbarEditTemplate | ||||
|                 } | ||||
|             ], | ||||
|             "components": [ | ||||
|                 { | ||||
|                     "type": "decorator", | ||||
|                     "provides": "capabilityService", | ||||
|                     "implementation": TransactionDecorator, | ||||
|                     "depends": [ | ||||
|                         "$q", | ||||
|                         "transactionService", | ||||
|                         "dirtyModelCache" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "type": "provider", | ||||
|                     "provides": "transactionService", | ||||
|                     "implementation": TransactionService, | ||||
|                     "depends": [ | ||||
|                         "$q", | ||||
|                         "dirtyModelCache" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "type": "provider", | ||||
|                     "provides": "dirtyModelCache", | ||||
|                     "implementation": DirtyModelCache, | ||||
|                     "depends": [ | ||||
|                         "topic" | ||||
|                     ] | ||||
|                 } | ||||
|             ], | ||||
|             "representers": [ | ||||
|                 { | ||||
|                     "implementation": EditRepresenter, | ||||
| @@ -263,7 +297,19 @@ define([ | ||||
|                 { | ||||
|                     "implementation": EditToolbarRepresenter | ||||
|                 } | ||||
|             ] | ||||
|             ], | ||||
|             "capabilities": [ | ||||
|                 { | ||||
|                     "key": "editor", | ||||
|                     "name": "Editor Capability", | ||||
|                     "description": "Provides transactional editing capabilities", | ||||
|                     "implementation": EditorCapability, | ||||
|                     "depends": [ | ||||
|                         "transactionService", | ||||
|                         "dirtyModelCache" | ||||
|                     ] | ||||
|                 } | ||||
|             ], | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
|   | ||||
| @@ -33,10 +33,8 @@ define( | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function CancelAction($injector, navigationService, context) { | ||||
|         function CancelAction(context) { | ||||
|             this.domainObject = context.domainObject; | ||||
|             this.navigationService = navigationService; | ||||
|             this.objectService = $injector.get('objectService'); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
| @@ -46,30 +44,16 @@ define( | ||||
|          *          cancellation has completed | ||||
|          */ | ||||
|         CancelAction.prototype.perform = function () { | ||||
|             var domainObject = this.domainObject, | ||||
|                 self = this; | ||||
|             var domainObject = this.domainObject; | ||||
|  | ||||
|             // Look up the object's "editor.completion" capability; | ||||
|             // this is introduced by EditableDomainObject which is | ||||
|             // used to insulate underlying objects from changes made | ||||
|             // during editing. | ||||
|             function getEditorCapability() { | ||||
|                 return domainObject.getCapability("editor"); | ||||
|             function returnToBrowse () { | ||||
|                 var parent; | ||||
|                 domainObject.getCapability("location").getOriginal().then(function (original) { | ||||
|                     parent = original.getCapability("context").getParent(); | ||||
|                     parent.getCapability("action").perform("navigate"); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             // Invoke any save behavior introduced by the editor.completion | ||||
|             // capability. | ||||
|             function doCancel(editor) { | ||||
|                 return editor.cancel(); | ||||
|             } | ||||
|  | ||||
|             //Discard current 'editable' object, and retrieve original | ||||
|             // un-edited object. | ||||
|             function returnToBrowse() { | ||||
|                 return self.navigationService.setNavigation(self.domainObject.getOriginalObject()); | ||||
|             } | ||||
|  | ||||
|             return doCancel(getEditorCapability()) | ||||
|             return this.domainObject.getCapability("editor").cancel() | ||||
|                 .then(returnToBrowse); | ||||
|         }; | ||||
|  | ||||
| @@ -82,7 +66,7 @@ define( | ||||
|         CancelAction.appliesTo = function (context) { | ||||
|             var domainObject = (context || {}).domainObject; | ||||
|             return domainObject !== undefined && | ||||
|                 domainObject.hasCapability("editor"); | ||||
|                 domainObject.getCapability("status").get("editing"); | ||||
|         }; | ||||
|  | ||||
|         return CancelAction; | ||||
|   | ||||
| @@ -25,8 +25,8 @@ | ||||
|  * Module defining EditAction. Created by vwoeltje on 11/14/14. | ||||
|  */ | ||||
| define( | ||||
|     ['../objects/EditableDomainObject'], | ||||
|     function (EditableDomainObject) { | ||||
|     [], | ||||
|     function () { | ||||
|         "use strict"; | ||||
|  | ||||
|         // A no-op action to return in the event that the action cannot | ||||
| @@ -73,25 +73,12 @@ define( | ||||
|          */ | ||||
|         EditAction.prototype.perform = function () { | ||||
|             var self = this; | ||||
|             if (!this.domainObject.hasCapability("editor")) { | ||||
|                 //TODO: This is only necessary because the drop gesture is | ||||
|                 // wrapping the object itself, need to refactor this later. | ||||
|                 // All responsibility for switching into edit mode should be | ||||
|                 // in the edit action, and not duplicated in the gesture | ||||
|                 this.domainObject = new EditableDomainObject(this.domainObject, this.$q); | ||||
|             } | ||||
|             this.navigationService.setNavigation(this.domainObject); | ||||
|             this.domainObject.getCapability('status').set('editing', true); | ||||
|  | ||||
|             //Register a listener to automatically cancel this edit action | ||||
|             //if the user navigates away from this object. | ||||
|             function cancelEditing(navigatedTo){ | ||||
|                 if (!navigatedTo || navigatedTo.getId() !== self.domainObject.getId()) { | ||||
|                     self.domainObject.getCapability('editor').cancel(); | ||||
|                     self.navigationService.removeListener(cancelEditing); | ||||
|                 } | ||||
|             function cancelEditing(){ | ||||
|                 self.domainObject.getCapability('editor').cancel(); | ||||
|                 self.navigationService.removeListener(cancelEditing); | ||||
|             } | ||||
|             this.navigationService.addListener(cancelEditing); | ||||
|             this.domainObject.useCapability("editor"); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -115,15 +115,11 @@ define( | ||||
|                 return copyService.perform(domainObject, parent, allowClone); | ||||
|             } | ||||
|  | ||||
|             function cancelEditingAfterClone(clonedObject) { | ||||
|                 return domainObject.getCapability("editor").cancel() | ||||
|             function saveEdit(clonedObject) { | ||||
|                 return domainObject.getCapability("editor").save() | ||||
|                     .then(resolveWith(clonedObject)); | ||||
|             } | ||||
|  | ||||
|             // Invoke any save behavior introduced by the editor capability; | ||||
|             // this is introduced by EditableDomainObject which is | ||||
|             // used to insulate underlying objects from changes made | ||||
|             // during editing. | ||||
|             function doSave() { | ||||
|                 //This is a new 'virtual object' that has not been persisted | ||||
|                 // yet. | ||||
| @@ -132,11 +128,10 @@ define( | ||||
|                         .then(doWizardSave) | ||||
|                         .then(getParent) | ||||
|                         .then(cloneIntoParent) | ||||
|                         .then(cancelEditingAfterClone) | ||||
|                         .then(saveEdit) | ||||
|                         .catch(resolveWith(false)); | ||||
|                 } else { | ||||
|                     return domainObject.getCapability("editor").save() | ||||
|                         .then(resolveWith(domainObject.getOriginalObject())); | ||||
|                     return domainObject.getCapability("editor").save(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @@ -162,7 +157,7 @@ define( | ||||
|         SaveAction.appliesTo = function (context) { | ||||
|             var domainObject = (context || {}).domainObject; | ||||
|             return domainObject !== undefined && | ||||
|                 domainObject.hasCapability("editor"); | ||||
|                 domainObject.getCapability("status").get("editing"); | ||||
|         }; | ||||
|  | ||||
|         return SaveAction; | ||||
|   | ||||
| @@ -1,60 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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'; | ||||
|         var DISALLOWED_ACTIONS = ["move", "copy", "link", "window", "follow"]; | ||||
|         /** | ||||
|          * Editable Action Capability. Overrides the action capability | ||||
|          * normally exhibited by a domain object and filters out certain | ||||
|          * actions not applicable when an object is in edit mode. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {PersistenceCapability} | ||||
|          */ | ||||
|         function EditableActionCapability( | ||||
|             actionCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|         ) { | ||||
|             var action = Object.create(actionCapability); | ||||
|  | ||||
|             action.getActions = function(domainObject) { | ||||
|                 return actionCapability.getActions(domainObject).filter(function(action){ | ||||
|                    return DISALLOWED_ACTIONS.indexOf(action.getMetadata().key) === -1; | ||||
|                 }); | ||||
|             }; | ||||
|  | ||||
|             return action; | ||||
|         } | ||||
|  | ||||
|         return EditableActionCapability; | ||||
|     } | ||||
| ); | ||||
| @@ -1,60 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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( | ||||
|     ['./EditableLookupCapability'], | ||||
|     function (EditableLookupCapability) { | ||||
|         'use strict'; | ||||
|  | ||||
|         /** | ||||
|          * Wrapper for the "composition" capability; | ||||
|          * ensures that any domain objects reachable in Edit mode | ||||
|          * are also wrapped as EditableDomainObjects. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {CompositionCapability} | ||||
|          */ | ||||
|         return function EditableCompositionCapability( | ||||
|             contextCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|         ) { | ||||
|             // This is a "lookup" style capability (it looks up other | ||||
|             // domain objects), but we do not want to return the same | ||||
|             // specific value every time (composition may change) | ||||
|             return new EditableLookupCapability( | ||||
|                 contextCapability, | ||||
|                 editableObject, | ||||
|                 domainObject, | ||||
|                 cache, | ||||
|                 false // Not idempotent | ||||
|             ); | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| @@ -1,78 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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( | ||||
|     ['./EditableLookupCapability'], | ||||
|     function (EditableLookupCapability) { | ||||
|         'use strict'; | ||||
|  | ||||
|         /** | ||||
|          * Wrapper for the "context" capability; | ||||
|          * ensures that any domain objects reachable in Edit mode | ||||
|          * are also wrapped as EditableDomainObjects. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {ContextCapability} | ||||
|          */ | ||||
|         return function EditableContextCapability( | ||||
|             contextCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|         ) { | ||||
|             // This is a "lookup" style capability (it looks up other | ||||
|             // domain objects), and it should be idempotent | ||||
|             var capability = new EditableLookupCapability( | ||||
|                     contextCapability, | ||||
|                     editableObject, | ||||
|                     domainObject, | ||||
|                     cache, | ||||
|                     true // Idempotent | ||||
|                 ), | ||||
|                 // Track the real root object for the Elements pane | ||||
|                 trueRoot = capability.getRoot(); | ||||
|  | ||||
|             // Provide access to the real root, for the Elements pane. | ||||
|             capability.getTrueRoot = function () { | ||||
|                 return trueRoot; | ||||
|             }; | ||||
|  | ||||
|             // Hide ancestry after the root of this subgraph | ||||
|             if (cache.isRoot(domainObject)) { | ||||
|                 capability.getRoot = function () { | ||||
|                     return editableObject; | ||||
|                 }; | ||||
|                 capability.getPath = function () { | ||||
|                     return [editableObject]; | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             return capability; | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| @@ -1,60 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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( | ||||
|     ['./EditableLookupCapability'], | ||||
|     function (EditableLookupCapability) { | ||||
|         'use strict'; | ||||
|  | ||||
|         /** | ||||
|          * Wrapper for the "instantiation" capability; | ||||
|          * ensures that any domain objects instantiated in Edit mode | ||||
|          * are also wrapped as EditableDomainObjects. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {CompositionCapability} | ||||
|          */ | ||||
|         return function EditableInstantiationCapability( | ||||
|             contextCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|         ) { | ||||
|             // This is a "lookup" style capability (it looks up other | ||||
|             // domain objects), but we do not want to return the same | ||||
|             // specific value every time (composition may change) | ||||
|             return new EditableLookupCapability( | ||||
|                 contextCapability, | ||||
|                 editableObject, | ||||
|                 domainObject, | ||||
|                 cache, | ||||
|                 false // Not idempotent | ||||
|             ); | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| @@ -1,125 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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'; | ||||
|  | ||||
|         /** | ||||
|          * Wrapper for both "context" and "composition" capabilities; | ||||
|          * ensures that any domain objects reachable in Edit mode | ||||
|          * are also wrapped as EditableDomainObjects. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          */ | ||||
|         return function EditableLookupCapability( | ||||
|             contextCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache, | ||||
|             idempotent | ||||
|         ) { | ||||
|             var capability = Object.create(contextCapability), | ||||
|                 method; | ||||
|  | ||||
|             // Check for domain object interface. If something has these | ||||
|             // three methods, we assume it's a domain object. | ||||
|             function isDomainObject(obj) { | ||||
|                 return obj !== undefined && | ||||
|                         typeof obj.getId === 'function' && | ||||
|                         typeof obj.getModel === 'function' && | ||||
|                         typeof obj.getCapability === 'function'; | ||||
|             } | ||||
|  | ||||
|             // Check an object returned by the wrapped capability; if it | ||||
|             // is a domain object, we want to make it editable and/or get | ||||
|             // it from the cache of editable domain objects. This will | ||||
|             // prevent changes made in edit mode from modifying the actual | ||||
|             // underlying domain object. | ||||
|             function makeEditableObject(obj) { | ||||
|                 return isDomainObject(obj) ? | ||||
|                         cache.getEditableObject(obj) : | ||||
|                         obj; | ||||
|             } | ||||
|  | ||||
|             // Wrap a returned value (see above); if it's an array, wrap | ||||
|             // all elements. | ||||
|             function makeEditable(returnValue) { | ||||
|                 return Array.isArray(returnValue) ? | ||||
|                         returnValue.map(makeEditableObject) : | ||||
|                         makeEditableObject(returnValue); | ||||
|             } | ||||
|  | ||||
|             // Wrap a returned value (see above); if it's a promise, wrap | ||||
|             // the resolved value. | ||||
|             function wrapResult(result) { | ||||
|                 return (result && result.then) ? // promise-like | ||||
|                         result.then(makeEditable) : | ||||
|                         makeEditable(result); | ||||
|             } | ||||
|  | ||||
|             // Return a wrapped version of a function, which ensures | ||||
|             // all results are editable domain objects. | ||||
|             function wrapFunction(fn) { | ||||
|                 return function () { | ||||
|                     return wrapResult(contextCapability[fn].apply( | ||||
|                         capability, | ||||
|                         arguments | ||||
|                     )); | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             // Wrap a method such that it only delegates once. | ||||
|             function oneTimeFunction(fn) { | ||||
|                 return function () { | ||||
|                     var result = wrapFunction(fn).apply(this, arguments); | ||||
|                     capability[fn] = function () { | ||||
|                         return result; | ||||
|                     }; | ||||
|                     return result; | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             // Wrap a method of this capability | ||||
|             function wrapMethod(fn) { | ||||
|                 if (typeof capability[fn] === 'function') { | ||||
|                     capability[fn] = | ||||
|                         (idempotent ? oneTimeFunction : wrapFunction)(fn); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Wrap all methods; return only editable domain objects. | ||||
|             for (method in contextCapability) { | ||||
|                 wrapMethod(method); | ||||
|             } | ||||
|  | ||||
|             return capability; | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| @@ -1,68 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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'; | ||||
|  | ||||
|         /** | ||||
|          * Editable Persistence Capability. Overrides the persistence capability | ||||
|          * normally exhibited by a domain object to ensure that changes made | ||||
|          * during edit mode are not immediately stored to the database or other | ||||
|          * backing storage. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {PersistenceCapability} | ||||
|          */ | ||||
|         function EditablePersistenceCapability( | ||||
|             persistenceCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|         ) { | ||||
|             var persistence = Object.create(persistenceCapability); | ||||
|  | ||||
|             // Simply trigger refresh of in-view objects; do not | ||||
|             // write anything to database. | ||||
|             persistence.persist = function () { | ||||
|                 return cache.markDirty(editableObject); | ||||
|             }; | ||||
|  | ||||
|             // Delegate refresh to the original object; this avoids refreshing | ||||
|             // the editable instance of the object, and ensures that refresh | ||||
|             // correctly targets the "real" version of the object. | ||||
|             persistence.refresh = function () { | ||||
|                 return domainObject.getCapability('persistence').refresh(); | ||||
|             }; | ||||
|  | ||||
|             return persistence; | ||||
|         } | ||||
|  | ||||
|         return EditablePersistenceCapability; | ||||
|     } | ||||
| ); | ||||
| @@ -1,60 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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( | ||||
|     ['./EditableLookupCapability'], | ||||
|     function (EditableLookupCapability) { | ||||
|         'use strict'; | ||||
|  | ||||
|         /** | ||||
|          * Wrapper for the "relationship" capability; | ||||
|          * ensures that any domain objects reachable in Edit mode | ||||
|          * are also wrapped as EditableDomainObjects. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {RelationshipCapability} | ||||
|          */ | ||||
|         return function EditableRelationshipCapability( | ||||
|             relationshipCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|         ) { | ||||
|             // This is a "lookup" style capability (it looks up other | ||||
|             // domain objects), but we do not want to return the same | ||||
|             // specific value every time (composition may change) | ||||
|             return new EditableLookupCapability( | ||||
|                 relationshipCapability, | ||||
|                 editableObject, | ||||
|                 domainObject, | ||||
|                 cache, | ||||
|                 false // Not idempotent | ||||
|             ); | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| @@ -26,117 +26,61 @@ define( | ||||
|     function () { | ||||
|         'use strict'; | ||||
|  | ||||
|  | ||||
|         /** | ||||
|          * Implements "save" and "cancel" as capabilities of | ||||
|          * the object. In editing mode, user is seeing/using | ||||
|          * a copy of the object (an EditableDomainObject) | ||||
|          * which is disconnected from persistence; the Save | ||||
|          * and Cancel actions can use this capability to | ||||
|          * propagate changes from edit mode to the underlying | ||||
|          * actual persistable object. | ||||
|          * | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          */ | ||||
|         function EditorCapability( | ||||
|             persistenceCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|             transactionService, | ||||
|             dirtyModelCache, | ||||
|             domainObject | ||||
|         ) { | ||||
|             this.editableObject = editableObject; | ||||
|             this.transactionService = transactionService; | ||||
|             this.dirtyModelCache = dirtyModelCache; | ||||
|             this.domainObject = domainObject; | ||||
|             this.cache = cache; | ||||
|         } | ||||
|  | ||||
|         // Simulate Promise.resolve (or $q.when); the former | ||||
|         // causes a delayed reaction from Angular (since it | ||||
|         // does not trigger a digest) and the latter is not | ||||
|         // readily accessible, since we're a few classes | ||||
|         // removed from the layer which gets dependency | ||||
|         // injection. | ||||
|         function resolvePromise(value) { | ||||
|             return (value && value.then) ? value : { | ||||
|                 then: function (callback) { | ||||
|                     return resolvePromise(callback(value)); | ||||
|                 } | ||||
|             }; | ||||
|         EditorCapability.prototype.edit = function () { | ||||
|             this.transactionService.startTransaction(); | ||||
|             this.domainObject.getCapability('status').set('editing', true); | ||||
|         }; | ||||
|  | ||||
|         function isEditing (domainObject) { | ||||
|             return domainObject.getCapability('status').get('editing') || | ||||
|                 domainObject.hasCapability('context') && isEditing(domainObject.getCapability('context').getParent()); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Save any changes that have been made to this domain object | ||||
|          * (as well as to others that might have been retrieved and | ||||
|          * modified during the editing session) | ||||
|          * @param {boolean} nonrecursive if true, save only this | ||||
|          *        object (and not other objects with associated changes) | ||||
|          * @returns {Promise} a promise that will be fulfilled after | ||||
|          *          persistence has completed. | ||||
|          * @memberof platform/commonUI/edit.EditorCapability# | ||||
|          * Determines whether this object, or any of its ancestors are | ||||
|          * currently being edited. | ||||
|          * @returns boolean | ||||
|          */ | ||||
|         EditorCapability.prototype.save = function (nonrecursive) { | ||||
|             var domainObject = this.domainObject, | ||||
|                 editableObject = this.editableObject, | ||||
|                 self = this, | ||||
|                 cache = this.cache, | ||||
|                 returnPromise; | ||||
|         EditorCapability.prototype.isEditing = function () { | ||||
|             return isEditing(this.domainObject); | ||||
|         }; | ||||
|  | ||||
|             // Update the underlying, "real" domain object's model | ||||
|             // with changes made to the copy used for editing. | ||||
|             function doMutate() { | ||||
|                 return domainObject.useCapability('mutation', function () { | ||||
|                     return editableObject.getModel(); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             // Persist the underlying domain object | ||||
|             function doPersist() { | ||||
|                 return domainObject.getCapability('persistence').persist(); | ||||
|             } | ||||
|  | ||||
|             editableObject.getCapability("status").set("editing", false); | ||||
|  | ||||
|             if (nonrecursive) { | ||||
|                 returnPromise = resolvePromise(doMutate()) | ||||
|                     .then(doPersist) | ||||
|                     .then(function(){ | ||||
|                         self.cancel(); | ||||
|                     }); | ||||
|             } else { | ||||
|                 returnPromise = resolvePromise(cache.saveAll()); | ||||
|             } | ||||
|             //Return the original (non-editable) object | ||||
|             return returnPromise.then(function() { | ||||
|                 return domainObject.getOriginalObject ? domainObject.getOriginalObject() : domainObject; | ||||
|         EditorCapability.prototype.save = function () { | ||||
|             var domainObject = this.domainObject; | ||||
|             return this.transactionService.commit().then(function() { | ||||
|                 domainObject.getCapability('status').set('editing', false); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Cancel editing; Discard any changes that have been made to | ||||
|          * this domain object (as well as to others that might have | ||||
|          * been retrieved and modified during the editing session) | ||||
|          * @returns {Promise} a promise that will be fulfilled after | ||||
|          *          cancellation has completed. | ||||
|          * @memberof platform/commonUI/edit.EditorCapability# | ||||
|          */ | ||||
|         EditorCapability.prototype.invoke = EditorCapability.prototype.edit; | ||||
|  | ||||
|         EditorCapability.prototype.cancel = function () { | ||||
|             this.editableObject.getCapability("status").set("editing", false); | ||||
|             this.cache.markClean(); | ||||
|             return resolvePromise(undefined); | ||||
|             var domainObject = this.domainObject; | ||||
|             return this.transactionService.cancel().then(function(){ | ||||
|                 domainObject.getCapability("status").set("editing", false); | ||||
|                 return domainObject; | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if there are any unsaved changes. | ||||
|          * @returns {boolean} true if there are unsaved changes | ||||
|          * @memberof platform/commonUI/edit.EditorCapability# | ||||
|          */ | ||||
|         EditorCapability.prototype.dirty = function () { | ||||
|             return this.cache.dirty(); | ||||
|             return this.dirtyModelCache.isDirty(this.domainObject); | ||||
|         }; | ||||
|  | ||||
|         EditorCapability.prototype.appliesTo = function(context) { | ||||
|             var domainObject = context.domainObject; | ||||
|             return domainObject && domainObject.getType().hasFeature("creation"); | ||||
|         } | ||||
|  | ||||
|         return EditorCapability; | ||||
|     } | ||||
| ); | ||||
|   | ||||
| @@ -0,0 +1,68 @@ | ||||
| /***************************************************************************** | ||||
|  * 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( | ||||
|     ['./TransactionalPersistenceCapability'], | ||||
|     function (TransactionalPersistenceCapability) { | ||||
|         'use strict'; | ||||
|  | ||||
|         function TransactionDecorator( | ||||
|             $q, | ||||
|             transactionService, | ||||
|             dirtyModelCache, | ||||
|             capabilityService | ||||
|         ) { | ||||
|             this.capabilityService = capabilityService; | ||||
|             this.transactionService = transactionService; | ||||
|             this.dirtyModelCache = dirtyModelCache; | ||||
|             this.$q = $q; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Decorate PersistenceCapability to ignore persistence calls when a | ||||
|          * transaction is in progress. | ||||
|          */ | ||||
|         TransactionDecorator.prototype.getCapabilities = function (model) { | ||||
|             var self = this, | ||||
|                 capabilities = this.capabilityService.getCapabilities(model), | ||||
|                 persistenceCapability = capabilities.persistence; | ||||
|  | ||||
|             capabilities.persistence = function (domainObject) { | ||||
|                 var original = | ||||
|                     (typeof persistenceCapability === 'function') ? | ||||
|                         persistenceCapability(domainObject) : | ||||
|                         persistenceCapability; | ||||
|                 return new TransactionalPersistenceCapability( | ||||
|                     self.$q, | ||||
|                     self.transactionService, | ||||
|                     self.dirtyModelCache, | ||||
|                     original, | ||||
|                     domainObject | ||||
|                 ); | ||||
|             }; | ||||
|             return capabilities; | ||||
|         }; | ||||
|  | ||||
|         return TransactionDecorator; | ||||
|     } | ||||
| ); | ||||
| @@ -0,0 +1,75 @@ | ||||
| /***************************************************************************** | ||||
|  * 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'; | ||||
|  | ||||
|         function TransactionalPersistenceCapability( | ||||
|             $q, | ||||
|             transactionService, | ||||
|             dirtyModelCache, | ||||
|             persistenceCapability, | ||||
|             domainObject | ||||
|         ) { | ||||
|             this.transactionService = transactionService; | ||||
|             this.dirtyModelCache = dirtyModelCache; | ||||
|             this.persistenceCapability = Object.create(persistenceCapability); | ||||
|             this.domainObject = domainObject; | ||||
|             this.$q = $q; | ||||
|         } | ||||
|  | ||||
|         TransactionalPersistenceCapability.prototype.persist = function () { | ||||
|             var domainObject = this.domainObject, | ||||
|                 dirtyModelCache = this.dirtyModelCache; | ||||
|             if (this.transactionService.isActive() && !this.transactionService.isCommitting()) { | ||||
|                 dirtyModelCache.markDirty(domainObject); | ||||
|                 //Using $q here because need to return something | ||||
|                 // from which 'catch' can be chained | ||||
|                 return this.$q.when(true); | ||||
|             } else { | ||||
|                 return this.persistenceCapability.persist().then(function (result) { | ||||
|                     dirtyModelCache.markClean(domainObject); | ||||
|                     return result; | ||||
|                 }); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         TransactionalPersistenceCapability.prototype.refresh = function () { | ||||
|             var domainObject = this.domainObject, | ||||
|                 dirtyModelCache = this.dirtyModelCache; | ||||
|  | ||||
|             return this.persistenceCapability.refresh().then(function (result) { | ||||
|                 dirtyModelCache.markClean(domainObject); | ||||
|                 return result; | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         TransactionalPersistenceCapability.prototype.getSpace = function () { | ||||
|             return this.persistenceCapability.getSpace(); | ||||
|         }; | ||||
|  | ||||
|         return TransactionalPersistenceCapability; | ||||
|     } | ||||
| ); | ||||
| @@ -1,132 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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*/ | ||||
|  | ||||
| /** | ||||
|  * Defines EditableDomainObject, which wraps domain objects | ||||
|  * such that user code may work with and mutate a copy of the | ||||
|  * domain object model; these changes may then be propagated | ||||
|  * up to the real domain object (or not) by way of invoking | ||||
|  * save or cancel behaviors of the "editor.completion" | ||||
|  * capability (a capability intended as internal to edit | ||||
|  * mode; invoked by way of the Save and Cancel actions.) | ||||
|  */ | ||||
| define( | ||||
|     [ | ||||
|         '../capabilities/EditablePersistenceCapability', | ||||
|         '../capabilities/EditableContextCapability', | ||||
|         '../capabilities/EditableCompositionCapability', | ||||
|         '../capabilities/EditableRelationshipCapability', | ||||
|         '../capabilities/EditableInstantiationCapability', | ||||
|         '../capabilities/EditorCapability', | ||||
|         '../capabilities/EditableActionCapability', | ||||
|         './EditableDomainObjectCache' | ||||
|     ], | ||||
|     function ( | ||||
|         EditablePersistenceCapability, | ||||
|         EditableContextCapability, | ||||
|         EditableCompositionCapability, | ||||
|         EditableRelationshipCapability, | ||||
|         EditableInstantiationCapability, | ||||
|         EditorCapability, | ||||
|         EditableActionCapability, | ||||
|         EditableDomainObjectCache | ||||
|     ) { | ||||
|         "use strict"; | ||||
|  | ||||
|         var capabilityFactories = { | ||||
|             persistence: EditablePersistenceCapability, | ||||
|             context: EditableContextCapability, | ||||
|             composition: EditableCompositionCapability, | ||||
|             relationship: EditableRelationshipCapability, | ||||
|             instantiation: EditableInstantiationCapability, | ||||
|             editor: EditorCapability | ||||
|         }; | ||||
|  | ||||
|         // Handle special case where "editor.completion" wraps persistence | ||||
|         // (other capability overrides wrap capabilities of the same type.) | ||||
|         function getDelegateArguments(name, args) { | ||||
|             return name === "editor" ? ['persistence'] : args; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * An EditableDomainObject overrides capabilities | ||||
|          * which need to behave differently in edit mode, | ||||
|          * and provides a "working copy" of the object's | ||||
|          * model to allow changes to be easily cancelled. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {DomainObject} | ||||
|          */ | ||||
|         function EditableDomainObject(domainObject, $q) { | ||||
|             // The cache will hold all domain objects reached from | ||||
|             // the initial EditableDomainObject; this ensures that | ||||
|             // different versions of the same editable domain object | ||||
|             // are not shown in different sections of the same Edit | ||||
|             // UI, which might thereby fall out of sync. | ||||
|             var cache, | ||||
|                 originalObject = domainObject, | ||||
|                 cachedObject; | ||||
|  | ||||
|             // Constructor for EditableDomainObject, which adheres | ||||
|             // to the same shared cache. | ||||
|             function EditableDomainObjectImpl(domainObject, model) { | ||||
|                 var editableObject = Object.create(domainObject); | ||||
|  | ||||
|                 // Only provide the cloned model. | ||||
|                 editableObject.getModel = function () { return model; }; | ||||
|  | ||||
|                 // Override certain capabilities | ||||
|                 editableObject.getCapability = function (name) { | ||||
|                     var delegateArguments = getDelegateArguments(name, arguments), | ||||
|                         capability = domainObject.getCapability.apply( | ||||
|                             this, | ||||
|                             delegateArguments | ||||
|                         ), | ||||
|                         Factory = capabilityFactories[name]; | ||||
|  | ||||
|                     return (Factory && capability) ? | ||||
|                             new Factory(capability, editableObject, domainObject, cache) : | ||||
|                             capability; | ||||
|                 }; | ||||
|  | ||||
|  | ||||
|                 editableObject.setOriginalObject = function(object) { | ||||
|                     originalObject = object; | ||||
|                 }; | ||||
|  | ||||
|                 editableObject.getOriginalObject = function() { | ||||
|                     return originalObject; | ||||
|                 }; | ||||
|  | ||||
|                 return editableObject; | ||||
|             } | ||||
|  | ||||
|             cache = new EditableDomainObjectCache(EditableDomainObjectImpl, $q); | ||||
|             cachedObject = cache.getEditableObject(domainObject); | ||||
|  | ||||
|             return cachedObject; | ||||
|         } | ||||
|  | ||||
|         return EditableDomainObject; | ||||
|     } | ||||
| ); | ||||
| @@ -1,173 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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*/ | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * An editable domain object cache stores domain objects that have been | ||||
|  * made editable, in a group that can be saved all-at-once. This supports | ||||
|  * Edit mode, which is launched for a specific object but may contain | ||||
|  * changes across many objects. | ||||
|  * | ||||
|  * Editable domain objects have certain specific capabilities overridden | ||||
|  * to ensure that changes made while in edit mode do not propagate up | ||||
|  * to the objects used in browse mode (or to persistence) until the user | ||||
|  * initiates a Save. | ||||
|  */ | ||||
| define( | ||||
|     ["./EditableModelCache"], | ||||
|     function (EditableModelCache) { | ||||
|         'use strict'; | ||||
|  | ||||
|         /** | ||||
|          * Construct a new cache for editable domain objects. This can be used | ||||
|          * to get-or-create editable objects, particularly to support wrapping | ||||
|          * of objects retrieved via composition or context capabilities as | ||||
|          * editable domain objects. | ||||
|          * | ||||
|          * @param {Constructor<DomainObject>} EditableDomainObject a | ||||
|          *        constructor function which takes a regular domain object as | ||||
|          *        an argument, and returns an editable domain object as its | ||||
|          *        result. | ||||
|          * @param $q Angular's $q, for promise handling | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditableDomainObjectCache(EditableDomainObject, $q) { | ||||
|             this.cache = new EditableModelCache(); | ||||
|             this.dirtyObjects = {}; | ||||
|             this.root = undefined; | ||||
|             this.$q = $q; | ||||
|             this.EditableDomainObject = EditableDomainObject; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Wrap this domain object in an editable form, or pull such | ||||
|          * an object from the cache if one already exists. | ||||
|          * | ||||
|          * @param {DomainObject} domainObject the regular domain object | ||||
|          * @returns {DomainObject} the domain object in an editable form | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.getEditableObject = function (domainObject) { | ||||
|             var type = domainObject.getCapability('type'), | ||||
|                 EditableDomainObject = this.EditableDomainObject, | ||||
|                 editableObject, | ||||
|                 statusListener; | ||||
|  | ||||
|             // Track the top-level domain object; this will have | ||||
|             // some special behavior for its context capability. | ||||
|             this.root = this.root || domainObject; | ||||
|  | ||||
|             // Avoid double-wrapping (WTD-1017) | ||||
|             if (domainObject.hasCapability('editor')) { | ||||
|                 return domainObject; | ||||
|             } | ||||
|  | ||||
|             // Don't bother wrapping non-editable objects | ||||
|             if (!type || !type.hasFeature('creation')) { | ||||
|                 return domainObject; | ||||
|             } | ||||
|  | ||||
|             // Provide an editable form of the object | ||||
|             editableObject = new EditableDomainObject( | ||||
|                 domainObject, | ||||
|                 this.cache.getCachedModel(domainObject) | ||||
|             ); | ||||
|  | ||||
|             return editableObject; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if a domain object is (effectively) the top-level | ||||
|          * object in this editable subgraph. | ||||
|          * @returns {boolean} true if it is the root | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.isRoot = function (domainObject) { | ||||
|             return domainObject === this.root; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Mark an editable domain object (presumably already cached) | ||||
|          * as having received modifications during editing; it should be | ||||
|          * included in the bulk save invoked when editing completes. | ||||
|          * | ||||
|          * @param {DomainObject} domainObject the domain object | ||||
|          * @memberof platform/commonUI/edit.EditableDomainObjectCache# | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.markDirty = function (domainObject) { | ||||
|             this.dirtyObjects[domainObject.getId()] = domainObject; | ||||
|             return this.$q.when(true); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Mark an object (presumably already cached) as having had its | ||||
|          * changes saved (and thus no longer needing to be subject to a | ||||
|          * save operation.) | ||||
|          * | ||||
|          * @param {DomainObject} domainObject the domain object | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.markClean = function (domainObject) { | ||||
|             var self = this; | ||||
|             if (!domainObject) { | ||||
|                 Object.keys(this.dirtyObjects).forEach(function(key) { | ||||
|                     delete self.dirtyObjects[key]; | ||||
|                 }); | ||||
|             } else { | ||||
|                 delete this.dirtyObjects[domainObject.getId()]; | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Initiate a save on all objects that have been cached. | ||||
|          * @return {Promise} A promise which will resolve when all objects are | ||||
|          *         persisted. | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.saveAll = function () { | ||||
|             // Get a list of all dirty objects | ||||
|             var dirty = this.dirtyObjects, | ||||
|                 objects = Object.keys(dirty).map(function (k) { | ||||
|                     return dirty[k]; | ||||
|                 }); | ||||
|  | ||||
|             // Clear dirty set, since we're about to save. | ||||
|             this.dirtyObjects = {}; | ||||
|  | ||||
|             // Most save logic is handled by the "editor.completion" | ||||
|             // capability, so that is delegated here. | ||||
|             return this.$q.all(objects.map(function (object) { | ||||
|                 // Save; pass a nonrecursive flag to avoid looping | ||||
|                 return object.getCapability('editor').save(true); | ||||
|             })); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if any objects have been marked dirty in this cache. | ||||
|          * @returns {boolean} true if objects are dirty | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.dirty = function () { | ||||
|             return Object.keys(this.dirtyObjects).length > 0; | ||||
|         }; | ||||
|  | ||||
|         return EditableDomainObjectCache; | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @@ -1,62 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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"; | ||||
|  | ||||
|         /** | ||||
|          * An editable model cache stores domain object models that have been | ||||
|          * made editable, to support a group that can be saved all-at-once. | ||||
|          * This is useful in Edit mode, which is launched for a specific | ||||
|          * object but may contain changes across many objects. | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditableModelCache() { | ||||
|             this.cache = {}; | ||||
|         } | ||||
|  | ||||
|         // Deep-copy a model. Models are JSONifiable, so this can be | ||||
|         // done by stringification then destringification | ||||
|         function clone(model) { | ||||
|             return JSON.parse(JSON.stringify(model)); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get this domain object's model from the cache (or | ||||
|          * place it in the cache if it isn't in the cache yet) | ||||
|          * @returns a clone of the domain object's model | ||||
|          */ | ||||
|         EditableModelCache.prototype.getCachedModel = function (domainObject) { | ||||
|             var id = domainObject.getId(), | ||||
|                 cache = this.cache; | ||||
|  | ||||
|             return (cache[id] = | ||||
|                 cache[id] || clone(domainObject.getModel())); | ||||
|         }; | ||||
|  | ||||
|         return EditableModelCache; | ||||
|     } | ||||
| ); | ||||
| @@ -37,11 +37,12 @@ define([], function () { | ||||
|     } | ||||
|  | ||||
|     EditableLinkPolicy.prototype.allow = function (action, context) { | ||||
|         var key = action.getMetadata().key; | ||||
|         var key = action.getMetadata().key, | ||||
|             object; | ||||
|  | ||||
|         if (key === 'link') { | ||||
|             return !((context.selectedObject || context.domainObject) | ||||
|                 .hasCapability('editor')); | ||||
|             object = context.selectedObject || context.domainObject; | ||||
|             return !(object.hasCapability("editor") && object.getCapability("editor").isEditing()); | ||||
|         } | ||||
|  | ||||
|         // Like all policies, allow by default. | ||||
|   | ||||
| @@ -39,8 +39,8 @@ define([], function () { | ||||
|             selectedObject = context.selectedObject, | ||||
|             key = action.getMetadata().key; | ||||
|  | ||||
|         if (key === 'move' && domainObject.hasCapability('editor')) { | ||||
|             return !!selectedObject && selectedObject.hasCapability('editor'); | ||||
|         if (key === 'move' && domainObject.hasCapability('editor') && domainObject.getCapability('editor').isEditing()) { | ||||
|             return !!selectedObject && selectedObject.hasCapability('editor') && selectedObject.getCapability('editor').isEditing(); | ||||
|         } | ||||
|  | ||||
|         // Like all policies, allow by default. | ||||
|   | ||||
| @@ -39,7 +39,7 @@ define( | ||||
|             // If a view is flagged as non-editable, only allow it | ||||
|             // while we're not in Edit mode. | ||||
|             if ((view || {}).editable === false) { | ||||
|                 return !domainObject.hasCapability('editor'); | ||||
|                 return !(domainObject.hasCapability('editor') && domainObject.getCapability('editor').isEditing()); | ||||
|             } | ||||
|  | ||||
|             // Like all policies, allow by default. | ||||
|   | ||||
| @@ -19,15 +19,29 @@ | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*global define,describe,it,expect,beforeEach,jasmine*/ | ||||
| 
 | ||||
| /*global define*/ | ||||
| define( | ||||
|     ["../../src/objects/EditableDomainObject"], | ||||
|     function (EditableDomainObject) { | ||||
|         "use strict"; | ||||
|     [], | ||||
|     function() { | ||||
|         function DirtyModelCache(topic) { | ||||
|             this.cache = {}; | ||||
|         } | ||||
| 
 | ||||
|         describe("Editable domain object", function () { | ||||
|         DirtyModelCache.prototype.get = function () { | ||||
|             return this.cache; | ||||
|         }; | ||||
| 
 | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
|         DirtyModelCache.prototype.isDirty = function (domainObject) { | ||||
|             return !!this.cache[domainObject.getId()]; | ||||
|         }; | ||||
| 
 | ||||
|         DirtyModelCache.prototype.markDirty = function (domainObject) { | ||||
|             this.cache[domainObject.getId()] = domainObject; | ||||
|         }; | ||||
| 
 | ||||
|         DirtyModelCache.prototype.markClean = function (domainObject) { | ||||
|             delete this.cache[domainObject.getId()]; | ||||
|         }; | ||||
| 
 | ||||
|         return DirtyModelCache; | ||||
|     }); | ||||
							
								
								
									
										118
									
								
								platform/commonUI/edit/src/services/TransactionService.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								platform/commonUI/edit/src/services/TransactionService.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| /***************************************************************************** | ||||
|  * 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() { | ||||
|         /** | ||||
|          * Implements an application-wide transaction state. Once a | ||||
|          * transaction is started, calls to PersistenceCapability.persist() | ||||
|          * will be deferred until a subsequent call to | ||||
|          * TransactionService.commit() is made. | ||||
|          * | ||||
|          * @param $q | ||||
|          * @constructor | ||||
|          */ | ||||
|         function TransactionService($q, dirtyModelCache) { | ||||
|             this.$q = $q; | ||||
|             this.transaction = false; | ||||
|             this.committing = false; | ||||
|             this.cache = dirtyModelCache; | ||||
|         } | ||||
|  | ||||
|         TransactionService.prototype.startTransaction = function () { | ||||
|             if (this.transaction) | ||||
|                 console.error("Transaction already in progress") | ||||
|             this.transaction = true; | ||||
|         }; | ||||
|  | ||||
|         TransactionService.prototype.isActive = function () { | ||||
|             return this.transaction; | ||||
|         }; | ||||
|  | ||||
|         TransactionService.prototype.isCommitting = function () { | ||||
|             return this.committing; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * All persist calls deferred since the beginning of the transaction | ||||
|          * will be committed. Any failures will be reported via a promise | ||||
|          * rejection. | ||||
|          * @returns {*} | ||||
|          */ | ||||
|         TransactionService.prototype.commit = function () { | ||||
|             var self = this; | ||||
|                 cache = this.cache.get(); | ||||
|  | ||||
|             this.committing = true; | ||||
|  | ||||
|             function keyToObject(key) { | ||||
|                 return cache[key]; | ||||
|             } | ||||
|  | ||||
|             function objectToPromise(object) { | ||||
|                 return object.getCapability('persistence').persist(); | ||||
|             } | ||||
|  | ||||
|             return this.$q.all( | ||||
|                 Object.keys(cache) | ||||
|                     .map(keyToObject) | ||||
|                     .map(objectToPromise)) | ||||
|                 .then(function () { | ||||
|                     self.transaction = false; | ||||
|                     this.committing = false; | ||||
|                 }).catch(function() { | ||||
|                     return this.committing = false; | ||||
|                 }); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Cancel the current transaction, replacing any dirty objects from | ||||
|          * persistence. Not a true rollback, as it cannot be used to undo any | ||||
|          * persist calls that were successful in the event one of a batch of | ||||
|          * persists failing. | ||||
|          * | ||||
|          * @returns {*} | ||||
|          */ | ||||
|         TransactionService.prototype.cancel = function () { | ||||
|             var self = this, | ||||
|                 cache = this.cache.get(); | ||||
|  | ||||
|             function keyToObject(key) { | ||||
|                 return cache[key]; | ||||
|             } | ||||
|  | ||||
|             function objectToPromise(object) { | ||||
|                 return self.$q.when(object.getModel().persisted && object.getCapability('persistence').refresh()); | ||||
|             } | ||||
|  | ||||
|             return this.$q.all(Object.keys(cache) | ||||
|                 .map(keyToObject) | ||||
|                 .map(objectToPromise)) | ||||
|                 .then(function () { | ||||
|                     self.transaction = false; | ||||
|                     this.committing = false; | ||||
|                 }); | ||||
|         }; | ||||
|  | ||||
|         return TransactionService; | ||||
| }); | ||||
| @@ -1,75 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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,describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ["../../src/capabilities/EditableCompositionCapability"], | ||||
|     function (EditableCompositionCapability) { | ||||
|         "use strict"; | ||||
|  | ||||
|         describe("An editable composition capability", function () { | ||||
|             var mockContext, | ||||
|                 mockEditableObject, | ||||
|                 mockDomainObject, | ||||
|                 mockTestObject, | ||||
|                 someValue, | ||||
|                 mockFactory, | ||||
|                 capability; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 // EditableContextCapability should watch ALL | ||||
|                 // methods for domain objects, so give it an | ||||
|                 // arbitrary interface to wrap. | ||||
|                 mockContext = | ||||
|                     jasmine.createSpyObj("context", [ "getDomainObject" ]); | ||||
|                 mockTestObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getModel", "getCapability" ] | ||||
|                 ); | ||||
|                 mockFactory = | ||||
|                     jasmine.createSpyObj("factory", ["getEditableObject"]); | ||||
|  | ||||
|                 someValue = { x: 42 }; | ||||
|  | ||||
|                 mockContext.getDomainObject.andReturn(mockTestObject); | ||||
|                 mockFactory.getEditableObject.andReturn(someValue); | ||||
|  | ||||
|                 capability = new EditableCompositionCapability( | ||||
|                     mockContext, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     mockFactory | ||||
|                 ); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             // Most behavior is tested for EditableLookupCapability, | ||||
|             // so just verify that this isse | ||||
|             it("presumes non-idempotence of its wrapped capability", function () { | ||||
|                 expect(capability.getDomainObject()) | ||||
|                     .toEqual(capability.getDomainObject()); | ||||
|                 expect(mockContext.getDomainObject.calls.length).toEqual(2); | ||||
|             }); | ||||
|  | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -1,89 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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,describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ["../../src/capabilities/EditableContextCapability"], | ||||
|     function (EditableContextCapability) { | ||||
|         "use strict"; | ||||
|  | ||||
|         describe("An editable context capability", function () { | ||||
|             var mockContext, | ||||
|                 mockEditableObject, | ||||
|                 mockDomainObject, | ||||
|                 mockTestObject, | ||||
|                 someValue, | ||||
|                 mockFactory, | ||||
|                 capability; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 // EditableContextCapability should watch ALL | ||||
|                 // methods for domain objects, so give it an | ||||
|                 // arbitrary interface to wrap. | ||||
|                 mockContext = | ||||
|                     jasmine.createSpyObj("context", [ "getDomainObject", "getRoot" ]); | ||||
|                 mockTestObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getModel", "getCapability" ] | ||||
|                 ); | ||||
|                 mockFactory = jasmine.createSpyObj( | ||||
|                     "factory", | ||||
|                     ["getEditableObject", "isRoot"] | ||||
|                 ); | ||||
|  | ||||
|                 someValue = { x: 42 }; | ||||
|  | ||||
|                 mockContext.getRoot.andReturn(mockTestObject); | ||||
|                 mockContext.getDomainObject.andReturn(mockTestObject); | ||||
|                 mockFactory.getEditableObject.andReturn(someValue); | ||||
|                 mockFactory.isRoot.andReturn(true); | ||||
|  | ||||
|                 capability = new EditableContextCapability( | ||||
|                     mockContext, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     mockFactory | ||||
|                 ); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             it("presumes idempotence of its wrapped capability", function () { | ||||
|                 expect(capability.getDomainObject()) | ||||
|                     .toEqual(capability.getDomainObject()); | ||||
|                 expect(mockContext.getDomainObject.calls.length).toEqual(1); | ||||
|             }); | ||||
|  | ||||
|             it("hides the root object", function () { | ||||
|                 expect(capability.getRoot()).toEqual(mockEditableObject); | ||||
|                 expect(capability.getPath()).toEqual([mockEditableObject]); | ||||
|             }); | ||||
|  | ||||
|             it("exposes the root object through a different method", function () { | ||||
|                 // Should still go through the factory... | ||||
|                 expect(capability.getTrueRoot()).toEqual(someValue); | ||||
|                 // ...with value of the unwrapped capability's getRoot | ||||
|                 expect(mockFactory.getEditableObject) | ||||
|                     .toHaveBeenCalledWith(mockTestObject); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -1,146 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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,describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ["../../src/capabilities/EditableLookupCapability"], | ||||
|     function (EditableLookupCapability) { | ||||
|         "use strict"; | ||||
|  | ||||
|         describe("An editable lookup capability", function () { | ||||
|             var mockContext, | ||||
|                 mockEditableObject, | ||||
|                 mockDomainObject, | ||||
|                 mockTestObject, | ||||
|                 someValue, | ||||
|                 factory, | ||||
|                 capability; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 // EditableContextCapability should watch ALL | ||||
|                 // methods for domain objects, so give it an | ||||
|                 // arbitrary interface to wrap. | ||||
|                 mockContext = jasmine.createSpyObj( | ||||
|                     "context", | ||||
|                     [ | ||||
|                         "getSomething", | ||||
|                         "getDomainObject", | ||||
|                         "getDomainObjectArray" | ||||
|                     ] | ||||
|                 ); | ||||
|                 mockTestObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getModel", "getCapability" ] | ||||
|                 ); | ||||
|                 factory = { | ||||
|                     getEditableObject: function (v) { | ||||
|                         return { | ||||
|                             isFromTestFactory: true, | ||||
|                             calledWith: v | ||||
|                         }; | ||||
|                     } | ||||
|                 }; | ||||
|  | ||||
|                 someValue = { x: 42 }; | ||||
|  | ||||
|                 mockContext.getSomething.andReturn(someValue); | ||||
|                 mockContext.getDomainObject.andReturn(mockTestObject); | ||||
|                 mockContext.getDomainObjectArray.andReturn([mockTestObject]); | ||||
|  | ||||
|                 capability = new EditableLookupCapability( | ||||
|                     mockContext, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     factory, | ||||
|                     false | ||||
|                 ); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             it("wraps retrieved domain objects", function () { | ||||
|                 var object = capability.getDomainObject(); | ||||
|                 expect(object.isFromTestFactory).toBe(true); | ||||
|                 expect(object.calledWith).toEqual(mockTestObject); | ||||
|             }); | ||||
|  | ||||
|             it("wraps retrieved domain object arrays", function () { | ||||
|                 var object = capability.getDomainObjectArray()[0]; | ||||
|                 expect(object.isFromTestFactory).toBe(true); | ||||
|                 expect(object.calledWith).toEqual(mockTestObject); | ||||
|             }); | ||||
|  | ||||
|             it("does not wrap non-domain-objects", function () { | ||||
|                 expect(capability.getSomething()).toEqual(someValue); | ||||
|             }); | ||||
|  | ||||
|             it("caches idempotent lookups", function () { | ||||
|                 capability = new EditableLookupCapability( | ||||
|                     mockContext, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     factory, | ||||
|                     true // idempotent | ||||
|                 ); | ||||
|                 expect(capability.getDomainObject()) | ||||
|                     .toEqual(capability.getDomainObject()); | ||||
|                 expect(mockContext.getDomainObject.calls.length).toEqual(1); | ||||
|             }); | ||||
|  | ||||
|             it("does not cache non-idempotent lookups", function () { | ||||
|                 capability = new EditableLookupCapability( | ||||
|                     mockContext, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     factory, | ||||
|                     false // Not idempotent | ||||
|                 ); | ||||
|                 expect(capability.getDomainObject()) | ||||
|                     .toEqual(capability.getDomainObject()); | ||||
|                 expect(mockContext.getDomainObject.calls.length).toEqual(2); | ||||
|             }); | ||||
|  | ||||
|             it("wraps inherited methods", function () { | ||||
|                 var CapabilityClass = function(){ | ||||
|                 }; | ||||
|                 CapabilityClass.prototype.inheritedMethod=function () { | ||||
|                     return "an inherited method"; | ||||
|                 }; | ||||
|  | ||||
|                 mockContext = new CapabilityClass(); | ||||
|  | ||||
|                 capability = new EditableLookupCapability( | ||||
|                     mockContext, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     factory, | ||||
|                     false | ||||
|                 ); | ||||
|                 expect(capability.inheritedMethod()).toEqual("an inherited method"); | ||||
|                 expect(capability.hasOwnProperty('inheritedMethod')).toBe(true); | ||||
|                 // The presence of an own property indicates that the method | ||||
|                 // has been wrapped on the object itself and this is a valid | ||||
|                 // test that the inherited method has been wrapped. | ||||
|             }); | ||||
|  | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -1,96 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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,describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ["../../src/capabilities/EditablePersistenceCapability"], | ||||
|     function (EditablePersistenceCapability) { | ||||
|         "use strict"; | ||||
|  | ||||
|         describe("An editable persistence capability", function () { | ||||
|             var mockPersistence, | ||||
|                 mockEditableObject, | ||||
|                 mockDomainObject, | ||||
|                 mockCache, | ||||
|                 mockPromise, | ||||
|                 capability; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 mockPersistence = jasmine.createSpyObj( | ||||
|                     "persistence", | ||||
|                     [ "persist", "refresh" ] | ||||
|                 ); | ||||
|                 mockEditableObject = jasmine.createSpyObj( | ||||
|                     "editableObject", | ||||
|                     [ "getId", "getModel", "getCapability" ] | ||||
|                 ); | ||||
|                 mockDomainObject = jasmine.createSpyObj( | ||||
|                     "editableObject", | ||||
|                     [ "getId", "getModel", "getCapability" ] | ||||
|                 ); | ||||
|                 mockCache = jasmine.createSpyObj( | ||||
|                     "cache", | ||||
|                     [ "markDirty" ] | ||||
|                 ); | ||||
|                 mockPromise = jasmine.createSpyObj("promise", ["then"]); | ||||
|  | ||||
|                 mockCache.markDirty.andReturn(mockPromise); | ||||
|                 mockDomainObject.getCapability.andReturn(mockPersistence); | ||||
|  | ||||
|                 capability = new EditablePersistenceCapability( | ||||
|                     mockPersistence, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     mockCache | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
|             it("marks objects as dirty (in the cache) upon persist", function () { | ||||
|                 capability.persist(); | ||||
|                 expect(mockCache.markDirty) | ||||
|                     .toHaveBeenCalledWith(mockEditableObject); | ||||
|             }); | ||||
|  | ||||
|             it("does not invoke the underlying persistence capability", function () { | ||||
|                 capability.persist(); | ||||
|                 expect(mockPersistence.persist).not.toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("refreshes using the original domain object's persistence", function () { | ||||
|                 // Refreshing needs to delegate via the unwrapped domain object. | ||||
|                 // Otherwise, only the editable version of the object will be updated; | ||||
|                 // we instead want the real version of the object to receive these | ||||
|                 // changes. | ||||
|                 expect(mockDomainObject.getCapability).not.toHaveBeenCalled(); | ||||
|                 expect(mockPersistence.refresh).not.toHaveBeenCalled(); | ||||
|                 capability.refresh(); | ||||
|                 expect(mockDomainObject.getCapability).toHaveBeenCalledWith('persistence'); | ||||
|                 expect(mockPersistence.refresh).toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("returns a promise from persist", function () { | ||||
|                 expect(capability.persist().then).toEqual(jasmine.any(Function)); | ||||
|             }); | ||||
|  | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -1,75 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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,describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ["../../src/capabilities/EditableRelationshipCapability"], | ||||
|     function (EditableRelationshipCapability) { | ||||
|         "use strict"; | ||||
|  | ||||
|         describe("An editable relationship capability", function () { | ||||
|             var mockContext, | ||||
|                 mockEditableObject, | ||||
|                 mockDomainObject, | ||||
|                 mockTestObject, | ||||
|                 someValue, | ||||
|                 mockFactory, | ||||
|                 capability; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 // EditableContextCapability should watch ALL | ||||
|                 // methods for domain objects, so give it an | ||||
|                 // arbitrary interface to wrap. | ||||
|                 mockContext = | ||||
|                     jasmine.createSpyObj("context", [ "getDomainObject" ]); | ||||
|                 mockTestObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getModel", "getCapability" ] | ||||
|                 ); | ||||
|                 mockFactory = | ||||
|                     jasmine.createSpyObj("factory", ["getEditableObject"]); | ||||
|  | ||||
|                 someValue = { x: 42 }; | ||||
|  | ||||
|                 mockContext.getDomainObject.andReturn(mockTestObject); | ||||
|                 mockFactory.getEditableObject.andReturn(someValue); | ||||
|  | ||||
|                 capability = new EditableRelationshipCapability( | ||||
|                     mockContext, | ||||
|                     mockEditableObject, | ||||
|                     mockDomainObject, | ||||
|                     mockFactory | ||||
|                 ); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             // Most behavior is tested for EditableLookupCapability, | ||||
|             // so just verify that this isse | ||||
|             it("presumes non-idempotence of its wrapped capability", function () { | ||||
|                 expect(capability.getDomainObject()) | ||||
|                     .toEqual(capability.getDomainObject()); | ||||
|                 expect(mockContext.getDomainObject.calls.length).toEqual(2); | ||||
|             }); | ||||
|  | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -1,180 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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,describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ["../../src/objects/EditableDomainObjectCache"], | ||||
|     function (EditableDomainObjectCache) { | ||||
|         'use strict'; | ||||
|  | ||||
|         describe("Editable domain object cache", function () { | ||||
|  | ||||
|             var captured, | ||||
|                 completionCapability, | ||||
|                 object, | ||||
|                 mockQ, | ||||
|                 mockType, | ||||
|                 cache; | ||||
|  | ||||
|  | ||||
|             // Constructors for test objects | ||||
|             function TestObject(id) { | ||||
|                 return { | ||||
|                     getId: function () { return id; }, | ||||
|                     getModel: function () { return {}; }, | ||||
|                     getCapability: function (key) { | ||||
|                         return { | ||||
|                             editor: completionCapability, | ||||
|                             type: mockType | ||||
|                         }[key]; | ||||
|                     }, | ||||
|                     hasCapability: function (key) { | ||||
|                         return false; | ||||
|                     } | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             function WrapObject(domainObject, model) { | ||||
|                 var result = Object.create(domainObject); | ||||
|                 result.wrapped = true; | ||||
|                 result.wrappedModel = model; | ||||
|                 result.hasCapability = function (name) { | ||||
|                     return name === 'editor'; | ||||
|                 }; | ||||
|                 captured.wraps = (captured.wraps || 0) + 1; | ||||
|                 return result; | ||||
|             } | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 mockQ = jasmine.createSpyObj('$q', ['when', 'all']); | ||||
|                 mockType = jasmine.createSpyObj('type', ['hasFeature']); | ||||
|                 mockType.hasFeature.andReturn(true); | ||||
|                 captured = {}; | ||||
|                 completionCapability = { | ||||
|                     save: function () { | ||||
|                         captured.saved = (captured.saved || 0) + 1; | ||||
|                     } | ||||
|                 }; | ||||
|  | ||||
|                 cache = new EditableDomainObjectCache(WrapObject, mockQ); | ||||
|             }); | ||||
|  | ||||
|             it("wraps objects using provided constructor", function () { | ||||
|                 var domainObject = new TestObject('test-id'), | ||||
|                     wrappedObject = cache.getEditableObject(domainObject); | ||||
|                 expect(wrappedObject.wrapped).toBeTruthy(); | ||||
|                 expect(wrappedObject.getId()).toEqual(domainObject.getId()); | ||||
|             }); | ||||
|  | ||||
|             it("wraps objects repeatedly, wraps models once", function () { | ||||
|                 var domainObject = new TestObject('test-id'), | ||||
|                     wrappedObjects = []; | ||||
|  | ||||
|                 // Verify precondition | ||||
|                 expect(captured.wraps).toBeUndefined(); | ||||
|  | ||||
|                 // Invoke a few more times; expect count not to increment | ||||
|                 wrappedObjects.push(cache.getEditableObject(domainObject)); | ||||
|                 expect(captured.wraps).toEqual(1); | ||||
|                 wrappedObjects.push(cache.getEditableObject(domainObject)); | ||||
|                 expect(captured.wraps).toEqual(2); | ||||
|                 wrappedObjects.push(cache.getEditableObject(domainObject)); | ||||
|                 expect(captured.wraps).toEqual(3); | ||||
|  | ||||
|                 // Verify that the last call still gave us a wrapped object | ||||
|                 expect(wrappedObjects[0].wrapped).toBeTruthy(); | ||||
|                 expect(wrappedObjects[0].getId()).toEqual(domainObject.getId()); | ||||
|  | ||||
|                 // Verify that objects are distinct but models are identical | ||||
|                 expect(wrappedObjects[0].wrappedModel) | ||||
|                     .toBe(wrappedObjects[1].wrappedModel); | ||||
|                 expect(wrappedObjects[0]).not | ||||
|                     .toBe(wrappedObjects[1]); | ||||
|             }); | ||||
|  | ||||
|             it("saves objects that have been marked dirty", function () { | ||||
|                 var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) { | ||||
|                     return cache.getEditableObject(domainObject); | ||||
|                 }); | ||||
|  | ||||
|                 cache.markDirty(objects[0]); | ||||
|                 cache.markDirty(objects[2]); | ||||
|  | ||||
|                 cache.saveAll(); | ||||
|  | ||||
|                 expect(captured.saved).toEqual(2); | ||||
|             }); | ||||
|  | ||||
|             it("does not save objects that have been marked clean", function () { | ||||
|                 var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) { | ||||
|                     return cache.getEditableObject(domainObject); | ||||
|                 }); | ||||
|  | ||||
|                 cache.markDirty(objects[0]); | ||||
|                 cache.markDirty(objects[2]); | ||||
|                 cache.markClean(objects[0]); | ||||
|  | ||||
|                 cache.saveAll(); | ||||
|  | ||||
|                 expect(captured.saved).toEqual(1); | ||||
|             }); | ||||
|  | ||||
|             it("tracks the root object of the Edit mode subgraph", function () { | ||||
|                 // Root object is the first object exposed to the cache | ||||
|                 var domainObjects = ['a', 'b', 'c'].map(TestObject); | ||||
|                 domainObjects.forEach(function (obj) { | ||||
|                     cache.getEditableObject(obj); | ||||
|                 }); | ||||
|                 expect(cache.isRoot(domainObjects[0])).toBeTruthy(); | ||||
|                 expect(cache.isRoot(domainObjects[1])).toBeFalsy(); | ||||
|                 expect(cache.isRoot(domainObjects[2])).toBeFalsy(); | ||||
|             }); | ||||
|  | ||||
|             it("does not double-wrap objects", function () { | ||||
|                 var domainObject = new TestObject('test-id'), | ||||
|                     wrappedObject = cache.getEditableObject(domainObject); | ||||
|  | ||||
|                 // Same instance should be returned if you try to wrap | ||||
|                 // twice. This is necessary, since it's possible to (e.g.) | ||||
|                 // use a context capability on an object retrieved via | ||||
|                 // composition, in which case a result will already be | ||||
|                 // wrapped. | ||||
|                 expect(cache.getEditableObject(wrappedObject)) | ||||
|                     .toBe(wrappedObject); | ||||
|             }); | ||||
|  | ||||
|             it("does not wrap non-editable objects", function () { | ||||
|                 var domainObject = new TestObject('test-id'); | ||||
|  | ||||
|                 mockType.hasFeature.andCallFake(function (key) { | ||||
|                     return key !== 'creation'; | ||||
|                 }); | ||||
|  | ||||
|                 expect(cache.getEditableObject(domainObject)) | ||||
|                     .toBe(domainObject); | ||||
|             }); | ||||
|  | ||||
|  | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| ); | ||||
| @@ -1,81 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * 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,describe,it,expect,beforeEach,jasmine*/ | ||||
|  | ||||
| define( | ||||
|     ["../../src/objects/EditableModelCache"], | ||||
|     function (EditableModelCache) { | ||||
|         "use strict"; | ||||
|  | ||||
|         describe("The editable model cache", function () { | ||||
|             var mockObject, | ||||
|                 mockOtherObject, | ||||
|                 testModel, | ||||
|                 testId, | ||||
|                 otherModel, | ||||
|                 otherId, | ||||
|                 cache; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 testId = "test"; | ||||
|                 testModel = { someKey: "some value" }; | ||||
|                 otherId = "other"; | ||||
|                 otherModel = { someKey: "some other value" }; | ||||
|  | ||||
|                 mockObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getModel" ] | ||||
|                 ); | ||||
|                 mockOtherObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getModel" ] | ||||
|                 ); | ||||
|  | ||||
|                 mockObject.getId.andReturn(testId); | ||||
|                 mockObject.getModel.andReturn(testModel); | ||||
|                 mockOtherObject.getId.andReturn(otherId); | ||||
|                 mockOtherObject.getModel.andReturn(otherModel); | ||||
|  | ||||
|                 cache = new EditableModelCache(); | ||||
|             }); | ||||
|  | ||||
|             it("provides clones of domain object models", function () { | ||||
|                 var model = cache.getCachedModel(mockObject); | ||||
|                 // Should be identical... | ||||
|                 expect(model).toEqual(testModel); | ||||
|                 // ...but not pointer-identical | ||||
|                 expect(model).not.toBe(testModel); | ||||
|             }); | ||||
|  | ||||
|             it("provides only one clone per object", function () { | ||||
|                 var model = cache.getCachedModel(mockObject); | ||||
|                 expect(cache.getCachedModel(mockObject)).toBe(model); | ||||
|             }); | ||||
|  | ||||
|             it("maintains separate caches per-object", function () { | ||||
|                 expect(cache.getCachedModel(mockObject)) | ||||
|                     .not.toEqual(cache.getCachedModel(mockOtherObject)); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|     } | ||||
| ); | ||||
| @@ -48,7 +48,11 @@ define( | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             $scope.regions = filterRegions(typeCapability.getDefinition().inspector || new InspectorRegion()); | ||||
|             function setRegions() { | ||||
|                 $scope.regions = filterRegions(typeCapability.getDefinition().inspector || new InspectorRegion()); | ||||
|             } | ||||
|  | ||||
|             setRegions(); | ||||
|         } | ||||
|  | ||||
|         return InspectorController; | ||||
|   | ||||
| @@ -173,13 +173,10 @@ define( | ||||
|                 }, modified); | ||||
|             } | ||||
|  | ||||
|             // Only update if we don't have unsaved changes | ||||
|             return (model.modified === model.persisted) ? | ||||
|                 this.persistenceService.readObject( | ||||
|             return this.persistenceService.readObject( | ||||
|                     this.getSpace(), | ||||
|                     this.domainObject.getId() | ||||
|                 ).then(updateModel) : | ||||
|                 fastPromise(false); | ||||
|                 ).then(updateModel); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -41,9 +41,10 @@ define( | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             // Check if we are in edit mode | ||||
|             function inEditMode() { | ||||
|                 return swimlane.domainObject.hasCapability("editor"); | ||||
|             // Check if we are in edit mode (also check parents) | ||||
|             function inEditMode(swimlane) { | ||||
|                 return swimlane.domainObject.hasCapability('editor') && | ||||
|                     swimlane.domainObject.getCapability('editor').isEditing(); | ||||
|             } | ||||
|  | ||||
|             // Boolean and (for reduce below) | ||||
| @@ -175,7 +176,7 @@ define( | ||||
|                  * @returns {boolean} true if this should be allowed | ||||
|                  */ | ||||
|                 allowDropIn: function (id, domainObject) { | ||||
|                     return inEditMode() && | ||||
|                     return inEditMode(swimlane) && | ||||
|                         !pathContains(swimlane, id) && | ||||
|                         !contains(swimlane, id) && | ||||
|                         canDrop(swimlane.domainObject, domainObject); | ||||
| @@ -190,7 +191,7 @@ define( | ||||
|                 allowDropAfter: function (id, domainObject) { | ||||
|                     var target = expandedForDropInto() ? | ||||
|                             swimlane : swimlane.parent; | ||||
|                     return inEditMode() && | ||||
|                     return inEditMode(swimlane) && | ||||
|                         target && | ||||
|                         !pathContains(target, id) && | ||||
|                         canDrop(target.domainObject, domainObject); | ||||
|   | ||||
| @@ -56,7 +56,8 @@ define( | ||||
|          */ | ||||
|         function MCTRepresentation(representations, views, representers, $q, templateLinker, $log) { | ||||
|             var representationMap = {}, | ||||
|                 gestureMap = {}; | ||||
|                 gestureMap = {}, | ||||
|                 listeners = 0; | ||||
|  | ||||
|             // Assemble all representations and views | ||||
|             // The distinction between views and representations is | ||||
| @@ -94,6 +95,7 @@ define( | ||||
|                     couldEdit = false, | ||||
|                     lastIdPath = [], | ||||
|                     lastKey, | ||||
|                     statusListener, | ||||
|                     changeTemplate = templateLinker.link($scope, element); | ||||
|  | ||||
|                 // Populate scope with any capabilities indicated by the | ||||
| @@ -170,7 +172,7 @@ define( | ||||
|                         representation = lookup($scope.key, domainObject), | ||||
|                         uses = ((representation || {}).uses || []), | ||||
|                         canRepresent = !!(representation && domainObject), | ||||
|                         canEdit = !!(domainObject && domainObject.hasCapability('editor')), | ||||
|                         canEdit = !!(domainObject && domainObject.hasCapability('editor') && domainObject.getCapability('editor').isEditing()), | ||||
|                         idPath = getIdPath(domainObject), | ||||
|                         key = $scope.key; | ||||
|  | ||||
| @@ -242,6 +244,25 @@ define( | ||||
|                 // (to a different object) | ||||
|                 $scope.$watch("domainObject", refresh); | ||||
|  | ||||
|                 function listenForStatusChange(object) { | ||||
|                     if (statusListener) { | ||||
|                         statusListener(); | ||||
|                     } | ||||
|                     statusListener = object.getCapability("status").listen(refresh); | ||||
|                 } | ||||
|  | ||||
|                 /** | ||||
|                  * Add a listener for status changes to the object itself. | ||||
|                  */ | ||||
|                 $scope.$watch("domainObject", function(domainObject, oldDomainObject) { | ||||
|                     if (domainObject!==oldDomainObject){ | ||||
|                         listenForStatusChange(domainObject); | ||||
|                     } | ||||
|                 }); | ||||
|                 if ($scope.domainObject) { | ||||
|                     listenForStatusChange($scope.domainObject); | ||||
|                 } | ||||
|  | ||||
|                 // Finally, also update when there is a new version of that | ||||
|                 // same domain object; these changes should be tracked in the | ||||
|                 // model's "modified" field, by the mutation capability. | ||||
| @@ -250,6 +271,11 @@ define( | ||||
|                 // Make sure any resources allocated by representers also get | ||||
|                 // released. | ||||
|                 $scope.$on("$destroy", destroyRepresenters); | ||||
|                 $scope.$on("$destroy", function () { | ||||
|                     if (statusListener) { | ||||
|                         statusListener(); | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 // Do one initial refresh, so that we don't need another | ||||
|                 // digest iteration just to populate the scope. Failure to | ||||
|   | ||||
| @@ -25,9 +25,8 @@ | ||||
|  * Module defining DropGesture. Created by vwoeltje on 11/17/14. | ||||
|  */ | ||||
| define( | ||||
|     ['./GestureConstants', | ||||
|      '../../../commonUI/edit/src/objects/EditableDomainObject'], | ||||
|     function (GestureConstants, EditableDomainObject) { | ||||
|     ['./GestureConstants'], | ||||
|     function (GestureConstants) { | ||||
|         "use strict"; | ||||
|  | ||||
|         /** | ||||
| @@ -43,7 +42,6 @@ define( | ||||
|          */ | ||||
|         function DropGesture(dndService, $q, navigationService, instantiate, typeService, element, domainObject) { | ||||
|             var actionCapability = domainObject.getCapability('action'), | ||||
|                 editableDomainObject, | ||||
|                 scope = element.scope && element.scope(), | ||||
|                 action; // Action for the drop, when it occurs | ||||
|              | ||||
| @@ -68,30 +66,13 @@ define( | ||||
|                             x: event.pageX - rect.left, | ||||
|                             y: event.pageY - rect.top | ||||
|                         }, | ||||
|                         editableDomainObject | ||||
|                         domainObject | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             function canCompose(domainObject, selectedObject){ | ||||
|                 return domainObject.getCapability("action").getActions({ | ||||
|                     key: 'compose', | ||||
|                     selectedObject: selectedObject | ||||
|                 }).length > 0; | ||||
|             } | ||||
|  | ||||
|             function dragOver(e) { | ||||
|                 //Refresh domain object on each dragOver to catch external | ||||
|                 // updates to the model | ||||
|                 //Don't use EditableDomainObject for folders, allow immediate persistence | ||||
|                 if (domainObject.hasCapability('editor') || | ||||
|                     domainObject.getModel().type==='folder') { | ||||
|                     editableDomainObject = domainObject; | ||||
|                 } else { | ||||
|                     editableDomainObject = new EditableDomainObject(domainObject, $q); | ||||
|                 } | ||||
|  | ||||
|                 actionCapability = editableDomainObject.getCapability('action'); | ||||
|                 actionCapability = domainObject.getCapability('action'); | ||||
|  | ||||
|                 var event = (e || {}).originalEvent || e, | ||||
|                     selectedObject = dndService.getData( | ||||
| @@ -117,18 +98,18 @@ define( | ||||
|             function drop(e) { | ||||
|                 var event = (e || {}).originalEvent || e, | ||||
|                     id = event.dataTransfer.getData(GestureConstants.MCT_DRAG_TYPE), | ||||
|                     domainObjectType = editableDomainObject.getModel().type; | ||||
|                     domainObjectType = domainObject.getModel().type; | ||||
|  | ||||
|                 // Handle the drop; add the dropped identifier to the | ||||
|                 // destination domain object's composition, and persist | ||||
|                 // the change. | ||||
|                 if (id) { | ||||
|                     e.preventDefault(); | ||||
|                     $q.when(action && action.perform()).then(function (result) { | ||||
|                         //Don't go into edit mode for folders | ||||
|                         if (domainObjectType!=='folder') { | ||||
|                             editableDomainObject.getCapability('action').perform('edit'); | ||||
|                         } | ||||
|                     if (domainObjectType!=='folder') { | ||||
|                         domainObject.getCapability('action').perform('edit'); | ||||
|                     } | ||||
|  | ||||
|                     $q.when(action && action.perform()).then(function () { | ||||
|                         broadcastDrop(id, event); | ||||
|                     }); | ||||
|                 } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user