diff --git a/ui/help.html b/ui/help.html index c384a8c2d..92f6ee237 100644 --- a/ui/help.html +++ b/ui/help.html @@ -114,7 +114,12 @@ esc Close all open job or filter panels f - Enter a filter for platforms and jobs + Enter a quick filter + + ctrlshift + f + Clear the quick filter + ← Select previous job → @@ -123,8 +128,8 @@ Select previous unclassified failure j or n Select next unclassified failure - r - Retrigger selected job + l + Open the logviewer for the selected job ctrl or cmd Add job to the pinboard during click selection spacebar @@ -140,17 +145,14 @@ u Clear the pinboard - - ctrlshift - f - Clear the filter for platforms and jobs - + r + Retrigger selected job + ctrlbackspace + Delete job classification and related bugs i Toggle in-progress (running/pending) jobs u Show only unclassified failures - l - Open the logviewer for the selected job

Copy values on hover

diff --git a/ui/js/controllers/main.js b/ui/js/controllers/main.js index cb63c40ec..e40af5b46 100644 --- a/ui/js/controllers/main.js +++ b/ui/js/controllers/main.js @@ -239,6 +239,13 @@ treeherderApp.controller('MainCtrl', [ } }); + // Shortcut: delete classification and related bugs + Mousetrap.bind('ctrl+backspace', function() { + if ($scope.selectedJob) { + $scope.$evalAsync($rootScope.$emit(thEvents.deleteClassification)); + } + }); + }; $scope.repoModel = ThRepositoryModel; diff --git a/ui/js/directives/clonejobs.js b/ui/js/directives/clonejobs.js index bc73ddee8..29b50241e 100644 --- a/ui/js/directives/clonejobs.js +++ b/ui/js/directives/clonejobs.js @@ -98,26 +98,22 @@ treeherder.directive('thCloneJobs', [ }); - $rootScope.$on(thEvents.selectJob, function(ev, job) { - selectJob(job); + $rootScope.$on(thEvents.selectJob, function(ev, job, job_selection_type) { + selectJob(job, job_selection_type); }); $rootScope.$on(thEvents.clearSelectedJob, function(ev, job) { clearSelectJobStyles(); }); - var selectJob = function(job){ - + var selectJob = function(job, job_selection_type) { var jobKey = getJobMapKey(job); var jobEl = $('.' + jobKey); - clickJobCb({}, jobEl, job); + clickJobCb({}, jobEl, job, job_selection_type); scrollToElement(jobEl); - ThResultSetStore.setSelectedJob( - $rootScope.repoName, jobEl, job - ); - + ThResultSetStore.setSelectedJob($rootScope.repoName, jobEl, job); }; var setSelectJobStyles = function(el){ @@ -149,7 +145,7 @@ treeherder.directive('thCloneJobs', [ }; var broadcastJobChangedTimeout = null; - var clickJobCb = function(ev, el, job){ + var clickJobCb = function(ev, el, job, job_selection_type){ setSelectJobStyles(el); // delay switching right away, in case the user is switching rapidly // between jobs @@ -157,7 +153,7 @@ treeherder.directive('thCloneJobs', [ window.clearTimeout(broadcastJobChangedTimeout); } broadcastJobChangedTimeout = window.setTimeout(function() { - $rootScope.$emit(thEvents.jobClick, job); + $rootScope.$emit(thEvents.jobClick, job, job_selection_type); }, 200); }; diff --git a/ui/js/providers.js b/ui/js/providers.js index f4968ee81..36c81a729 100644 --- a/ui/js/providers.js +++ b/ui/js/providers.js @@ -219,6 +219,8 @@ treeherder.provider('thEvents', function() { saveClassification: "save-classification-EVT", + deleteClassification: "delete-classification-EVT", + clearPinboard: "clear-pinboard-EVT", searchPage: "search-page-EVT", diff --git a/ui/plugins/annotations/controller.js b/ui/plugins/annotations/controller.js index 8ddfaf956..27e315620 100644 --- a/ui/plugins/annotations/controller.js +++ b/ui/plugins/annotations/controller.js @@ -15,11 +15,27 @@ treeherder.controller('AnnotationsPluginCtrl', [ $log.debug("annotations plugin initialized"); - $scope.$watch('classifications', function(newValue, oldValue){ - + $scope.$watch('classifications', function(newValue, oldValue) { thTabs.tabs.annotations.num_items = newValue ? $scope.classifications.length : 0; }, true); + $rootScope.$on(thEvents.deleteClassification, function(event) { + if ($scope.classifications[0]) { + $scope.deleteClassification($scope.classifications[0]); + + // Delete any number of bugs if they exist + for (var i = 0; i < $scope.bugs.length; i++) { + $scope.deleteBug($scope.bugs[i]); + } + + // We reselect job in place ensuring a correct state for other actions + // Potential update with follow up 1181271 + $rootScope.$emit(thEvents.selectJob, $rootScope.selectedJob, 'passive'); + } else { + thNotify.send("No classification on this job to delete", 'warning'); + } + }); + $scope.deleteClassification = function(classification) { var key = "key" + classification.job_id; diff --git a/ui/plugins/controller.js b/ui/plugins/controller.js index fc7b7bc06..bad3c97b4 100644 --- a/ui/plugins/controller.js +++ b/ui/plugins/controller.js @@ -48,7 +48,12 @@ treeherder.controller('PluginCtrl', [ var selectJobPromise = null; var selectJobRetryPromise = null; - var selectJob = function(job_id) { + var selectJob = function(job_id, job_selection_type) { + // All interactive selection in treeherder is 'active' + // by definition but we set it here + if (typeof job_selection_type == 'undefined') { + job_selection_type = 'active'; + } // set the scope variables needed for the job detail panel if (job_id) { $scope.job_detail_loading = true; @@ -92,22 +97,27 @@ treeherder.controller('PluginCtrl', [ $scope.eta_abs = Math.abs($scope.job.get_current_eta()); $scope.typical_eta = $scope.job.get_typical_eta(); - // we handle which tab gets presented in the job details panel - // and a special set of rules for talos - if ($scope.job.job_group_name.indexOf('Talos') !== -1) { - $scope.tabService.tabs.talos.enabled = true; - if (thResultStatus($scope.job) === 'success') { - $scope.tabService.selectedTab = 'talos'; + // During save or delete classification we reselect the same + // job to update correct tab contents and job state, but we + // don't want to trigger this tab switch in that scenario + if (job_selection_type !== 'passive') { + // we handle which tab gets presented in the job details panel + // and a special set of rules for talos + if ($scope.job.job_group_name.indexOf('Talos') !== -1) { + $scope.tabService.tabs.talos.enabled = true; + if (thResultStatus($scope.job) === 'success') { + $scope.tabService.selectedTab = 'talos'; + } else { + $scope.tabService.selectedTab = 'failureSummary'; + } } else { - $scope.tabService.selectedTab = 'failureSummary'; - } - } else { - // tab presentation for any other (non-talos) job - $scope.tabService.tabs.talos.enabled = false; - if (thResultStatus($scope.job) === 'success') { - $scope.tabService.selectedTab = 'jobDetails'; - } else { - $scope.tabService.selectedTab = 'failureSummary'; + // tab presentation for any other (non-talos) job + $scope.tabService.tabs.talos.enabled = false; + if (thResultStatus($scope.job) === 'success') { + $scope.tabService.selectedTab = 'jobDetails'; + } else { + $scope.tabService.selectedTab = 'failureSummary'; + } } } @@ -336,15 +346,15 @@ treeherder.controller('PluginCtrl', [ } }; - var selectJobAndRender = function(job_id){ - $scope.jobLoadedPromise = selectJob(job_id); + var selectJobAndRender = function(job_id, job_selection_type){ + $scope.jobLoadedPromise = selectJob(job_id, job_selection_type); $scope.jobLoadedPromise.then(function(){ thTabs.showTab(thTabs.selectedTab, job_id); }); }; - $rootScope.$on(thEvents.jobClick, function(event, job) { - selectJobAndRender(job.id); + $rootScope.$on(thEvents.jobClick, function(event, job, job_selection_type) { + selectJobAndRender(job.id, job_selection_type); $rootScope.selectedJob = job; }); diff --git a/ui/plugins/pinboard.js b/ui/plugins/pinboard.js index 34ae45ff5..09491abeb 100644 --- a/ui/plugins/pinboard.js +++ b/ui/plugins/pinboard.js @@ -75,6 +75,10 @@ treeherder.controller('PinboardCtrl', [ thPinboard.save(classification); $scope.completeClassification(); $scope.classification = thPinboard.createNewClassification(); + + // We reselect job in place ensuring a correct state for other actions + // Potential update with follow up 1181271 + $rootScope.$emit(thEvents.selectJob, $rootScope.selectedJob, 'passive'); } else { thNotify.send("Must be logged in to save job classifications", "danger"); }