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");
}