From 5bb68f32bf461679a9e07765c98aaa1b951b4aaf Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 19 Nov 2013 10:39:18 +1100 Subject: [PATCH] Fixes up editorState - ensures that it is set in all of the correct places (removes appState editingEntity and references), ensures that setting 'current' is not possible, ensures that editorState is reset on all route changes, adds unit tests for getting/setting editorState. --- .../src/common/services/appstate.service.js | 31 +++++++++++++------ src/Umbraco.Web.UI.Client/src/init.js | 10 ++++-- .../views/content/content.edit.controller.js | 15 ++++----- .../datatype/datatype.edit.controller.js | 15 +++++++-- .../src/views/media/media.edit.controller.js | 11 ++----- .../views/member/member.edit.controller.js | 14 +++------ .../unit/common/services/app-state.spec.js | 21 ++++++++++++- src/Umbraco.Web.UI/umbraco/js/init.js | 10 ++++-- 8 files changed, 81 insertions(+), 46 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js b/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js index 938edb5419..8160dfccea 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js @@ -16,8 +16,7 @@ function appState($rootScope) { touchDevice: null, showTray: null, stickyNavigation: null, - navMode: null, - editingEntity: null + navMode: null }; var sectionState = { @@ -200,14 +199,28 @@ angular.module('umbraco.services').factory('appState', appState); * * it is possible to modify this object, so should be used with care */ -angular.module('umbraco.services').factory("editorState", function(){ - return { - //we need this structure to return as an object reference - current: {entity: null}, +angular.module('umbraco.services').factory("editorState", function() { - //shortcut to current.entity = whatever; - set: function(entity){ - this.current.entity = entity; + var current = null; + var state = { + set: function (entity) { + current = entity; + }, + reset: function() { + current = null; } + }; + + //create a get/set property but don't allow setting + Object.defineProperty(state, "current", { + get: function () { + return current; + }, + set: function (value) { + throw "Use editorState.set to set the value of the current entity"; + }, + }); + + return state; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/init.js b/src/Umbraco.Web.UI.Client/src/init.js index 0811d5b650..34fc1b5888 100644 --- a/src/Umbraco.Web.UI.Client/src/init.js +++ b/src/Umbraco.Web.UI.Client/src/init.js @@ -1,6 +1,6 @@ /** Executed when the application starts */ -app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', - function(userService, $log, $rootScope, $location, navigationService, appState) { +app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', + function(userService, $log, $rootScope, $location, navigationService, appState, editorState) { var firstRun = true; @@ -18,10 +18,14 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', if(current.params.section){ $rootScope.locationTitle = current.params.section + " - " + $location.$$host; - }else{ + } + else { $rootScope.locationTitle = "Umbraco - " + $location.$$host; } + //reset the editorState on each successful route chage + editorState.reset(); + }); /** When the route change is rejected - based on checkAuth - we'll prevent the rejected route from executing including diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js index 6789ab3879..5d1bba3017 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js @@ -124,8 +124,7 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); - //update appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); configureButtons(data); @@ -143,8 +142,7 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data) }); - //update appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); deferred.reject(err); }); @@ -162,8 +160,7 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS .then(function(data) { $scope.loaded = true; $scope.content = data; - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); configureButtons($scope.content); @@ -175,9 +172,7 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS .then(function(data) { $scope.loaded = true; $scope.content = data; - - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); configureButtons($scope.content); @@ -210,6 +205,8 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); + editorState.set($scope.content); + configureButtons(data); navigationService.syncTree({ tree: "content", path: data.path.split(","), forceReload: true }).then(function (syncArgs) { diff --git a/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js index e34d9554ae..a2a96e9e9f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/datatype/datatype.edit.controller.js @@ -64,11 +64,11 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig $scope.preValuesLoaded = true; $scope.content = data; - //share state - editorState.set($scope.content); - createPreValueProps($scope.content.preValues); + //share state + editorState.set($scope.content); + //in one particular special case, after we've created a new item we redirect back to the edit // route but there might be server validation errors in the collection which we need to display // after the redirect, so we will bind all subscriptions which will show the server validation errors @@ -92,6 +92,9 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig $scope.preValuesLoaded = true; $scope.content.preValues = data; createPreValueProps($scope.content.preValues); + + //share state + editorState.set($scope.content); }); } }); @@ -113,6 +116,9 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig } }); + //share state + editorState.set($scope.content); + navigationService.syncTree({ tree: "datatype", path: [String(data.id)], forceReload: true }).then(function (syncArgs) { $scope.currentNode = syncArgs.node; }); @@ -125,6 +131,9 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig redirectOnFailure: false, err: err }); + + //share state + editorState.set($scope.content); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js index 896edb13b7..ab9da21733 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js @@ -20,8 +20,6 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, navi $scope.loaded = true; $scope.content = data; - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); editorState.set($scope.content); }); } @@ -30,8 +28,7 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, navi .then(function (data) { $scope.loaded = true; $scope.content = data; - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); //in one particular special case, after we've created a new item we redirect back to the edit @@ -62,8 +59,7 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, navi rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); - //update appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); navigationService.syncTree({ tree: "media", path: data.path, forceReload: true }).then(function (syncArgs) { $scope.currentNode = syncArgs.node; @@ -77,8 +73,7 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, navi rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data) }); - //update appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js index 9715877d56..7fc78b67b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js @@ -31,8 +31,6 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS $scope.loaded = true; $scope.content = data; - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); editorState.set($scope.content); }); } @@ -41,8 +39,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS .then(function (data) { $scope.loaded = true; $scope.content = data; - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); }); } @@ -67,8 +64,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS $scope.loaded = true; $scope.content = data; - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); var path = buildTreePath(data); @@ -103,8 +99,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); - //update appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); var path = buildTreePath(data); @@ -120,8 +115,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data) }); - //update appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + editorState.set($scope.content); }); } diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/app-state.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/app-state.spec.js index 69a0e08b88..749bbca3de 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/common/services/app-state.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/app-state.spec.js @@ -1,13 +1,32 @@ describe('appState tests', function () { - var appState, $rootScope; + var appState, $rootScope, editorState; beforeEach(module('umbraco.services')); beforeEach(inject(function ($injector) { appState = $injector.get('appState'); $rootScope = $injector.get('$rootScope'); + editorState = $injector.get('editorState'); })); + describe('Editor state', function () { + it('Can set', function () { + editorState.set({ some: "object" }); + expect(editorState.current).not.toBeNull(); + expect(editorState.current.some).toBe("object"); + }); + it('Can reset', function () { + editorState.reset(); + expect(editorState.current).toBeNull(); + }); + it('Throws when setting current', function () { + function setCurrent() { + editorState.current = { some: "object" }; + } + expect(setCurrent).toThrow(); + }); + }); + describe('Global state', function () { it('Can get/set state', function () { appState.setGlobalState("showNavigation", true); diff --git a/src/Umbraco.Web.UI/umbraco/js/init.js b/src/Umbraco.Web.UI/umbraco/js/init.js index 0811d5b650..34fc1b5888 100644 --- a/src/Umbraco.Web.UI/umbraco/js/init.js +++ b/src/Umbraco.Web.UI/umbraco/js/init.js @@ -1,6 +1,6 @@ /** Executed when the application starts */ -app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', - function(userService, $log, $rootScope, $location, navigationService, appState) { +app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', + function(userService, $log, $rootScope, $location, navigationService, appState, editorState) { var firstRun = true; @@ -18,10 +18,14 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', if(current.params.section){ $rootScope.locationTitle = current.params.section + " - " + $location.$$host; - }else{ + } + else { $rootScope.locationTitle = "Umbraco - " + $location.$$host; } + //reset the editorState on each successful route chage + editorState.reset(); + }); /** When the route change is rejected - based on checkAuth - we'll prevent the rejected route from executing including