From 491f8b4f2a7204f1d74eb1a0db4acd98f15006d6 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Thu, 14 Jan 2016 14:45:50 -0500 Subject: [PATCH] (js) Fix sg-avatar-image with md-virtual-repeat --- .../ContactsUI/UIxContactFoldersView.wox | 1 + .../MailerUI/UIxMailFolderTemplate.wox | 2 +- UI/WebServerResources/js/Common/Common.app.js | 8 +- .../js/Common/navController.js | 31 +++--- .../js/Common/sgAvatarImage.directive.js | 95 +++++++++++-------- .../virtualRepeat/virtual-repeat.scss | 1 + 6 files changed, 81 insertions(+), 57 deletions(-) diff --git a/UI/Templates/ContactsUI/UIxContactFoldersView.wox b/UI/Templates/ContactsUI/UIxContactFoldersView.wox index 52ea63e17..c87523a3e 100644 --- a/UI/Templates/ContactsUI/UIxContactFoldersView.wox +++ b/UI/Templates/ContactsUI/UIxContactFoldersView.wox @@ -390,6 +390,7 @@ diff --git a/UI/Templates/MailerUI/UIxMailFolderTemplate.wox b/UI/Templates/MailerUI/UIxMailFolderTemplate.wox index be57d012b..3e58bcb2d 100644 --- a/UI/Templates/MailerUI/UIxMailFolderTemplate.wox +++ b/UI/Templates/MailerUI/UIxMailFolderTemplate.wox @@ -226,7 +226,7 @@ ng-switch="currentMessage.selected">
diff --git a/UI/WebServerResources/js/Common/Common.app.js b/UI/WebServerResources/js/Common/Common.app.js index 9ce0d1bd0..26dccc6cc 100644 --- a/UI/WebServerResources/js/Common/Common.app.js +++ b/UI/WebServerResources/js/Common/Common.app.js @@ -230,7 +230,7 @@ return { response: function(response) { // When expecting JSON but receiving HTML, assume session has expired and reload page - if (/^application\/json/.test(response.config.headers.Accept) && + if (response && /^application\/json/.test(response.config.headers.Accept) && /^/.test(response.data)) { $window.location.reload(true); return $q.reject(); @@ -247,8 +247,10 @@ function ErrorInterceptor($rootScope, $q) { return { responseError: function(rejection) { - // Broadcast the response error - $rootScope.$broadcast('http:Error', rejection); + if (/^application\/json/.test(rejection.config.headers.Accept)) { + // Broadcast the response error + $rootScope.$broadcast('http:Error', rejection); + } return $q.reject(rejection); } }; diff --git a/UI/WebServerResources/js/Common/navController.js b/UI/WebServerResources/js/Common/navController.js index a0d2cc098..a6f78b5d8 100644 --- a/UI/WebServerResources/js/Common/navController.js +++ b/UI/WebServerResources/js/Common/navController.js @@ -66,23 +66,26 @@ function onHttpError(event, response) { var message; - if (response.data.message) + if (response.data && response.data.message) message = response.data.message; - else + else if (response.status) message = response.statusText; - $mdToast.show({ - template: [ - '', - '
', - ' error_outline', - ' ' + l(message) + '', - '
', - '
' - ].join(''), - hideDelay: 5000, - position: 'top right' - }); + if (message) + $mdToast.show({ + template: [ + '', + '
', + ' error_outline', + ' ' + l(message) + '', + '
', + '
' + ].join(''), + hideDelay: 5000, + position: 'top right' + }); + else + console.debug('untrap error'); } // Listen to HTTP errors broadcasted from HTTP interceptor diff --git a/UI/WebServerResources/js/Common/sgAvatarImage.directive.js b/UI/WebServerResources/js/Common/sgAvatarImage.directive.js index 13efe3fb9..c29cab748 100644 --- a/UI/WebServerResources/js/Common/sgAvatarImage.directive.js +++ b/UI/WebServerResources/js/Common/sgAvatarImage.directive.js @@ -6,7 +6,7 @@ /** * sgAvatarImage - An avatar directive that returns un img element with either a local URL (if sg-src is specified) - * or a Gravatar URL built from the Gravatar factory. + * or a Gravatar URL built from the Gravatar factory (using sg-email). * Based on http://blog.lingohub.com/2014/08/better-ux-with-angularjs-directives/. * @memberof SOGo.Common * @example: @@ -15,60 +15,54 @@ function sgAvatarImage() { return { restrict: 'AE', - scope: { + scope: {}, + bindToController: { size: '@', email: '=sgEmail', src: '=sgSrc' }, - template: '', + template: [ + 'person', // the generic icon + '' // the gravatar or local image + ].join(''), link: link, - bindToController: true, controller: 'sgAvatarImageController', controllerAs: 'vm' }; } function link(scope, element, attrs, controller) { - var el = element[0], - className = el.className, - imgElement = element.find('img'), - img = imgElement[0]; + var imgElement = element.find('img'), + mdIconElement = element.find('md-icon'); if (attrs.size) { imgElement.attr('width', attrs.size); imgElement.attr('height', attrs.size); } - imgElement.bind('error', function() { - // Error while loading external link; insert a generic avatar - controller.insertGenericAvatar(img); - }); + controller.img = imgElement; + controller.genericImg = mdIconElement; } /** * @ngInject */ - sgAvatarImageController.$inject = ['$scope', '$element', 'Preferences', 'Gravatar']; - function sgAvatarImageController($scope, $element, Preferences, Gravatar) { - var vm = this; + sgAvatarImageController.$inject = ['$scope', '$element', '$http', '$q', 'Preferences', 'Gravatar']; + function sgAvatarImageController($scope, $element, $http, $q, Preferences, Gravatar) { + var vm; - $scope.$watch('vm.email', function(email) { + vm = this; - Preferences.ready().then(function() { - var img = $element.find('img')[0]; - if (!email && !vm.genericAvatar) { - // If no email is specified, insert a generic avatar - vm.insertGenericAvatar(img); - } - else if (email && !vm.url) { - if (vm.genericAvatar) { - // Remove generic avatar and restore visibility of image - vm.genericAvatar.parentNode.removeChild(vm.genericAvatar); - delete vm.genericAvatar; - img.classList.remove('ng-hide'); - } - vm.url = Gravatar(email, vm.size, Preferences.defaults.SOGoAlternateAvatar); + // Wait on user's defaults + Preferences.ready().then(function() { + $scope.$watch('vm.email', function(email, old) { + if (email && vm.urlEmail != email) { + // Email has changed or doesn't match the current URL (this happens when using md-virtual-repeat) + showGenericAvatar(); + getGravatar(email); } + else if (!email) + showGenericAvatar(); }); }); @@ -76,21 +70,44 @@ if ('sg-src' in $element[0].attributes) { $scope.$watch('vm.src', function(src) { if (src) { + // Set image URL and save the associated email address vm.url = src; + vm.urlEmail = '' + vm.email; + hideGenericAvatar(); } }); } - vm.insertGenericAvatar = function(img) { - var avatar; + function getGravatar(email) { + var url = Gravatar(email, vm.size, Preferences.defaults.SOGoAlternateAvatar); + $http({ + method: 'GET', + url: url, + cache: true, + headers: { Accept: 'image/*' } + }).then(function successCallback() { + if (!vm.url) { + // Set image URL and save the associated email address + vm.url = url; + vm.urlEmail = email; + hideGenericAvatar(); + } + }, function errorCallback() { + showGenericAvatar(); + }); + } - if (!vm.genericAvatar) { - avatar = document.createElement('md-icon'); - avatar.className = 'material-icons icon-person'; - img.classList.add('ng-hide'); - vm.genericAvatar = img.parentNode.insertBefore(avatar, img); - } - }; + function showGenericAvatar() { + vm.url = null; + vm.urlEmail = null; + vm.img.addClass('ng-hide'); + vm.genericImg.removeClass('ng-hide'); + } + + function hideGenericAvatar() { + vm.genericImg.addClass('ng-hide'); + vm.img.removeClass('ng-hide'); + } } angular diff --git a/UI/WebServerResources/scss/components/virtualRepeat/virtual-repeat.scss b/UI/WebServerResources/scss/components/virtualRepeat/virtual-repeat.scss index 168aed8eb..52719c083 100644 --- a/UI/WebServerResources/scss/components/virtualRepeat/virtual-repeat.scss +++ b/UI/WebServerResources/scss/components/virtualRepeat/virtual-repeat.scss @@ -6,5 +6,6 @@ md-virtual-repeat-container { // Fix weird scroll behavior when reaching bottom of list // See https://github.com/angular/material/issues/4169 padding-top: 0; + padding-bottom: 0; } } \ No newline at end of file