/** * The application header bar. */ angular.module('quay').directive('headerBar', function () { var number = 0; var directiveDefinitionObject = { priority: 0, templateUrl: '/static/directives/header-bar.html', replace: false, transclude: false, restrict: 'C', scope: { }, controller: function($rootScope, $scope, $element, $location, $timeout, hotkeys, UserService, PlanService, ApiService, NotificationService, Config, CreateService, Features, DocumentationService, ExternalLoginService) { $scope.externalSigninUrl = ExternalLoginService.getSingleSigninUrl(); var hotkeysAdded = false; var userUpdated = function(cUser) { $scope.searchingAllowed = Features.ANONYMOUS_ACCESS || !cUser.anonymous; if (hotkeysAdded) { return; } hotkeysAdded = true; // Register hotkeys. if ($scope.searchingAllowed) { hotkeys.add({ combo: '/', description: 'Show search', callback: function(e) { e.preventDefault(); e.stopPropagation(); $scope.toggleSearch(); } }); } if (!cUser.anonymous) { hotkeys.add({ combo: 'alt+c', description: 'Create new repository', callback: function(e) { e.preventDefault(); e.stopPropagation(); $location.url('/new'); } }); } }; $scope.Config = Config; $scope.Features = Features; $scope.notificationService = NotificationService; $scope.searchingAllowed = false; $scope.searchVisible = false; $scope.currentSearchQuery = null; $scope.searchResultState = null; $scope.showBuildDialogCounter = 0; // Monitor any user changes and place the current user into the scope. UserService.updateUserIn($scope, userUpdated); $scope.currentPageContext = {}; $rootScope.$watch('currentPage.scope.viewuser', function(u) { $scope.currentPageContext['viewuser'] = u; }); $rootScope.$watch('currentPage.scope.organization', function(o) { $scope.currentPageContext['organization'] = o; }); $rootScope.$watch('currentPage.scope.repository', function(r) { $scope.currentPageContext['repository'] = r; }); var documentSearchMaxResults = 10; var documentSearchScoreThreshold = 0.9; var conductDocumentationSearch = function(query) { if (!query) { return; } var mapper = function(result, score) { return { 'kind': 'doc', 'name': result.title.replace(/'\;/g, "'"), 'score': score, 'href': Config.DOCUMENTATION_LOCATION + result.url } }; DocumentationService.findDocumentation($scope, query.split(' '), function(results) { if (!$scope.searchVisible) { return; } var currentResults = $scope.searchResultState['results'] || []; results.forEach(function(result) { if (currentResults.length < documentSearchMaxResults) { currentResults.push(result); } }); $scope.searchResultState = { 'state': currentResults.length ? 'results' : 'no-results', 'results': currentResults, 'current': currentResults.length ? 0 : -1 }; }, mapper, documentSearchScoreThreshold); } var conductSearch = function(query) { if (!query) { $scope.searchResultState = null; return; } $scope.searchResultState = { 'state': 'loading' }; var params = { 'query': query }; ApiService.conductSearch(null, params).then(function(resp) { if (!$scope.searchVisible || query != $scope.currentSearchQuery) { return; } $scope.searchResultState = { 'state': resp.results.length ? 'results' : 'no-results', 'results': resp.results, 'current': resp.results.length ? 0 : -1 }; if (resp.results.length < documentSearchMaxResults) { conductDocumentationSearch(query); } }, function(resp) { $scope.searchResultState = null; }, /* background */ true); }; $scope.$watch('currentSearchQuery', conductSearch); $scope.signout = function() { ApiService.logout().then(function() { UserService.load(); $location.path('/'); }); }; $scope.appLinkTarget = function() { if ($scope._appLinkTarget) { return $scope._appLinkTarget; } if ($("div[ng-view]").length === 0) { return $scope._appLinkTarget = "_self"; } return $scope._appLinkTarget = ""; }; $scope.getEnterpriseLogo = function() { return Config.getEnterpriseLogo(false); }; $scope.toggleSearch = function() { $scope.searchVisible = !$scope.searchVisible; if ($scope.searchVisible) { $('#search-box-input').focus(); if ($scope.currentSearchQuery) { conductSearch($scope.currentSearchQuery); } } else { $('#search-box-input').blur() $scope.searchResultState = null; } }; $scope.getSearchBoxClasses = function(searchVisible, searchResultState) { var classes = searchVisible ? 'search-visible ' : ''; if (searchResultState) { classes += 'results-visible'; } return classes; }; $scope.handleSearchKeyDown = function(e) { if (e.keyCode == 27) { $scope.toggleSearch(); return; } var state = $scope.searchResultState; if (!state || !state['results']) { return; } if (e.keyCode == 40) { state['current']++; e.preventDefault(); } else if (e.keyCode == 38) { state['current']--; e.preventDefault(); } else if (e.keyCode == 13) { var current = state['current']; if (current >= 0 && current < state['results'].length) { $scope.showResult(state['results'][current]); } e.preventDefault(); } if (state['current'] < -1) { state['current'] = state['results'].length - 1; } else if (state['current'] >= state['results'].length) { state['current'] = 0; } }; $scope.showResult = function(result) { $scope.toggleSearch(); $timeout(function() { if (result['kind'] == 'doc') { window.location = result['href']; return; } $scope.currentSearchQuery = ''; $location.url(result['href']) }, 500); }; $scope.setCurrentResult = function(result) { if (!$scope.searchResultState) { return; } $scope.searchResultState['current'] = result; }; $scope.getNamespace = function(context) { if (!context) { return null; } if (context.repository && context.repository.namespace) { return context.repository.namespace; } if (context.organization && context.organization.name) { return context.organization.name; } if (context.viewuser && context.viewuser.username) { return context.viewuser.username; } return null; }; $scope.canAdmin = function(namespace) { if (!namespace) { return false; } return UserService.isNamespaceAdmin(namespace); }; $scope.isOrganization = function(namespace) { if (!namespace) { return false; } return UserService.isOrganization(namespace); }; $scope.startBuild = function(context) { $scope.showBuildDialogCounter++; }; $scope.handleBuildStarted = function(build, context) { $location.url('/repository/' + context.repository.namespace + '/' + context.repository.name + '/build/' + build.id); }; $scope.createRobot = function(context) { var namespace = $scope.getNamespace(context); CreateService.askCreateRobot(namespace, function(created) { if (UserService.isOrganization(namespace)) { $location.url('/organization/' + namespace + '?tab=robots&showRobot=' + created.name); } else { $location.url('/user/' + namespace + '?tab=robots&showRobot=' + created.name); } }); }; $scope.createTeam = function(context) { var namespace = $scope.getNamespace(context); if (!namespace || !UserService.isNamespaceAdmin(namespace)) { return; } CreateService.askCreateTeam(namespace, function(created) { $location.url('/organization/' + namespace + '/teams/' + created.name); }); }; } }; return directiveDefinitionObject; });