From a11dba88b239e0be0d46ac3bb158d62d65ffc1e3 Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 12 May 2016 20:23:33 -0700 Subject: [PATCH 01/11] [New Edit Mode] #634 Removed edit concerns from MctRepresentation --- .../regions/src/InspectorController.js | 8 +++- .../regions/test/InspectorControllerSpec.js | 39 +++++++++++++++++-- .../representation/src/MCTRepresentation.js | 29 ++------------ .../test/MCTRepresentationSpec.js | 15 ------- 4 files changed, 45 insertions(+), 46 deletions(-) diff --git a/platform/commonUI/regions/src/InspectorController.js b/platform/commonUI/regions/src/InspectorController.js index 32b0e1903d..89b88d4b15 100644 --- a/platform/commonUI/regions/src/InspectorController.js +++ b/platform/commonUI/regions/src/InspectorController.js @@ -32,7 +32,8 @@ define( */ function InspectorController($scope, policyService) { var domainObject = $scope.domainObject, - typeCapability = domainObject.getCapability('type'); + typeCapability = domainObject.getCapability('type'), + statusListener; /** * Filters region parts to only those allowed by region policies @@ -50,6 +51,11 @@ define( $scope.regions = filterRegions(typeCapability.getDefinition().inspector || new InspectorRegion()); } + statusListener = domainObject.getCapability("status").listen(setRegions); + $scope.$on("$destroy", function () { + statusListener(); + }); + setRegions(); } diff --git a/platform/commonUI/regions/test/InspectorControllerSpec.js b/platform/commonUI/regions/test/InspectorControllerSpec.js index ad3243c348..9d815e2851 100644 --- a/platform/commonUI/regions/test/InspectorControllerSpec.js +++ b/platform/commonUI/regions/test/InspectorControllerSpec.js @@ -30,6 +30,8 @@ define( mockTypeCapability, mockTypeDefinition, mockPolicyService, + mockStatusCapability, + capabilities = {}, controller; beforeEach(function(){ @@ -47,19 +49,29 @@ define( 'getDefinition' ]); mockTypeCapability.getDefinition.andReturn(mockTypeDefinition); + capabilities.type = mockTypeCapability; + + mockStatusCapability = jasmine.createSpyObj('statusCapability', [ + 'listen' + ]); + capabilities.status = mockStatusCapability; mockDomainObject = jasmine.createSpyObj('domainObject', [ 'getCapability' ]); - mockDomainObject.getCapability.andReturn(mockTypeCapability); + mockDomainObject.getCapability.andCallFake(function (name) { + return capabilities[name]; + }); mockPolicyService = jasmine.createSpyObj('policyService', [ 'allow' ]); - mockScope = { - domainObject: mockDomainObject - }; + mockScope = jasmine.createSpyObj('$scope', + ['$on'] + ); + + mockScope.domainObject = mockDomainObject; }); it("filters out regions disallowed by region policy", function() { @@ -73,6 +85,25 @@ define( controller = new InspectorController(mockScope, mockPolicyService); expect(mockScope.regions.length).toBe(2); }); + + it("Responds to status changes", function() { + mockPolicyService.allow.andReturn(true); + controller = new InspectorController(mockScope, mockPolicyService); + expect(mockScope.regions.length).toBe(2); + expect(mockStatusCapability.listen).toHaveBeenCalled(); + mockPolicyService.allow.andReturn(false); + mockStatusCapability.listen.mostRecentCall.args[0](); + expect(mockScope.regions.length).toBe(0); + }); + + it("Unregisters status listener", function() { + var mockListener = jasmine.createSpy('listener'); + mockStatusCapability.listen.andReturn(mockListener); + controller = new InspectorController(mockScope, mockPolicyService); + expect(mockScope.$on).toHaveBeenCalledWith("$destroy", jasmine.any(Function)); + mockScope.$on.mostRecentCall.args[1](); + expect(mockListener).toHaveBeenCalled(); + }); }); } ); diff --git a/platform/representation/src/MCTRepresentation.js b/platform/representation/src/MCTRepresentation.js index bcaa90e4e7..331139b793 100644 --- a/platform/representation/src/MCTRepresentation.js +++ b/platform/representation/src/MCTRepresentation.js @@ -88,7 +88,6 @@ define( toClear = [], // Properties to clear out of scope on change counter = 0, couldRepresent = false, - couldEdit = false, lastIdPath = [], lastKey, statusListener, @@ -137,14 +136,13 @@ define( }); } - function unchanged(canRepresent, canEdit, idPath, key) { + function unchanged(canRepresent, idPath, key) { return (canRepresent === couldRepresent) && (key === lastKey) && (idPath.length === lastIdPath.length) && idPath.every(function (id, i) { return id === lastIdPath[i]; - }) && - (canEdit === couldEdit); + }); } function getIdPath(domainObject) { @@ -168,11 +166,10 @@ define( representation = lookup($scope.key, domainObject), uses = ((representation || {}).uses || []), canRepresent = !!(representation && domainObject), - canEdit = !!(domainObject && domainObject.hasCapability('editor') && domainObject.getCapability('editor').inEditContext()), idPath = getIdPath(domainObject), key = $scope.key; - if (unchanged(canRepresent, canEdit, idPath, key)) { + if (unchanged(canRepresent, idPath, key)) { return; } @@ -201,7 +198,6 @@ define( // To allow simplified change detection next time around couldRepresent = canRepresent; lastIdPath = idPath; - couldEdit = canEdit; lastKey = key; // Populate scope with fields associated with the current @@ -240,25 +236,6 @@ define( // (to a different object) $scope.$watch("domainObject", refresh); - function listenForStatusChange(object) { - if (statusListener) { - statusListener(); - } - statusListener = object.getCapability("status").listen(refresh); - } - - /** - * Add a listener to the object for status changes. - */ - $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. diff --git a/platform/representation/test/MCTRepresentationSpec.js b/platform/representation/test/MCTRepresentationSpec.js index 52d6c70d55..b5e78fec2a 100644 --- a/platform/representation/test/MCTRepresentationSpec.js +++ b/platform/representation/test/MCTRepresentationSpec.js @@ -253,21 +253,6 @@ define( expect(mockScope.testCapability).toBeUndefined(); }); - it("registers a status change listener", function () { - mockScope.$watch.calls[2].args[1](mockDomainObject); - expect(mockStatusCapability.listen).toHaveBeenCalled(); - }); - - it("unlistens for status change on scope destruction", function () { - var mockUnlistener = jasmine.createSpy("unlisten"); - mockStatusCapability.listen.andReturn(mockUnlistener); - mockScope.$watch.calls[2].args[1](mockDomainObject); - expect(mockStatusCapability.listen).toHaveBeenCalled(); - - mockScope.$on.calls[1].args[1](); - expect(mockUnlistener).toHaveBeenCalled(); - }); - describe("when a domain object has been observed", function () { var mockContext, mockContext2, From 54a0de4a08868b637f2937e1e136ebadcde3c40b Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 13 May 2016 13:45:14 -0700 Subject: [PATCH 02/11] [New Edit Mode] #636 Removed edit concerns from DropGesture --- platform/commonUI/edit/bundle.js | 6 +++--- .../{LinkAction.js => EditAndComposeAction.js} | 10 +++++++--- ...ctionSpec.js => EditAndComposeActionSpec.js} | 17 +++++++++++++---- .../representation/src/gestures/DropGesture.js | 13 +------------ 4 files changed, 24 insertions(+), 22 deletions(-) rename platform/commonUI/edit/src/actions/{LinkAction.js => EditAndComposeAction.js} (87%) rename platform/commonUI/edit/test/actions/{LinkActionSpec.js => EditAndComposeActionSpec.js} (87%) diff --git a/platform/commonUI/edit/bundle.js b/platform/commonUI/edit/bundle.js index fb357c0934..3d00dd80df 100644 --- a/platform/commonUI/edit/bundle.js +++ b/platform/commonUI/edit/bundle.js @@ -26,7 +26,7 @@ define([ "./src/controllers/ElementsController", "./src/controllers/EditObjectController", "./src/directives/MCTBeforeUnload", - "./src/actions/LinkAction", + "./src/actions/EditAndComposeAction", "./src/actions/EditAction", "./src/actions/PropertiesAction", "./src/actions/RemoveAction", @@ -55,7 +55,7 @@ define([ ElementsController, EditObjectController, MCTBeforeUnload, - LinkAction, + EditAndComposeAction, EditAction, PropertiesAction, RemoveAction, @@ -126,7 +126,7 @@ define([ "actions": [ { "key": "compose", - "implementation": LinkAction + "implementation": EditAndComposeAction }, { "key": "edit", diff --git a/platform/commonUI/edit/src/actions/LinkAction.js b/platform/commonUI/edit/src/actions/EditAndComposeAction.js similarity index 87% rename from platform/commonUI/edit/src/actions/LinkAction.js rename to platform/commonUI/edit/src/actions/EditAndComposeAction.js index f12539b1fe..974ab2f001 100644 --- a/platform/commonUI/edit/src/actions/LinkAction.js +++ b/platform/commonUI/edit/src/actions/EditAndComposeAction.js @@ -31,12 +31,12 @@ define( * @memberof platform/commonUI/edit * @implements {Action} */ - function LinkAction(context) { + function EditAndComposeAction(context) { this.domainObject = (context || {}).domainObject; this.selectedObject = (context || {}).selectedObject; } - LinkAction.prototype.perform = function () { + EditAndComposeAction.prototype.perform = function () { var self = this; // Persist changes to the domain object @@ -54,9 +54,13 @@ define( .then(doPersist); } + if (this.domainObject.getCapability('type').getKey() !== 'folder') { + this.domainObject.getCapability('action').perform('edit'); + } + return this.selectedObject && doLink(); }; - return LinkAction; + return EditAndComposeAction; } ); diff --git a/platform/commonUI/edit/test/actions/LinkActionSpec.js b/platform/commonUI/edit/test/actions/EditAndComposeActionSpec.js similarity index 87% rename from platform/commonUI/edit/test/actions/LinkActionSpec.js rename to platform/commonUI/edit/test/actions/EditAndComposeActionSpec.js index 144dd4e395..a02c259fd1 100644 --- a/platform/commonUI/edit/test/actions/LinkActionSpec.js +++ b/platform/commonUI/edit/test/actions/EditAndComposeActionSpec.js @@ -21,8 +21,8 @@ *****************************************************************************/ define( - ["../../src/actions/LinkAction"], - function (LinkAction) { + ["../../src/actions/EditAndComposeAction"], + function (EditAndComposeAction) { describe("The Link action", function () { var mockQ, @@ -31,6 +31,7 @@ define( mockContext, mockComposition, mockPersistence, + mockActionCapability, mockType, actionContext, model, @@ -67,18 +68,21 @@ define( mockContext = jasmine.createSpyObj("context", [ "getParent" ]); mockComposition = jasmine.createSpyObj("composition", [ "invoke", "add" ]); mockPersistence = jasmine.createSpyObj("persistence", [ "persist" ]); - mockType = jasmine.createSpyObj("type", [ "hasFeature" ]); + mockType = jasmine.createSpyObj("type", [ "hasFeature", "getKey" ]); + mockActionCapability = jasmine.createSpyObj("actionCapability", [ "perform"]); mockDomainObject.getId.andReturn("test"); mockDomainObject.getCapability.andReturn(mockContext); mockContext.getParent.andReturn(mockParent); mockType.hasFeature.andReturn(true); + mockType.getKey.andReturn("layout"); mockComposition.invoke.andReturn(mockPromise(true)); mockComposition.add.andReturn(mockPromise(true)); capabilities = { composition: mockComposition, persistence: mockPersistence, + action: mockActionCapability, type: mockType }; model = { @@ -90,7 +94,7 @@ define( selectedObject: mockDomainObject }; - action = new LinkAction(actionContext); + action = new EditAndComposeAction(actionContext); }); @@ -105,6 +109,11 @@ define( expect(mockPersistence.persist).toHaveBeenCalled(); }); + it("enables edit mode", function () { + action.perform(); + expect(mockActionCapability.perform).toHaveBeenCalledWith("edit"); + }); + }); } ); diff --git a/platform/representation/src/gestures/DropGesture.js b/platform/representation/src/gestures/DropGesture.js index f2d64024a3..f76d163ad4 100644 --- a/platform/representation/src/gestures/DropGesture.js +++ b/platform/representation/src/gestures/DropGesture.js @@ -54,9 +54,6 @@ define( // ...and broadcast the event. This allows specific // views to have post-drop behavior which depends on // drop position. - // Also broadcast the editableDomainObject to - // avoid race condition against non-editable - // version in EditRepresenter scope.$broadcast( GestureConstants.MCT_DROP_EVENT, id, @@ -93,21 +90,13 @@ define( function drop(e) { var event = (e || {}).originalEvent || e, - id = event.dataTransfer.getData(GestureConstants.MCT_DRAG_TYPE), - domainObjectType = domainObject.getModel().type; + id = event.dataTransfer.getData(GestureConstants.MCT_DRAG_TYPE); // Handle the drop; add the dropped identifier to the // destination domain object's composition, and persist // the change. if (id) { e.preventDefault(); - - //Use scope.apply, drop event is outside digest cycle - scope.$apply(function () { - if (domainObjectType !== 'folder') { - domainObject.getCapability('action').perform('edit'); - } - }); $q.when(action && action.perform()).then(function () { broadcastDrop(id, event); }); From bcdd8352750a626108784e7d20808e523b38dd37 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 18 May 2016 16:59:23 -0700 Subject: [PATCH 03/11] [Website] Automate site build process --- build-docs.sh | 27 +++++++++++++-------------- circle.yml | 6 ++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/build-docs.sh b/build-docs.sh index c318a0dbda..5b94f65d13 100755 --- a/build-docs.sh +++ b/build-docs.sh @@ -25,14 +25,15 @@ # Script to build and deploy docs to github pages. OUTPUT_DIRECTORY="target/docs" -REPOSITORY_URL="git@github.com:nasa/openmctweb.git" +REPOSITORY_URL="git@github.com:nasa/openmct-website.git" +WEBSITE_DIRECTORY="website" BUILD_SHA=`git rev-parse head` # A remote will be created for the git repository we are pushing to. # Don't worry, as this entire directory will get trashed inbetween builds. REMOTE_NAME="documentation" -WEBSITE_BRANCH="gh-pages" +WEBSITE_BRANCH="master" # Clean output directory, JSDOC will recreate if [ -d $OUTPUT_DIRECTORY ]; then @@ -40,23 +41,21 @@ if [ -d $OUTPUT_DIRECTORY ]; then fi npm run docs -cd $OUTPUT_DIRECTORY || exit 1 -echo "git init" -git init +echo "git clone $REPOSITORY_URL website" +git clone $REPOSITORY_URL website +echo "cp -r $OUTPUT_DIRECTORY $WEBSITE_DIRECTORY/docs" +cp -r $OUTPUT_DIRECTORY $WEBSITE_DIRECTORY/docs +echo "cd $WEBSITE_DIRECTORY" +cd $WEBSITE_DIRECTORY # Configure github for CircleCI user. git config user.email "buildbot@circleci.com" git config user.name "BuildBot" -echo "git remote add $REMOTE_NAME $REPOSITORY_URL" -git remote add $REMOTE_NAME $REPOSITORY_URL echo "git add ." git add . -echo "git commit -m \"Generate docs from build $BUILD_SHA\"" -git commit -m "Generate docs from build $BUILD_SHA" - -echo "git push $REMOTE_NAME HEAD:$WEBSITE_BRANCH -f" -git push $REMOTE_NAME HEAD:$WEBSITE_BRANCH -f - -echo "Documentation pushed to gh-pages branch." +echo "git commit -m \"Docs updated from build build $BUILD_SHA\"" +git commit -m "Docs updated from build build $BUILD_SHA" +echo "git push" +git push diff --git a/circle.yml b/circle.yml index 472fdf7c17..aba013d239 100644 --- a/circle.yml +++ b/circle.yml @@ -3,6 +3,12 @@ deployment: branch: master heroku: appname: openmctweb-demo + website: + branch: openmct-website + commands: + - git clone + - git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master + openmct-demo: branch: live_demo heroku: From b2c6db6207069488958e57f69eb9ab567d917316 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 18 May 2016 17:00:16 -0700 Subject: [PATCH 04/11] Changed circleci.yml --- build-docs.sh | 6 ++---- circle.yml | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/build-docs.sh b/build-docs.sh index 5b94f65d13..abdb7bbdbd 100755 --- a/build-docs.sh +++ b/build-docs.sh @@ -43,11 +43,11 @@ fi npm run docs echo "git clone $REPOSITORY_URL website" -git clone $REPOSITORY_URL website +git clone $REPOSITORY_URL website || exit 1 echo "cp -r $OUTPUT_DIRECTORY $WEBSITE_DIRECTORY/docs" cp -r $OUTPUT_DIRECTORY $WEBSITE_DIRECTORY/docs echo "cd $WEBSITE_DIRECTORY" -cd $WEBSITE_DIRECTORY +cd $WEBSITE_DIRECTORY || exit 1 # Configure github for CircleCI user. git config user.email "buildbot@circleci.com" @@ -57,5 +57,3 @@ echo "git add ." git add . echo "git commit -m \"Docs updated from build build $BUILD_SHA\"" git commit -m "Docs updated from build build $BUILD_SHA" -echo "git push" -git push diff --git a/circle.yml b/circle.yml index aba013d239..5ed3bf7147 100644 --- a/circle.yml +++ b/circle.yml @@ -6,9 +6,8 @@ deployment: website: branch: openmct-website commands: - - git clone - - git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master - + - npm install canvas nomnoml + - ./build-docs.sh openmct-demo: branch: live_demo heroku: From edb158f2d345b3621e768dd30320388611bd6f67 Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 19 May 2016 10:30:28 -0700 Subject: [PATCH 05/11] [Website] Added push to website repo --- build-docs.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build-docs.sh b/build-docs.sh index abdb7bbdbd..9fdfdc91d3 100755 --- a/build-docs.sh +++ b/build-docs.sh @@ -57,3 +57,4 @@ echo "git add ." git add . echo "git commit -m \"Docs updated from build build $BUILD_SHA\"" git commit -m "Docs updated from build build $BUILD_SHA" +git push From 516b8c9e38a668619ae93be4093954241088d99d Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 19 May 2016 10:36:58 -0700 Subject: [PATCH 06/11] [Website] #901 Automate build process - Updated build SHA --- build-docs.sh | 10 ++++++---- circle.yml | 6 ++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build-docs.sh b/build-docs.sh index 9fdfdc91d3..87ada35524 100755 --- a/build-docs.sh +++ b/build-docs.sh @@ -22,13 +22,14 @@ #* at runtime from the About dialog for additional information. #***************************************************************************** -# Script to build and deploy docs to github pages. +# Script to build and deploy docs. OUTPUT_DIRECTORY="target/docs" +# Docs, once built, are pushed to the private website repo REPOSITORY_URL="git@github.com:nasa/openmct-website.git" WEBSITE_DIRECTORY="website" -BUILD_SHA=`git rev-parse head` +BUILD_SHA=`git rev-parse HEAD` # A remote will be created for the git repository we are pushing to. # Don't worry, as this entire directory will get trashed inbetween builds. @@ -55,6 +56,7 @@ git config user.name "BuildBot" echo "git add ." git add . -echo "git commit -m \"Docs updated from build build $BUILD_SHA\"" -git commit -m "Docs updated from build build $BUILD_SHA" +echo "git commit -m \"Docs updated from build $BUILD_SHA\"" +git commit -m "Docs updated from build $BUILD_SHA" +# Push to the website repo git push diff --git a/circle.yml b/circle.yml index 5ed3bf7147..db25ab22de 100644 --- a/circle.yml +++ b/circle.yml @@ -1,13 +1,11 @@ deployment: production: branch: master - heroku: - appname: openmctweb-demo - website: - branch: openmct-website commands: - npm install canvas nomnoml - ./build-docs.sh + heroku: + appname: openmctweb-demo openmct-demo: branch: live_demo heroku: From e4b192001f831457ef600c4dc669f5461fc77c22 Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 19 May 2016 12:14:42 -0700 Subject: [PATCH 07/11] Changed circle.yml to go back to command-based deployment to heroku as cannot use 'heroku' deployment support and commands in the same deployment descriptor --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index db25ab22de..3a671eaa72 100644 --- a/circle.yml +++ b/circle.yml @@ -4,8 +4,8 @@ deployment: commands: - npm install canvas nomnoml - ./build-docs.sh - heroku: - appname: openmctweb-demo + - git fetch--unshallow + - git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master openmct-demo: branch: live_demo heroku: From b7cfaf6b63483a634fed88293aa7e4534f326899 Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 19 May 2016 13:42:48 -0700 Subject: [PATCH 08/11] Fixed failed circle.yml command --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 3a671eaa72..bfc2e8fede 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,7 @@ deployment: commands: - npm install canvas nomnoml - ./build-docs.sh - - git fetch--unshallow + - git fetch --unshallow - git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master openmct-demo: branch: live_demo From 78bf804e02a94d2624ac6d8a0f2623ff7d91c631 Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 19 May 2016 15:24:14 -0700 Subject: [PATCH 09/11] [Build] Ignore gh-pages from circle-ci --- circle.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/circle.yml b/circle.yml index bfc2e8fede..7caa57740d 100644 --- a/circle.yml +++ b/circle.yml @@ -17,3 +17,8 @@ deployment: test: post: - gulp lint + +general: + branches: + ignore: + - gh-pages From 776586ae25fcd8a1f9c781f995ec63465f496dad Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 12 May 2016 20:23:33 -0700 Subject: [PATCH 10/11] [New Edit Mode] #634 Removed edit concerns from MctRepresentation --- .../regions/src/InspectorController.js | 8 +++- .../regions/test/InspectorControllerSpec.js | 39 +++++++++++++++++-- .../representation/src/MCTRepresentation.js | 29 ++------------ .../test/MCTRepresentationSpec.js | 15 ------- 4 files changed, 45 insertions(+), 46 deletions(-) diff --git a/platform/commonUI/regions/src/InspectorController.js b/platform/commonUI/regions/src/InspectorController.js index 32b0e1903d..89b88d4b15 100644 --- a/platform/commonUI/regions/src/InspectorController.js +++ b/platform/commonUI/regions/src/InspectorController.js @@ -32,7 +32,8 @@ define( */ function InspectorController($scope, policyService) { var domainObject = $scope.domainObject, - typeCapability = domainObject.getCapability('type'); + typeCapability = domainObject.getCapability('type'), + statusListener; /** * Filters region parts to only those allowed by region policies @@ -50,6 +51,11 @@ define( $scope.regions = filterRegions(typeCapability.getDefinition().inspector || new InspectorRegion()); } + statusListener = domainObject.getCapability("status").listen(setRegions); + $scope.$on("$destroy", function () { + statusListener(); + }); + setRegions(); } diff --git a/platform/commonUI/regions/test/InspectorControllerSpec.js b/platform/commonUI/regions/test/InspectorControllerSpec.js index ad3243c348..9d815e2851 100644 --- a/platform/commonUI/regions/test/InspectorControllerSpec.js +++ b/platform/commonUI/regions/test/InspectorControllerSpec.js @@ -30,6 +30,8 @@ define( mockTypeCapability, mockTypeDefinition, mockPolicyService, + mockStatusCapability, + capabilities = {}, controller; beforeEach(function(){ @@ -47,19 +49,29 @@ define( 'getDefinition' ]); mockTypeCapability.getDefinition.andReturn(mockTypeDefinition); + capabilities.type = mockTypeCapability; + + mockStatusCapability = jasmine.createSpyObj('statusCapability', [ + 'listen' + ]); + capabilities.status = mockStatusCapability; mockDomainObject = jasmine.createSpyObj('domainObject', [ 'getCapability' ]); - mockDomainObject.getCapability.andReturn(mockTypeCapability); + mockDomainObject.getCapability.andCallFake(function (name) { + return capabilities[name]; + }); mockPolicyService = jasmine.createSpyObj('policyService', [ 'allow' ]); - mockScope = { - domainObject: mockDomainObject - }; + mockScope = jasmine.createSpyObj('$scope', + ['$on'] + ); + + mockScope.domainObject = mockDomainObject; }); it("filters out regions disallowed by region policy", function() { @@ -73,6 +85,25 @@ define( controller = new InspectorController(mockScope, mockPolicyService); expect(mockScope.regions.length).toBe(2); }); + + it("Responds to status changes", function() { + mockPolicyService.allow.andReturn(true); + controller = new InspectorController(mockScope, mockPolicyService); + expect(mockScope.regions.length).toBe(2); + expect(mockStatusCapability.listen).toHaveBeenCalled(); + mockPolicyService.allow.andReturn(false); + mockStatusCapability.listen.mostRecentCall.args[0](); + expect(mockScope.regions.length).toBe(0); + }); + + it("Unregisters status listener", function() { + var mockListener = jasmine.createSpy('listener'); + mockStatusCapability.listen.andReturn(mockListener); + controller = new InspectorController(mockScope, mockPolicyService); + expect(mockScope.$on).toHaveBeenCalledWith("$destroy", jasmine.any(Function)); + mockScope.$on.mostRecentCall.args[1](); + expect(mockListener).toHaveBeenCalled(); + }); }); } ); diff --git a/platform/representation/src/MCTRepresentation.js b/platform/representation/src/MCTRepresentation.js index bcaa90e4e7..331139b793 100644 --- a/platform/representation/src/MCTRepresentation.js +++ b/platform/representation/src/MCTRepresentation.js @@ -88,7 +88,6 @@ define( toClear = [], // Properties to clear out of scope on change counter = 0, couldRepresent = false, - couldEdit = false, lastIdPath = [], lastKey, statusListener, @@ -137,14 +136,13 @@ define( }); } - function unchanged(canRepresent, canEdit, idPath, key) { + function unchanged(canRepresent, idPath, key) { return (canRepresent === couldRepresent) && (key === lastKey) && (idPath.length === lastIdPath.length) && idPath.every(function (id, i) { return id === lastIdPath[i]; - }) && - (canEdit === couldEdit); + }); } function getIdPath(domainObject) { @@ -168,11 +166,10 @@ define( representation = lookup($scope.key, domainObject), uses = ((representation || {}).uses || []), canRepresent = !!(representation && domainObject), - canEdit = !!(domainObject && domainObject.hasCapability('editor') && domainObject.getCapability('editor').inEditContext()), idPath = getIdPath(domainObject), key = $scope.key; - if (unchanged(canRepresent, canEdit, idPath, key)) { + if (unchanged(canRepresent, idPath, key)) { return; } @@ -201,7 +198,6 @@ define( // To allow simplified change detection next time around couldRepresent = canRepresent; lastIdPath = idPath; - couldEdit = canEdit; lastKey = key; // Populate scope with fields associated with the current @@ -240,25 +236,6 @@ define( // (to a different object) $scope.$watch("domainObject", refresh); - function listenForStatusChange(object) { - if (statusListener) { - statusListener(); - } - statusListener = object.getCapability("status").listen(refresh); - } - - /** - * Add a listener to the object for status changes. - */ - $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. diff --git a/platform/representation/test/MCTRepresentationSpec.js b/platform/representation/test/MCTRepresentationSpec.js index 52d6c70d55..b5e78fec2a 100644 --- a/platform/representation/test/MCTRepresentationSpec.js +++ b/platform/representation/test/MCTRepresentationSpec.js @@ -253,21 +253,6 @@ define( expect(mockScope.testCapability).toBeUndefined(); }); - it("registers a status change listener", function () { - mockScope.$watch.calls[2].args[1](mockDomainObject); - expect(mockStatusCapability.listen).toHaveBeenCalled(); - }); - - it("unlistens for status change on scope destruction", function () { - var mockUnlistener = jasmine.createSpy("unlisten"); - mockStatusCapability.listen.andReturn(mockUnlistener); - mockScope.$watch.calls[2].args[1](mockDomainObject); - expect(mockStatusCapability.listen).toHaveBeenCalled(); - - mockScope.$on.calls[1].args[1](); - expect(mockUnlistener).toHaveBeenCalled(); - }); - describe("when a domain object has been observed", function () { var mockContext, mockContext2, From 601bc03ba2064a992553151e3843c69c0d9d41c1 Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 20 May 2016 10:23:05 -0700 Subject: [PATCH 11/11] [New Edit Mode] #636 Modified EditAndCompose action to rely on a slightly refactored EditActionPolicy to remove folder specific logic --- .../edit/src/actions/EditAndComposeAction.js | 7 ++++--- .../edit/src/policies/EditActionPolicy.js | 19 ++++++++----------- .../test/actions/EditAndComposeActionSpec.js | 19 ++++++++++++++++--- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/platform/commonUI/edit/src/actions/EditAndComposeAction.js b/platform/commonUI/edit/src/actions/EditAndComposeAction.js index 974ab2f001..de43ca0fdc 100644 --- a/platform/commonUI/edit/src/actions/EditAndComposeAction.js +++ b/platform/commonUI/edit/src/actions/EditAndComposeAction.js @@ -37,7 +37,8 @@ define( } EditAndComposeAction.prototype.perform = function () { - var self = this; + var self = this, + editAction = this.domainObject.getCapability('action').getActions("edit")[0]; // Persist changes to the domain object function doPersist() { @@ -54,8 +55,8 @@ define( .then(doPersist); } - if (this.domainObject.getCapability('type').getKey() !== 'folder') { - this.domainObject.getCapability('action').perform('edit'); + if (editAction) { + editAction.perform(); } return this.selectedObject && doLink(); diff --git a/platform/commonUI/edit/src/policies/EditActionPolicy.js b/platform/commonUI/edit/src/policies/EditActionPolicy.js index f266d580eb..86e103b387 100644 --- a/platform/commonUI/edit/src/policies/EditActionPolicy.js +++ b/platform/commonUI/edit/src/policies/EditActionPolicy.js @@ -81,17 +81,14 @@ define( var key = action.getMetadata().key, category = (context || {}).category; - // Only worry about actions in the view-control category - if (category === 'view-control') { - // Restrict 'edit' to cases where there are editable - // views (similarly, restrict 'properties' to when - // the converse is true), and where the domain object is not - // already being edited. - if (key === 'edit') { - return this.countEditableViews(context) > 0 && !isEditing(context); - } else if (key === 'properties') { - return this.countEditableViews(context) < 1 && !isEditing(context); - } + // Restrict 'edit' to cases where there are editable + // views (similarly, restrict 'properties' to when + // the converse is true), and where the domain object is not + // already being edited. + if (key === 'edit') { + return this.countEditableViews(context) > 0 && !isEditing(context); + } else if (key === 'properties' && category === 'view-control') { + return this.countEditableViews(context) < 1 && !isEditing(context); } // Like all policies, allow by default. diff --git a/platform/commonUI/edit/test/actions/EditAndComposeActionSpec.js b/platform/commonUI/edit/test/actions/EditAndComposeActionSpec.js index a02c259fd1..2e83b2f9c7 100644 --- a/platform/commonUI/edit/test/actions/EditAndComposeActionSpec.js +++ b/platform/commonUI/edit/test/actions/EditAndComposeActionSpec.js @@ -32,6 +32,7 @@ define( mockComposition, mockPersistence, mockActionCapability, + mockEditAction, mockType, actionContext, model, @@ -69,7 +70,8 @@ define( mockComposition = jasmine.createSpyObj("composition", [ "invoke", "add" ]); mockPersistence = jasmine.createSpyObj("persistence", [ "persist" ]); mockType = jasmine.createSpyObj("type", [ "hasFeature", "getKey" ]); - mockActionCapability = jasmine.createSpyObj("actionCapability", [ "perform"]); + mockActionCapability = jasmine.createSpyObj("actionCapability", [ "getActions"]); + mockEditAction = jasmine.createSpyObj("editAction", ["perform"]); mockDomainObject.getId.andReturn("test"); mockDomainObject.getCapability.andReturn(mockContext); @@ -78,6 +80,7 @@ define( mockType.getKey.andReturn("layout"); mockComposition.invoke.andReturn(mockPromise(true)); mockComposition.add.andReturn(mockPromise(true)); + mockActionCapability.getActions.andReturn([]); capabilities = { composition: mockComposition, @@ -109,9 +112,19 @@ define( expect(mockPersistence.persist).toHaveBeenCalled(); }); - it("enables edit mode", function () { + it("enables edit mode for objects that have an edit action", function () { + mockActionCapability.getActions.andReturn([mockEditAction]); action.perform(); - expect(mockActionCapability.perform).toHaveBeenCalledWith("edit"); + expect(mockEditAction.perform).toHaveBeenCalled(); + }); + + it("Does not enable edit mode for objects that do not have an" + + " edit action", function () { + mockActionCapability.getActions.andReturn([]); + action.perform(); + expect(mockEditAction.perform).not.toHaveBeenCalled(); + expect(mockComposition.add) + .toHaveBeenCalledWith(mockDomainObject); }); });