From 5314afb51afac0ada946daf3e7ec264783d86fae Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 15 Nov 2013 10:38:36 +1100 Subject: [PATCH] Changed editorContext to use appState instead for content/media/member editors - the appState saved is the basic entity, this means that if property editors resolve this value they do not have access to actually change the real content model which we don't want to allow (or changing other property's values). Fixed up some inconsistencies between all of these editors and the content editor helper, fixed up tree syncing with the members editor. --- .../src/common/services/appstate.service.js | 3 +- .../services/contenteditinghelper.service.js | 25 +++++++------- .../common/services/editorContext.service.js | 2 -- .../views/content/content.edit.controller.js | 23 ++++++++----- .../datatype/datatype.edit.controller.js | 10 +++--- .../src/views/media/media.edit.controller.js | 18 +++++++--- .../views/member/member.edit.controller.js | 34 ++++++++++++++----- 7 files changed, 72 insertions(+), 43 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/common/services/editorContext.service.js 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 f0563d5900..81e3fff441 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,7 +16,8 @@ function appState($rootScope) { touchDevice: null, showTray: null, stickyNavigation: null, - navMode: null + navMode: null, + editingEntity: null }; var sectionState = { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 0a2a74d006..5ed9212d3c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -2,11 +2,13 @@ /** * @ngdoc service * @name umbraco.services.contentEditingHelper -* @description A helper service for content/media/member controllers when editing/creating/saving content. +* @description A helper service for most editors, some methods are specific to content/media/member model types but most are used by +* all editors to share logic and reduce the amount of replicated code among editors. **/ -function contentEditingHelper($location, $routeParams, notificationsService, serverValidationManager, dialogService, formHelper) { +function contentEditingHelper($location, $routeParams, notificationsService, serverValidationManager, dialogService, formHelper, appState) { return { + /** * @ngdoc method @@ -36,15 +38,15 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser * @function * * @description - * re-binds all changed property values to the origContent object from the newContent object and returns an array of changed properties. + * re-binds all changed property values to the origContent object from the savedContent object and returns an array of changed properties. */ - reBindChangedProperties: function (origContent, newContent) { + reBindChangedProperties: function (origContent, savedContent) { var changed = []; //get a list of properties since they are contained in tabs var allOrigProps = this.getAllProps(origContent); - var allNewProps = this.getAllProps(newContent); + var allNewProps = this.getAllProps(savedContent); function getNewProp(alias) { return _.find(allNewProps, function (item) { @@ -66,8 +68,8 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser continue; } - if (!_.isEqual(origContent[o], newContent[o])) { - origContent[o] = newContent[o]; + if (!_.isEqual(origContent[o], savedContent[o])) { + origContent[o] = savedContent[o]; } } @@ -109,9 +111,6 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser if (!args.err) { throw "args.err cannot be null"; } - if (!args.allNewProps && !angular.isArray(args.allNewProps)) { - throw "args.allNewProps must be a valid array"; - } if (args.redirectOnFailure === undefined || args.redirectOnFailure === null) { throw "args.redirectOnFailure must be set to true or false"; } @@ -168,11 +167,11 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser if (!args) { throw "args cannot be null"; } - if (!args.newContent) { - throw "args.newContent cannot be null"; + if (!args.savedContent) { + throw "args.savedContent cannot be null"; } - if (!this.redirectToCreatedContent(args.redirectId ? args.redirectId : args.newContent.id)) { + if (!this.redirectToCreatedContent(args.redirectId ? args.redirectId : args.savedContent.id)) { //we are not redirecting because this is not new content, it is existing content. In this case // we need to detect what properties have changed and re-bind them with the server data. diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editorContext.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editorContext.service.js deleted file mode 100644 index 4f69a3011a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/services/editorContext.service.js +++ /dev/null @@ -1,2 +0,0 @@ -angular.module("umbraco.services") - .value('editorContext', undefined); \ No newline at end of file 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 f47b98f5a5..487ba611db 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 @@ -6,7 +6,7 @@ * @description * The controller for the content editor */ -function ContentEditController($scope, $routeParams, $q, $timeout, $window, appState, contentResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, editorContext, treeService, fileManager, formHelper, umbRequestHelper, keyboardService) { +function ContentEditController($scope, $routeParams, $q, $timeout, $window, appState, contentResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, treeService, fileManager, formHelper, umbRequestHelper, keyboardService, umbModelMapper) { //setup scope vars $scope.defaultButton = null; @@ -15,9 +15,6 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS $scope.currentSection = appState.getSectionState("currentSection"); $scope.currentNode = null; //the editors affiliated node - //we need this to share our content object with property editors - editorContext = $scope.content; - //This sets up the action buttons based on what permissions the user has. //The allowedActions parameter contains a list of chars, each represents a button by permission so //here we'll build the buttons according to the chars of the user. @@ -123,11 +120,15 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS contentEditingHelper.handleSuccessfulSave({ scope: $scope, - newContent: data, + savedContent: data, rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); + //update appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + configureButtons(data); + navigationService.syncTree({ tree: "content", path: data.path.split(","), forceReload: true }).then(function (syncArgs) { $scope.currentNode = syncArgs.node; }); @@ -139,10 +140,12 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS contentEditingHelper.handleSaveError({ redirectOnFailure: true, err: err, - allNewProps: contentEditingHelper.getAllProps(err.data), - allOrigProps: contentEditingHelper.getAllProps($scope.content) + rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data) }); + //update appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + deferred.reject(err); }); } @@ -159,6 +162,8 @@ 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)); configureButtons($scope.content); }); } @@ -168,6 +173,8 @@ 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)); configureButtons($scope.content); //in one particular special case, after we've created a new item we redirect back to the edit @@ -194,7 +201,7 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS contentEditingHelper.handleSuccessfulSave({ scope: $scope, - newContent: data, + savedContent: data, rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); 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 5a83003c46..7f82dd8fec 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 @@ -45,8 +45,8 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig $scope.preValues = []; if ($routeParams.create) { - //we are creating so get an empty content item - dataTypeResource.getScaffold($routeParams.id, $routeParams.doctype) + //we are creating so get an empty data type item + dataTypeResource.getScaffold($routeParams.id) .then(function(data) { $scope.loaded = true; $scope.preValuesLoaded = true; @@ -101,7 +101,7 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig contentEditingHelper.handleSuccessfulSave({ scope: $scope, - newContent: data, + savedContent: data, rebindCallback: function() { createPreValueProps(data.preValues); } @@ -117,9 +117,7 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig // to be the same thing since that only really matters for content/media. contentEditingHelper.handleSaveError({ redirectOnFailure: false, - err: err, - allNewProps: $scope.preValues, - allOrigProps: $scope.preValues + err: err }); }); } 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 99f21c3fb9..1d3e226fd8 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 @@ -6,7 +6,7 @@ * @description * The controller for the media editor */ -function mediaEditController($scope, $routeParams, appState, mediaResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, treeService, formHelper) { +function mediaEditController($scope, $routeParams, appState, mediaResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, treeService, formHelper, umbModelMapper) { //setup scope vars $scope.nav = navigationService; @@ -19,7 +19,8 @@ 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)); }); } else { @@ -27,7 +28,9 @@ 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)); + //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 @@ -52,10 +55,13 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, navi contentEditingHelper.handleSuccessfulSave({ scope: $scope, - newContent: data, + savedContent: data, rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); + //update appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + navigationService.syncTree({ tree: "media", path: data.path, forceReload: true }).then(function (syncArgs) { $scope.currentNode = syncArgs.node; }); @@ -65,9 +71,11 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, navi contentEditingHelper.handleSaveError({ err: err, redirectOnFailure: true, - allNewProps: contentEditingHelper.getAllProps(err.data), rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data) }); + + //update appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($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 f1ade8b374..4a20db9c43 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 @@ -6,19 +6,29 @@ * @description * The controller for the member editor */ -function MemberEditController($scope, $routeParams, $location, $q, $window, appState, memberResource, entityResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, formHelper, treeService) { +function MemberEditController($scope, $routeParams, $location, $q, $window, appState, memberResource, entityResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, formHelper, umbModelMapper) { //setup scope vars $scope.nav = navigationService; $scope.currentSection = appState.getSectionState("currentSection"); $scope.currentNode = null; //the editors affiliated node + //build a path to sync the tree with + function buildTreePath(data) { + //TODO: Will this work for the 'other' list ? + var path = data.name[0] + "," + data.key; + path = path.replace(/-/g, ''); + return path; + } + if ($routeParams.create) { //we are creating so get an empty member item memberResource.getScaffold($routeParams.doctype) .then(function(data) { $scope.loaded = true; $scope.content = data; + //put this into appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); }); } else { @@ -40,9 +50,10 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS $scope.loaded = true; $scope.content = data; - //build a path to sync the tree with - var path = data.name[0]+"," + data.key; - path = path.replace(/-/g,''); + //put this into appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + + var path = buildTreePath(data); navigationService.syncTree({ tree: "member", path: path.split(",") }).then(function (syncArgs) { $scope.currentNode = syncArgs.node; @@ -69,13 +80,18 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS contentEditingHelper.handleSuccessfulSave({ scope: $scope, - newContent: data, + savedContent: data, //specify a custom id to redirect to since we want to use the GUID redirectId: data.key, rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) }); - navigationService.syncTree({ tree: "member", path: path.split(",") }).then(function (syncArgs) { + //update appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + + var path = buildTreePath(data); + + navigationService.syncTree({ tree: "member", path: path.split(","), forceReload: true }).then(function (syncArgs) { $scope.currentNode = syncArgs.node; }); @@ -84,9 +100,11 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS contentEditingHelper.handleSaveError({ redirectOnFailure: false, err: err, - allNewProps: contentEditingHelper.getAllProps(err.data), - allOrigProps: contentEditingHelper.getAllProps($scope.content) + rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data) }); + + //update appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); }); }