From 006acadc25c2c068bd5696ead941bfb330cea7a9 Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Tue, 3 Jan 2017 17:11:10 -0500 Subject: [PATCH] Systematically truncate breadcrumbs based on their length to keep them inside the breadcrumb bar. This does not work on inventory manage breadcrumbs as those are controlled via a different mechanism. --- .../src/bread-crumb/bread-crumb.block.less | 1 - .../src/bread-crumb/bread-crumb.directive.js | 26 ++++-- .../src/bread-crumb/bread-crumb.partial.html | 1 + .../src/bread-crumb/bread-crumb.service.js | 79 +++++++++++++++++++ awx/ui/client/src/bread-crumb/main.js | 2 + .../organizations-admins.controller.js | 1 + .../organizations-inventories.controller.js | 1 + .../organizations-job-templates.controller.js | 1 + .../organizations-projects.controller.js | 1 + .../organizations-teams.controller.js | 1 + .../organizations-users.controller.js | 1 + awx/ui/client/src/partials/breadcrumb.html | 4 +- awx/ui/client/src/shared/directives.js | 14 ++++ 13 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 awx/ui/client/src/bread-crumb/bread-crumb.service.js diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.block.less b/awx/ui/client/src/bread-crumb/bread-crumb.block.less index ac8e0792c9..e0abee7832 100644 --- a/awx/ui/client/src/bread-crumb/bread-crumb.block.less +++ b/awx/ui/client/src/bread-crumb/bread-crumb.block.less @@ -66,7 +66,6 @@ display: inline-block; color: @default-interface-txt; text-transform: uppercase; - max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.directive.js b/awx/ui/client/src/bread-crumb/bread-crumb.directive.js index 5cc247d232..7e58100ea0 100644 --- a/awx/ui/client/src/bread-crumb/bread-crumb.directive.js +++ b/awx/ui/client/src/bread-crumb/bread-crumb.directive.js @@ -1,6 +1,6 @@ export default - ['templateUrl', '$state', 'FeaturesService', 'ProcessErrors','$rootScope', 'Store', 'Empty', - function(templateUrl, $state, FeaturesService, ProcessErrors, $rootScope, Store, Empty) { + ['templateUrl', '$state', 'FeaturesService', 'ProcessErrors','$rootScope', 'Store', 'Empty', '$window', 'BreadCrumbService', + function(templateUrl, $state, FeaturesService, ProcessErrors, $rootScope, Store, Empty, $window, BreadCrumbService) { return { restrict: 'E', templateUrl: templateUrl('bread-crumb/bread-crumb'), @@ -8,9 +8,25 @@ export default var streamConfig = {}, originalRoute; - scope.showActivityStreamButton = false; - scope.showRefreshButton = false; - scope.loadingLicense = true; + function init() { + + scope.showActivityStreamButton = false; + scope.showRefreshButton = false; + scope.loadingLicense = true; + + function onResize(){ + BreadCrumbService.truncateCrumbs(); + } + + function cleanUp() { + angular.element($window).off('resize', onResize); + } + + angular.element($window).on('resize', onResize); + scope.$on('$destroy', cleanUp); + } + + init(); scope.refresh = function() { $state.go($state.current, {}, {reload: true}); diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.partial.html b/awx/ui/client/src/bread-crumb/bread-crumb.partial.html index 4500556e96..563e6c4f79 100644 --- a/awx/ui/client/src/bread-crumb/bread-crumb.partial.html +++ b/awx/ui/client/src/bread-crumb/bread-crumb.partial.html @@ -30,4 +30,5 @@ + diff --git a/awx/ui/client/src/bread-crumb/bread-crumb.service.js b/awx/ui/client/src/bread-crumb/bread-crumb.service.js new file mode 100644 index 0000000000..903276b446 --- /dev/null +++ b/awx/ui/client/src/bread-crumb/bread-crumb.service.js @@ -0,0 +1,79 @@ +export default + [function(){ + return { + truncateCrumbs: function(){ + let breadCrumbBarWidth = $('#bread_crumb').outerWidth(); + let menuLinkWidth = $('.BreadCrumb-menuLinkHolder').outerWidth(); + let availableWidth = breadCrumbBarWidth - menuLinkWidth; + let $breadcrumbClone = $('.BreadCrumb-list').clone().appendTo('#bread_crumb_width_checker'); + let $breadcrumbCloneItems = $breadcrumbClone.find('.BreadCrumb-item'); + // 40px for the padding on the breadcrumb bar and a few extra pixels for rounding + let expandedBreadcrumbWidth = 45; + let crumbs = []; + $breadcrumbCloneItems.css('max-width', 'none'); + $breadcrumbCloneItems.each(function(index, item){ + let crumbWidth = $(item).outerWidth(); + expandedBreadcrumbWidth += crumbWidth; + crumbs.push({ + index: index, + origWidth: crumbWidth + }); + }); + // Remove the clone from the dom + $breadcrumbClone.remove(); + if(expandedBreadcrumbWidth > availableWidth) { + let widthToTrim = expandedBreadcrumbWidth - availableWidth; + // Sort the crumbs from biggest to smallest + let sortedCrumbs = _.sortByOrder(crumbs, ["origWidth"], ["desc"]); + let maxWidth; + for(let i=0; i widthToTrim) { + // If we trim down the biggest (i+1) crumbs equally then we can make it fit + maxWidth = maxWidth - (widthToTrim/potentialCrumbsToTrim); + break; + } + else { + // Trim this biggest crumb down to the next biggest + widthToTrim = widthToTrim - (sortedCrumbs[i].origWidth - sortedCrumbs[i+1].origWidth); + maxWidth = sortedCrumbs[i].origWidth; + } + } + else { + // This is the biggest crumb + if(sortedCrumbs[i].origWidth - widthToTrim > sortedCrumbs[i+1].origWidth) { + maxWidth = sortedCrumbs[i].origWidth - widthToTrim; + break; + } + else { + // Trim this biggest crumb down to the next biggest + widthToTrim = widthToTrim - (sortedCrumbs[i].origWidth - sortedCrumbs[i+1].origWidth); + maxWidth = sortedCrumbs[i+1].origWidth; + } + } + } + else { + // This is the smallest crumb + if(sortedCrumbs[i-1]) { + // We've gotten all the way down to the smallest crumb without being able to reasonably trim + // the previous crumbs. Go ahead and trim all of them equally. + maxWidth = availableWidth/(i+1); + } + else { + // There's only one breadcrumb so trim this one down + maxWidth = sortedCrumbs[i].origWidth - widthToTrim; + } + } + } + $('.BreadCrumb-item').css('max-width', maxWidth); + } + else { + $('.BreadCrumb-item').css('max-width', 'none'); + } + } + }; + }]; diff --git a/awx/ui/client/src/bread-crumb/main.js b/awx/ui/client/src/bread-crumb/main.js index fde7a7991c..6369beda61 100644 --- a/awx/ui/client/src/bread-crumb/main.js +++ b/awx/ui/client/src/bread-crumb/main.js @@ -1,5 +1,7 @@ import breadCrumb from './bread-crumb.directive'; +import breadCrumbService from './bread-crumb.service'; export default angular.module('breadCrumb', []) + .service('BreadCrumbService', breadCrumbService) .directive('breadCrumb', breadCrumb); diff --git a/awx/ui/client/src/organizations/linkout/controllers/organizations-admins.controller.js b/awx/ui/client/src/organizations/linkout/controllers/organizations-admins.controller.js index df3075305e..016421163c 100644 --- a/awx/ui/client/src/organizations/linkout/controllers/organizations-admins.controller.js +++ b/awx/ui/client/src/organizations/linkout/controllers/organizations-admins.controller.js @@ -29,6 +29,7 @@ export default ['$stateParams', '$scope', 'UserList', 'Rest', '$state', Rest.get() .success(function(data) { $scope.organization_name = data.name; + $scope.name = data.name; $scope.org_id = data.id; $scope.orgRelatedUrls = data.related; diff --git a/awx/ui/client/src/organizations/linkout/controllers/organizations-inventories.controller.js b/awx/ui/client/src/organizations/linkout/controllers/organizations-inventories.controller.js index 22b959fae5..ae92d23058 100644 --- a/awx/ui/client/src/organizations/linkout/controllers/organizations-inventories.controller.js +++ b/awx/ui/client/src/organizations/linkout/controllers/organizations-inventories.controller.js @@ -31,6 +31,7 @@ export default ['$scope', '$rootScope', '$location', '$log', .success(function(data) { $scope.organization_name = data.name; + $scope.name = data.name; $scope.org_id = data.id; $scope.orgRelatedUrls = data.related; diff --git a/awx/ui/client/src/organizations/linkout/controllers/organizations-job-templates.controller.js b/awx/ui/client/src/organizations/linkout/controllers/organizations-job-templates.controller.js index fb6517460f..7df8a2a344 100644 --- a/awx/ui/client/src/organizations/linkout/controllers/organizations-job-templates.controller.js +++ b/awx/ui/client/src/organizations/linkout/controllers/organizations-job-templates.controller.js @@ -32,6 +32,7 @@ export default ['$scope', '$rootScope', '$location', '$log', Rest.get() .success(function(data) { $scope.organization_name = data.name; + $scope.name = data.name; $scope.org_id = data.id; $scope.orgRelatedUrls = data.related; diff --git a/awx/ui/client/src/organizations/linkout/controllers/organizations-projects.controller.js b/awx/ui/client/src/organizations/linkout/controllers/organizations-projects.controller.js index 6205ae0ea8..b3851ad1a5 100644 --- a/awx/ui/client/src/organizations/linkout/controllers/organizations-projects.controller.js +++ b/awx/ui/client/src/organizations/linkout/controllers/organizations-projects.controller.js @@ -104,6 +104,7 @@ export default ['$scope', '$rootScope', '$location', '$log', Rest.get() .success(function(data) { $scope.organization_name = data.name; + $scope.name = data.name; $scope.org_id = data.id; $scope.orgRelatedUrls = data.related; diff --git a/awx/ui/client/src/organizations/linkout/controllers/organizations-teams.controller.js b/awx/ui/client/src/organizations/linkout/controllers/organizations-teams.controller.js index efa5c88ac7..654ed8ee59 100644 --- a/awx/ui/client/src/organizations/linkout/controllers/organizations-teams.controller.js +++ b/awx/ui/client/src/organizations/linkout/controllers/organizations-teams.controller.js @@ -37,6 +37,7 @@ export default ['$scope', '$rootScope', '$location', '$log', '$stateParams', 'Or .success(function(data) { $scope.organization_name = data.name; + $scope.name = data.name; $scope.org_id = data.id; $scope.orgRelatedUrls = data.related; diff --git a/awx/ui/client/src/organizations/linkout/controllers/organizations-users.controller.js b/awx/ui/client/src/organizations/linkout/controllers/organizations-users.controller.js index 2f3e0f7872..f8ac32f061 100644 --- a/awx/ui/client/src/organizations/linkout/controllers/organizations-users.controller.js +++ b/awx/ui/client/src/organizations/linkout/controllers/organizations-users.controller.js @@ -29,6 +29,7 @@ export default ['$stateParams', '$scope', 'OrgUserList', 'AddUserList','Rest', ' Rest.get() .success(function(data) { $scope.organization_name = data.name; + $scope.name = data.name; $scope.org_id = data.id; $scope.orgRelatedUrls = data.related; diff --git a/awx/ui/client/src/partials/breadcrumb.html b/awx/ui/client/src/partials/breadcrumb.html index b886fa4067..c4e12f87e8 100644 --- a/awx/ui/client/src/partials/breadcrumb.html +++ b/awx/ui/client/src/partials/breadcrumb.html @@ -1,8 +1,8 @@ diff --git a/awx/ui/client/src/shared/directives.js b/awx/ui/client/src/shared/directives.js index 4e8f8f38a8..1da55f80f8 100644 --- a/awx/ui/client/src/shared/directives.js +++ b/awx/ui/client/src/shared/directives.js @@ -1168,4 +1168,18 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'JobsHelper']) }); } }; +}]) + +.directive('awTruncateBreadcrumb', ['BreadCrumbService', function(BreadCrumbService) { + return { + restrict: 'A', + scope: { + breadcrumbStep: '=' + }, + link: function(scope) { + scope.$watch('breadcrumbStep.ncyBreadcrumbLabel', function(){ + BreadCrumbService.truncateCrumbs(); + }); + } + }; }]);