From 5ffca11c5b42e19830718beb6af07c6f933ba27e Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Sep 2013 18:58:24 +1000 Subject: [PATCH 1/5] Fixing: U4-2678 Fix logging out and then logging in as another user, the sections, etc... do not get updated. --- .../src/common/security/interceptor.js | 9 +- .../src/common/services/user.service.js | 20 +++- src/Umbraco.Web.UI.Client/src/routes.js | 12 ++- .../views/common/dialogs/login.controller.js | 28 ++--- .../views/common/dialogs/user.controller.js | 2 +- .../src/views/common/main.controller.js | 101 +++++++++++------- .../src/views/common/navigation.controller.js | 16 ++- 7 files changed, 126 insertions(+), 62 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js index fe77a4b26f..320296b5b3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js @@ -1,12 +1,19 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) // This http interceptor listens for authentication failures -.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', function ($injector, queue, notifications) { +.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', '$rootScope', '$log', function ($injector, queue, notifications, $rootScope, $log) { return function (promise) { // Intercept failed requests return promise.then(null, function (originalResponse) { + //A 401 means that the user is not logged in if (originalResponse.status === 401) { + + $log.log("Broadcasting notAuthenticated event"); + + //emit a global event that the user is no longer logged in + $rootScope.$broadcast("notAuthenticated"); + // The request bounced because it was not authorized - add a new request to the retry queue promise = queue.pushRetryFn('unauthorized-server', function retryRequest() { // We must use $injector to get the $http service to prevent circular dependency diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js index 54a5ae1999..9ea869a913 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js @@ -36,6 +36,10 @@ angular.module('umbraco.services') // Register a handler for when an item is added to the retry queue securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) { if (securityRetryQueue.hasMore()) { + + //clear the user + currentUser = null; + openLoginDialog(); } }); @@ -49,7 +53,7 @@ angular.module('umbraco.services') .then(function(data) { //note, this can return null if they are not authenticated - if (!data) { + if (!data) { throw "Not authenticated"; } else { @@ -65,16 +69,28 @@ angular.module('umbraco.services') return authResource.performLogin(login, password) .then(function (data) { + //when it's successful, return the user data currentUser = data; - return { user: data, authenticated: true }; + + var result = { user: data, authenticated: true }; + + //broadcast a global event + $rootScope.$broadcast("authenticated", result); + + return result; }); }, logout: function () { return authResource.performLogout() .then(function (data) { + currentUser = null; + + //broadcast a global event + $rootScope.$broadcast("notAuthenticated"); + openLoginDialog(); return null; }); diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 603948984b..6b482eba9b 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -53,8 +53,16 @@ app.config(function ($routeProvider) { }); -app.run(['userService', function (userService) { +app.run(['userService', '$log', '$rootScope', function (userService, $log, $rootScope) { + // Get the current user when the application starts // (in case they are still logged in from a previous session) - userService.isAuthenticated(); + + userService.isAuthenticated() + .then(function (data) { + + //broadcast a global event, will inform listening controllers to load in the user specific data + $rootScope.$broadcast("authenticated", data); + + }); }]); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js index e42a2aa479..a4dd1f7507 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js @@ -15,7 +15,8 @@ $scope.today = weekday[d.getDay()]; $scope.errorMsg = ""; - $scope.loginSubmit = function (login, password) { + $scope.loginSubmit = function (login, password) { + //if the login and password are not empty we need to automatically // validate them - this is because if there are validation errors on the server // then the user has to change both username & password to resubmit which isn't ideal, @@ -32,20 +33,19 @@ userService.authenticate(login, password) .then(function (data) { - //We need to load in the legacy tree js. - legacyJsLoader.loadLegacyTreeJs($scope).then( - function(result) { - var iframe = $("#right"); - if(iframe){ - var url = decodeURIComponent($routeParams.url); - if(!url){ - url ="dashboard.aspx"; - } - iframe.attr("src", url); - } + + var iframe = $("#right"); + if (iframe) { + var url = decodeURIComponent($routeParams.url); + if (!url) { + url = "dashboard.aspx"; + } + iframe.attr("src", url); + } - $scope.submit(true); - }); + $scope.submit(true); + + }, function (reason) { $scope.errorMsg = reason.errorMsg; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js index a0b244c8f2..e683c831d1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js @@ -12,7 +12,7 @@ angular.module("umbraco") $scope.gotoHistory = function (link) { $location.path(link); - $scope.$apply() + $scope.$apply(); $scope.hide(); }; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js index 476c9663c0..f1fa3e0549 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js @@ -10,6 +10,7 @@ */ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, notificationsService, userService, navigationService, legacyJsLoader) { + var legacyTreeJsLoaded = false; //detect if the current device is touch-enabled $scope.touchDevice = ("ontouchstart" in window || window.touch || window.navigator.msMaxTouchPoints===5 || window.DocumentTouch && document instanceof DocumentTouch); @@ -53,53 +54,77 @@ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, $rootScope.$emit("closeDialogs", event); }; - //fetch the authorized status - userService.isAuthenticated() - .then(function (data) { - - //We need to load in the legacy tree js. + //when a user logs out or timesout + $scope.$on("notAuthenticated", function() { + + //this means that the user has logged out + $log.log("MainController handling notAuthenticated"); + + $scope.authenticated = null; + $scope.user = null; + + }); + + //when a user is authorized setup the data + $scope.$on("authenticated", function (evt, data) { + + //this means that the user has logged in + $log.log("MainController handling authenticated"); + + //We need to load in the legacy tree js but only once no matter what user has logged in + if (!legacyTreeJsLoaded) { legacyJsLoader.loadLegacyTreeJs($scope).then( function (result) { + legacyTreeJsLoaded = true; + //TODO: We could wait for this to load before running the UI ? }); + } + + $scope.authenticated = data.authenticated; + $scope.user = data.user; + + }); + + ////fetch the authorized status + //userService.isAuthenticated() + // .then(function (data) { - $scope.authenticated = data.authenticated; - $scope.user = data.user; + // ////We need to load in the legacy tree js but only once no matter what user has logged in + // //if (!legacyTreeJsLoaded) { + // // legacyJsLoader.loadLegacyTreeJs($scope).then( + // // function (result) { + // // legacyTreeJsLoaded = true; + + // // //TODO: We could wait for this to load before running the UI ? + // // }); + // //} + + // //$scope.authenticated = data.authenticated; + // //$scope.user = data.user; + + // //var url = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".json?404=404"; + // //$http.jsonp(url).then(function(response){ + // // $log.log("found: " + response); + // //}, function(data){ + // // $log.log(data); + // //}); - -/* - var url = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".json?404=404"; - $http.jsonp(url).then(function(response){ - $log.log("found: " + response); - }, function(data){ - $log.log(data); - }); -*/ - - /* - if($scope.user.avatar){ - $http.get($scope.user.avatar).then(function(){ - //alert($scope.user.avatar); - $scope.avatar = $scope.user.avatar; - }); - }*/ + // //if($scope.user.avatar){ + // // $http.get($scope.user.avatar).then(function(){ + // // //alert($scope.user.avatar); + // // $scope.avatar = $scope.user.avatar; + // // }); + // //} - }, function (reason) { - notificationsService.error("An error occurred checking authentication."); - $scope.authenticated = false; - $scope.user = null; - }); + // }, function (reason) { + // notificationsService.error("An error occurred checking authentication."); + // $scope.authenticated = false; + // $scope.user = null; + // }); } //register it -angular.module('umbraco').controller("Umbraco.MainController", MainController); - -/* -angular.module("umbraco").run(function(eventsService){ - eventsService.subscribe("Umbraco.Dialogs.ContentPickerController.Select", function(a, b){ - a.node.name = "wat"; - }); -}); -*/ \ No newline at end of file +angular.module('umbraco').controller("Umbraco.MainController", MainController); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js index bc88a561bb..dbe7cea8e9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js @@ -30,11 +30,19 @@ function NavigationController($scope,$rootScope, $location, $log, $routeParams, $scope.selectedId = navigationService.currentId; $scope.sections = navigationService.sections; + + $scope.$on("notAuthenticated", function() { + $log.log("NavigationController handling notAuthenticated"); + }); - sectionResource.getSections() - .then(function(result) { - $scope.sections = result; - }); + $scope.$on("authenticated", function (evt, data) { + $log.log("NavigationController handling authenticated"); + + sectionResource.getSections() + .then(function(result) { + $scope.sections = result; + }); + }); //This reacts to clicks passed to the body element which emits a global call to close all dialogs $rootScope.$on("closeDialogs", function (event) { From ac2a4a1e0a50804404de3ef386d052f9107062aa Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Sep 2013 19:14:30 +1000 Subject: [PATCH 2/5] Fixing: U4-2678 Fix logging out and then logging in as another user, the sections, etc... do not get updated. - all event broadcasting is now centralized. --- .../src/common/security/interceptor.js | 7 +-- .../src/common/services/user.service.js | 20 ++++++- src/Umbraco.Web.UI.Client/src/routes.js | 10 +--- .../src/views/common/main.controller.js | 57 +++++-------------- .../src/views/common/navigation.controller.js | 18 +++--- 5 files changed, 45 insertions(+), 67 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js index 320296b5b3..e995765d29 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js @@ -1,7 +1,7 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) // This http interceptor listens for authentication failures -.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', '$rootScope', '$log', function ($injector, queue, notifications, $rootScope, $log) { +.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', function ($injector, queue, notifications) { return function (promise) { // Intercept failed requests return promise.then(null, function (originalResponse) { @@ -9,11 +9,6 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) //A 401 means that the user is not logged in if (originalResponse.status === 401) { - $log.log("Broadcasting notAuthenticated event"); - - //emit a global event that the user is no longer logged in - $rootScope.$broadcast("notAuthenticated"); - // The request bounced because it was not authorized - add a new request to the retry queue promise = queue.pushRetryFn('unauthorized-server', function retryRequest() { // We must use $injector to get the $http service to prevent circular dependency diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js index 9ea869a913..5bf23e97c3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js @@ -2,6 +2,7 @@ angular.module('umbraco.services') .factory('userService', function ($rootScope, $q, $location, $log, securityRetryQueue, authResource, dialogService) { var currentUser = null; + var lastUserId = null; var loginDialog = null; // Redirect to the given url (defaults to '/') @@ -38,8 +39,12 @@ angular.module('umbraco.services') if (securityRetryQueue.hasMore()) { //clear the user + lastUserId = currentUser.id; currentUser = null; + //broadcast a global event that the user is no longer logged in + $rootScope.$broadcast("notAuthenticated"); + openLoginDialog(); } }); @@ -47,7 +52,7 @@ angular.module('umbraco.services') return { /** Returns a promise, sends a request to the server to check if the current cookie is authorized */ - isAuthenticated: function () { + isAuthenticated: function (args) { return authResource.isAuthenticated() .then(function(data) { @@ -57,9 +62,17 @@ angular.module('umbraco.services') throw "Not authenticated"; } else { + + var result = { user: data, authenticated: true }; + + if (args.broadcastEvent) { + //broadcast a global event, will inform listening controllers to load in the user specific data + $rootScope.$broadcast("authenticated", result); + } + currentUser = data; currentUser.avatar = 'http://www.gravatar.com/avatar/' + data.emailHash + '?s=40&d=404'; - return { user: data, authenticated: true }; + return result; } }); }, @@ -73,7 +86,7 @@ angular.module('umbraco.services') //when it's successful, return the user data currentUser = data; - var result = { user: data, authenticated: true }; + var result = { user: data, authenticated: true, previousUserId: lastUserId }; //broadcast a global event $rootScope.$broadcast("authenticated", result); @@ -86,6 +99,7 @@ angular.module('umbraco.services') return authResource.performLogout() .then(function (data) { + lastUserId = currentUser.id; currentUser = null; //broadcast a global event diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 6b482eba9b..b3bd6791cd 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -57,12 +57,6 @@ app.run(['userService', '$log', '$rootScope', function (userService, $log, $root // Get the current user when the application starts // (in case they are still logged in from a previous session) - - userService.isAuthenticated() - .then(function (data) { - - //broadcast a global event, will inform listening controllers to load in the user specific data - $rootScope.$broadcast("authenticated", data); - - }); + + userService.isAuthenticated({broadcastEvent: true}); }]); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js index f1fa3e0549..502a379aa9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js @@ -57,9 +57,6 @@ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, //when a user logs out or timesout $scope.$on("notAuthenticated", function() { - //this means that the user has logged out - $log.log("MainController handling notAuthenticated"); - $scope.authenticated = null; $scope.user = null; @@ -68,9 +65,6 @@ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, //when a user is authorized setup the data $scope.$on("authenticated", function (evt, data) { - //this means that the user has logged in - $log.log("MainController handling authenticated"); - //We need to load in the legacy tree js but only once no matter what user has logged in if (!legacyTreeJsLoaded) { legacyJsLoader.loadLegacyTreeJs($scope).then( @@ -84,45 +78,22 @@ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, $scope.authenticated = data.authenticated; $scope.user = data.user; + //var url = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".json?404=404"; + //$http.jsonp(url).then(function(response){ + // $log.log("found: " + response); + //}, function(data){ + // $log.log(data); + //}); + + //if($scope.user.avatar){ + // $http.get($scope.user.avatar).then(function(){ + // //alert($scope.user.avatar); + // $scope.avatar = $scope.user.avatar; + // }); + //} + }); - ////fetch the authorized status - //userService.isAuthenticated() - // .then(function (data) { - - // ////We need to load in the legacy tree js but only once no matter what user has logged in - // //if (!legacyTreeJsLoaded) { - // // legacyJsLoader.loadLegacyTreeJs($scope).then( - // // function (result) { - // // legacyTreeJsLoaded = true; - - // // //TODO: We could wait for this to load before running the UI ? - // // }); - // //} - - // //$scope.authenticated = data.authenticated; - // //$scope.user = data.user; - - // //var url = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".json?404=404"; - // //$http.jsonp(url).then(function(response){ - // // $log.log("found: " + response); - // //}, function(data){ - // // $log.log(data); - // //}); - - // //if($scope.user.avatar){ - // // $http.get($scope.user.avatar).then(function(){ - // // //alert($scope.user.avatar); - // // $scope.avatar = $scope.user.avatar; - // // }); - // //} - - - // }, function (reason) { - // notificationsService.error("An error occurred checking authentication."); - // $scope.authenticated = false; - // $scope.user = null; - // }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js index dbe7cea8e9..35f6b82b73 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js @@ -15,9 +15,12 @@ function NavigationController($scope,$rootScope, $location, $log, $routeParams, // IMPORTANT: all properties assigned to this scope are generally available on the scope object on dialogs since // when we create a dialog we pass in this scope to be used for the dialog's scope instead of creating a new one. $scope.nav = navigationService; - $scope.routeParams = $routeParams; - $scope.$watch("routeParams.section", function (newVal, oldVal) { - $scope.currentSection = newVal; + + $scope.$watch(function () { + //watch the route parameters section + return $routeParams.section; + }, function(newVal, oldVal) { + $scope.currentSection = newVal; }); //trigger search with a hotkey: @@ -31,13 +34,14 @@ function NavigationController($scope,$rootScope, $location, $log, $routeParams, $scope.selectedId = navigationService.currentId; $scope.sections = navigationService.sections; - $scope.$on("notAuthenticated", function() { - $log.log("NavigationController handling notAuthenticated"); + //When the user logs out or times out + $scope.$on("notAuthenticated", function () { + }); + //When the user logs in $scope.$on("authenticated", function (evt, data) { - $log.log("NavigationController handling authenticated"); - + //populate their sections if the user hasn't changed sectionResource.getSections() .then(function(result) { $scope.sections = result; From 3e9afcfc41a38717a59faeb1789fc00519e66799 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Sep 2013 20:08:15 +1000 Subject: [PATCH 3/5] Finishes: U4-2678 Fix logging out and then logging in as another user, the sections, etc... do not get updated. --- .../src/common/directives/umbtree.directive.js | 16 ++++++++++++---- .../src/common/services/tree.service.js | 10 +++++++++- .../src/common/services/user.service.js | 10 ++++++---- .../src/views/common/navigation.controller.js | 17 +++++++---------- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js index a69f13677a..c044a1edd2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js @@ -60,7 +60,6 @@ angular.module("umbraco.directives") if (scope.eventhandler) { $(scope.eventhandler).trigger(eventName, args); } - // $rootScope.$broadcast(eventName, args); } /** Method to load in the tree data */ @@ -93,7 +92,7 @@ angular.module("umbraco.directives") * When changing sections we don't want all of the tree-ndoes to do their 'leave' animations. */ scope.animation = function () { - if (enableDeleteAnimations && scope.tree.root.expanded) { + if (enableDeleteAnimations && scope.tree && scope.tree.root && scope.tree.root.expanded) { return { leave: 'tree-node-delete-leave' }; } else { @@ -126,8 +125,17 @@ angular.module("umbraco.directives") } }); - //initial change - loadTree(); + //When the user logs in + scope.$on("authenticated", function (evt, data) { + //populate the tree if the user has changed + if (data.lastUserId !== data.user.id) { + treeService.clearCache(); + scope.tree = null; + loadTree(); + } + }); + + }; } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js index db8a892618..a2b8961879 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js @@ -8,8 +8,10 @@ * The tree service factory, used internally by the umbTree and umbTreeItem directives */ function treeService($q, treeResource, iconHelper, notificationsService, $rootScope) { - //implement this in local storage + + //TODO: implement this in local storage var treeArray = []; + var standardCssClass = 'icon umb-tree-icon sprTree'; return { @@ -58,6 +60,11 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc } }, + /** clears the tree cache */ + clearCache: function() { + treeArray = []; + }, + /** * @ngdoc method * @name umbraco.services.treeService#loadNodeChildren @@ -259,6 +266,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc return data; }); } + }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js index 5bf23e97c3..626b11b98f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js @@ -38,8 +38,10 @@ angular.module('umbraco.services') securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) { if (securityRetryQueue.hasMore()) { - //clear the user - lastUserId = currentUser.id; + //store the last user id and clear the user + if (currentUser && currentUser.id !== undefined) { + lastUserId = currentUser.id; + } currentUser = null; //broadcast a global event that the user is no longer logged in @@ -63,7 +65,7 @@ angular.module('umbraco.services') } else { - var result = { user: data, authenticated: true }; + var result = { user: data, authenticated: true, lastUserId: lastUserId }; if (args.broadcastEvent) { //broadcast a global event, will inform listening controllers to load in the user specific data @@ -86,7 +88,7 @@ angular.module('umbraco.services') //when it's successful, return the user data currentUser = data; - var result = { user: data, authenticated: true, previousUserId: lastUserId }; + var result = { user: data, authenticated: true, lastUserId: lastUserId }; //broadcast a global event $rootScope.$broadcast("authenticated", result); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js index 35f6b82b73..2f12a2a40d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js @@ -33,19 +33,16 @@ function NavigationController($scope,$rootScope, $location, $log, $routeParams, $scope.selectedId = navigationService.currentId; $scope.sections = navigationService.sections; - - //When the user logs out or times out - $scope.$on("notAuthenticated", function () { - - }); //When the user logs in $scope.$on("authenticated", function (evt, data) { - //populate their sections if the user hasn't changed - sectionResource.getSections() - .then(function(result) { - $scope.sections = result; - }); + //populate their sections if the user has changed + if (data.lastUserId !== data.user.id) { + sectionResource.getSections() + .then(function (result) { + $scope.sections = result; + }); + } }); //This reacts to clicks passed to the body element which emits a global call to close all dialogs From 9ff74b39f8cec31d599c5adc96a6ec237d32334b Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Sep 2013 20:24:11 +1000 Subject: [PATCH 4/5] fixed web.config xform for debugging --- src/Umbraco.Web.UI/web.Template.Debug.config | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI/web.Template.Debug.config b/src/Umbraco.Web.UI/web.Template.Debug.config index a43ba6a739..1cc428f95a 100644 --- a/src/Umbraco.Web.UI/web.Template.Debug.config +++ b/src/Umbraco.Web.UI/web.Template.Debug.config @@ -46,6 +46,7 @@ + From 472ef6e48cb52400cf17cb59c2d8cc04b0ca4948 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Sep 2013 20:33:19 +1000 Subject: [PATCH 5/5] Starts fixing: U4-2947 Fix complex property editors with $watch expressions --- .../common/services/contenteditinghelper.service.js | 11 +++++++++++ .../propertyeditors/urllist/urllist.controller.js | 13 ++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) 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 a85cc8024c..03fd6b2946 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 @@ -55,8 +55,19 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser for (var p in allOrigProps) { var newProp = getNewProp(allOrigProps[p].alias); if (newProp && !_.isEqual(allOrigProps[p].value, newProp.value)) { + //they have changed so set the origContent prop to the new one + var origVal = allOrigProps[p].value; allOrigProps[p].value = newProp.value; + + //instead of having a property editor $watch their expression to check if it has + // been updated, instead we'll check for the existence of a special method on their model + // and just call it. + if (angular.isFunction(allOrigProps[p].onValueChanged)) { + //send the newVal + oldVal + allOrigProps[p].onValueChanged(allOrigProps[p].value, origVal); + } + changed.push(allOrigProps[p]); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/urllist/urllist.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/urllist/urllist.controller.js index 6dcd33847a..24a754b4f5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/urllist/urllist.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/urllist/urllist.controller.js @@ -12,12 +12,11 @@ angular.module('umbraco').controller("Umbraco.Editors.UrlListController", formatDisplayValue(); - //we need to put a watch on the real model because when it changes we have to update our renderModel - $scope.$watch("model.value", function (newVal, oldVal) { - if (newVal !== null && newVal !== undefined && newVal !== oldVal) { - //update the display val again - formatDisplayValue(); - } - }); + //here we declare a special method which will be called whenever the value has changed from the server + //this is instead of doing a watch on the model.value = faster + $scope.model.onValueChanged = function(newVal, oldVal) { + //update the display val again + formatDisplayValue(); + }; }); \ No newline at end of file