зеркало из https://github.com/mozilla/treeherder.git
coalesced jobs visible and filterable
This commit is contained in:
Родитель
0a53fc2136
Коммит
64fa1a7a09
|
@ -296,19 +296,18 @@ body {
|
|||
}
|
||||
|
||||
.result-set-title-left {
|
||||
width: 600px;
|
||||
padding-right: 10px;
|
||||
white-space: nowrap;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.result-set .revision-list {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.revision-link {
|
||||
padding-top: 5px;
|
||||
width: 155px;
|
||||
.result-set-buttons {
|
||||
width: 242px;
|
||||
display: block;
|
||||
}
|
||||
.revision-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
@ -668,6 +667,10 @@ ul.bug-suggestion-list li .btn-xs{
|
|||
* RESULT STATUS COUNTS
|
||||
*/
|
||||
|
||||
.result-counts {
|
||||
margin-left: -11px;
|
||||
}
|
||||
|
||||
.result-status-shading-success {background-color: rgba(2, 131, 44, 0.24);}
|
||||
.result-status-shading-testfailed {background-color: rgba(221, 102, 2, 0.25);}
|
||||
.result-status-shading-busted {background-color: rgba(144, 0, 0, 0.25);}
|
||||
|
@ -676,6 +679,7 @@ ul.bug-suggestion-list li .btn-xs{
|
|||
.result-status-shading-usercancel {background-color: rgba(250, 115, 172, 0.25)}
|
||||
.result-status-shading-pending {background-color: white;}
|
||||
.result-status-shading-running {background-color: white;}
|
||||
.result-status-shading-coalesced {background-color: white;}
|
||||
|
||||
.result-status-count-group {
|
||||
font-size: 12px;
|
||||
|
@ -721,6 +725,9 @@ ul.bug-suggestion-list li .btn-xs{
|
|||
.result-status-count-pending {
|
||||
width: 69px;
|
||||
}
|
||||
.result-status-count-coalesced {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.click-able-icon, .nav-tabs li {
|
||||
cursor: pointer;
|
||||
|
@ -982,6 +989,36 @@ fieldset[disabled] .btn-purple.active {
|
|||
color: rgba(61, 2, 85, 0.68);
|
||||
}
|
||||
|
||||
.btn-yellow {
|
||||
border-color: rgba(205, 206, 29, 0.24);
|
||||
color: #cdce1d;
|
||||
}
|
||||
.btn-yellow:hover,
|
||||
.btn-yellow:focus,
|
||||
.btn-yellow:active,
|
||||
.btn-yellow.active {
|
||||
border-color: #cdce1d;
|
||||
color: #cdce1d;
|
||||
}
|
||||
.btn-yellow.disabled:hover,
|
||||
.btn-yellow.disabled:focus,
|
||||
.btn-yellow.disabled:active,
|
||||
.btn-yellow.disabled.active,
|
||||
.btn-yellow[disabled]:hover,
|
||||
.btn-yellow[disabled]:focus,
|
||||
.btn-yellow[disabled]:active,
|
||||
.btn-yellow[disabled].active,
|
||||
fieldset[disabled] .btn-yellow:hover,
|
||||
fieldset[disabled] .btn-yellow:focus,
|
||||
fieldset[disabled] .btn-yellow:active,
|
||||
fieldset[disabled] .btn-yellow.active {
|
||||
border-color: #cdce1d;
|
||||
}
|
||||
|
||||
.btn-yellow-count-classified, .btn-yellow-count-unclassified {
|
||||
color: #cdce1d;
|
||||
}
|
||||
|
||||
.btn-ltgray-count-unclassified, .btn-ltgray-count-classified {
|
||||
border-color: #bfbfbf;
|
||||
color: #e0e0e0;
|
||||
|
|
|
@ -11,25 +11,22 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
|
||||
var $log = new ThLog(this.constructor.name);
|
||||
|
||||
$scope.filterOptions = thResultStatusList;
|
||||
$scope.filterOptions = thResultStatusList.all();
|
||||
|
||||
$scope.filterGroups = {
|
||||
failures: {
|
||||
value: "failures",
|
||||
name: "failures",
|
||||
allChecked: true,
|
||||
resultStatuses: ["testfailed", "busted", "exception"]
|
||||
},
|
||||
nonfailures: {
|
||||
value: "nonfailures",
|
||||
name: "non-failures",
|
||||
allChecked: true,
|
||||
resultStatuses: ["success", "retry", "usercancel"]
|
||||
resultStatuses: ["success", "retry", "usercancel", "coalesced"]
|
||||
},
|
||||
inProgress: {
|
||||
value: "inProgress",
|
||||
name: "in progress",
|
||||
allChecked: true,
|
||||
resultStatuses: ["pending", "running"]
|
||||
}
|
||||
};
|
||||
|
@ -41,7 +38,7 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
*
|
||||
* quiet - whether or not to broadcast a message about this change.
|
||||
*/
|
||||
$scope.toggleResultStatusGroup = function(group, quiet) {
|
||||
$scope.toggleResultStatusGroup = function(group) {
|
||||
var check = function(rs) {
|
||||
$scope.resultStatusFilters[rs] = group.allChecked;
|
||||
};
|
||||
|
@ -52,11 +49,6 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
group.resultStatuses,
|
||||
group.allChecked
|
||||
);
|
||||
|
||||
if (!quiet) {
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged,
|
||||
{target: group, newValue: group.allChecked});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -72,8 +64,6 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
} else {
|
||||
thJobFilters.addFilter(thJobFilters.resultStatus, filter);
|
||||
}
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged,
|
||||
{target: filter, newValue: $scope.resultStatusFilters[filter]});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -92,7 +82,7 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
* ``classified`` (when true) or ``unclassified``
|
||||
* (when false)
|
||||
*/
|
||||
$scope.setClassificationFilter = function(isClassified, isChecked, quiet) {
|
||||
$scope.setClassificationFilter = function(isClassified, isChecked) {
|
||||
var field = "isClassified";
|
||||
// this function is called before the checkbox value has actually
|
||||
// changed the scope model value, so change to the inverse.
|
||||
|
@ -100,11 +90,6 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
var target = isClassified? "classified": "unclassified";
|
||||
|
||||
func(field, isClassified, thJobFilters.matchType.bool);
|
||||
|
||||
if (!quiet) {
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged,
|
||||
{target: target, newValue: isChecked});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.createFieldFilter = function() {
|
||||
|
@ -149,18 +134,12 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
field: $scope.newFieldFilter.field,
|
||||
value: value
|
||||
});
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged,
|
||||
{target: $scope.newFieldFilter.field, newValue: $scope.newFieldFilter.value});
|
||||
$scope.newFieldFilter = null;
|
||||
|
||||
};
|
||||
|
||||
$scope.removeAllFieldFilters = function() {
|
||||
$scope.fieldFilters.forEach(function(ff) {
|
||||
thJobFilters.removeFilter(ff.field, ff.value);
|
||||
});
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged,
|
||||
{target: "allFieldFilters", newValue: null});
|
||||
thJobFilters.removeAllFieldFilters();
|
||||
$scope.fieldFilters = [];
|
||||
};
|
||||
|
||||
|
@ -170,14 +149,10 @@ treeherder.controller('FilterPanelCtrl', [
|
|||
$scope.fieldFilters[index].field,
|
||||
$scope.fieldFilters[index].value
|
||||
);
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged,
|
||||
{target: $scope.fieldFilters[index].field, newValue: null});
|
||||
$scope.fieldFilters.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.pinAllShownJobs = function() {
|
||||
thJobFilters.pinAllShownJobs();
|
||||
};
|
||||
$scope.thJobFilters = thJobFilters;
|
||||
|
||||
var updateToggleFilters = function() {
|
||||
for (var i = 0; i < $scope.filterOptions.length; i++) {
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
treeherder.controller('JobsCtrl', [
|
||||
'$scope', '$http', '$rootScope', '$routeParams', 'ThLog', '$cookies',
|
||||
'localStorageService', 'thUrl', 'ThRepositoryModel', 'thSocket',
|
||||
'ThResultSetModel', 'thResultStatusCountsList', '$location', 'thEvents',
|
||||
'ThResultSetModel', 'thResultStatusList', '$location', 'thEvents',
|
||||
function JobsCtrl(
|
||||
$scope, $http, $rootScope, $routeParams, ThLog, $cookies,
|
||||
localStorageService, thUrl, ThRepositoryModel, thSocket,
|
||||
ThResultSetModel, thResultStatusCountsList, $location, thEvents) {
|
||||
ThResultSetModel, thResultStatusList, $location, thEvents) {
|
||||
|
||||
var $log = new ThLog(this.constructor.name);
|
||||
|
||||
|
@ -33,7 +33,7 @@ treeherder.controller('JobsCtrl', [
|
|||
$scope.isLoadingRsBatch = ThResultSetModel.getLoadingStatus($scope.repoName);
|
||||
$scope.result_sets = ThResultSetModel.getResultSetsArray($scope.repoName);
|
||||
$scope.job_map = ThResultSetModel.getJobMap($scope.repoName);
|
||||
$scope.statusList = thResultStatusCountsList;
|
||||
$scope.statusList = thResultStatusList.counts();
|
||||
|
||||
// determine how many resultsets to fetch. default to 10.
|
||||
var count = 10;
|
||||
|
@ -127,6 +127,10 @@ treeherder.controller('ResultSetCtrl', [
|
|||
|
||||
};
|
||||
|
||||
$scope.pinAllShownJobs = function() {
|
||||
thJobFilters.pinAllShownJobs($scope.resultset.id, $scope.resultStatusFilters);
|
||||
};
|
||||
|
||||
$scope.revisionUrlCopied = function(revision) {
|
||||
thNotify.send("url to " + revision + " copied to clipboard");
|
||||
};
|
||||
|
|
|
@ -116,7 +116,6 @@ treeherder.controller('MainCtrl', [
|
|||
|
||||
$scope.toggleExcludedJobs = function() {
|
||||
thJobFilters.toggleSkipExclusionProfiles();
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
};
|
||||
|
||||
$scope.toggleUnclassifiedFailures = function() {
|
||||
|
@ -126,13 +125,10 @@ treeherder.controller('MainCtrl', [
|
|||
} else {
|
||||
thJobFilters.showUnclassifiedFailures();
|
||||
}
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
|
||||
};
|
||||
|
||||
$scope.toggleInProgress = function() {
|
||||
thJobFilters.toggleInProgress();
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
};
|
||||
|
||||
$scope.allExpanded = function(cls) {
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
|
||||
|
||||
treeherder.directive('thPinnedJob', [
|
||||
'thResultStatusInfo',
|
||||
function (thResultStatusInfo) {
|
||||
'thResultStatusInfo', 'thResultStatus',
|
||||
function (thResultStatusInfo, thResultStatus) {
|
||||
|
||||
var getHoverText = function(job) {
|
||||
var duration = Math.round((job.end_timestamp - job.start_timestamp) / 60);
|
||||
var status = job.result;
|
||||
if (job.state !== "completed") {
|
||||
status = job.state;
|
||||
}
|
||||
var status = thResultStatus(job);
|
||||
return job.job_type_name + " - " + status + " - " + duration + "mins";
|
||||
};
|
||||
|
||||
|
@ -18,10 +15,7 @@ treeherder.directive('thPinnedJob', [
|
|||
restrict: "E",
|
||||
link: function(scope, element, attrs) {
|
||||
var unbindWatcher = scope.$watch("job", function(newValue) {
|
||||
var resultState = scope.job.result;
|
||||
if (scope.job.state !== "completed") {
|
||||
resultState = scope.job.state;
|
||||
}
|
||||
var resultState = thResultStatus(scope.job);
|
||||
scope.job.display = thResultStatusInfo(resultState);
|
||||
scope.hoverText = getHoverText(scope.job);
|
||||
|
||||
|
|
|
@ -5,11 +5,12 @@ treeherder.directive('thCloneJobs', [
|
|||
'$rootScope', '$http', 'ThLog', 'thUrl', 'thCloneHtml',
|
||||
'thServiceDomain', 'thResultStatusInfo', 'thEvents', 'thAggregateIds',
|
||||
'thJobFilters', 'thResultStatusObject', 'ThResultSetModel',
|
||||
'ThJobModel', 'linkifyBugsFilter',
|
||||
'ThJobModel', 'linkifyBugsFilter', 'thResultStatus',
|
||||
function(
|
||||
$rootScope, $http, ThLog, thUrl, thCloneHtml, thServiceDomain,
|
||||
thResultStatusInfo, thEvents, thAggregateIds, thJobFilters,
|
||||
thResultStatusObject, ThResultSetModel, ThJobModel, linkifyBugsFilter){
|
||||
$rootScope, $http, ThLog, thUrl, thCloneHtml,
|
||||
thServiceDomain, thResultStatusInfo, thEvents, thAggregateIds,
|
||||
thJobFilters, thResultStatusObject, ThResultSetModel,
|
||||
ThJobModel, linkifyBugsFilter, thResultStatus){
|
||||
|
||||
var $log = new ThLog("thCloneJobs");
|
||||
|
||||
|
@ -49,10 +50,7 @@ treeherder.directive('thCloneJobs', [
|
|||
};
|
||||
|
||||
var getHoverText = function(job) {
|
||||
var jobStatus = job.result;
|
||||
if (job.state !== "completed") {
|
||||
jobStatus = job.state;
|
||||
}
|
||||
var jobStatus = thResultStatus(job);
|
||||
var result = job.job_type_name + " - " + jobStatus;
|
||||
$log.debug("job timestamps", job, job.end_timestamp, job.submit_timestamp);
|
||||
if (job.end_timestamp && job.submit_timestamp) {
|
||||
|
@ -181,16 +179,7 @@ treeherder.directive('thCloneJobs', [
|
|||
job = jgObj.jobs[l];
|
||||
|
||||
//Set the resultState
|
||||
resultState = job.result;
|
||||
if (job.state !== "completed") {
|
||||
resultState = job.state;
|
||||
}
|
||||
resultState = resultState || 'unknown';
|
||||
|
||||
if(job.job_coalesced_to_guid !== null){
|
||||
// Don't count or render coalesced jobs
|
||||
continue;
|
||||
}
|
||||
resultState = thResultStatus(job);
|
||||
|
||||
//Increment the jobCounts here so they're not modified by
|
||||
//filtering
|
||||
|
|
|
@ -11,14 +11,24 @@ treeherder.provider('thServiceDomain', function() {
|
|||
});
|
||||
|
||||
treeherder.provider('thResultStatusList', function() {
|
||||
this.$get = function() {
|
||||
var all = function() {
|
||||
return ['success', 'testfailed', 'busted', 'exception', 'retry', 'usercancel', 'running', 'pending', 'coalesced'];
|
||||
};
|
||||
|
||||
var counts = function() {
|
||||
return ['success', 'testfailed', 'busted', 'exception', 'retry', 'running', 'pending', 'coalesced'];
|
||||
};
|
||||
|
||||
var defaultFilters = function() {
|
||||
return ['success', 'testfailed', 'busted', 'exception', 'retry', 'usercancel', 'running', 'pending'];
|
||||
};
|
||||
});
|
||||
|
||||
treeherder.provider('thResultStatusCountsList', function() {
|
||||
this.$get = function() {
|
||||
return ['success', 'testfailed', 'busted', 'exception', 'retry', 'running', 'pending'];
|
||||
return {
|
||||
all: all,
|
||||
counts: counts,
|
||||
defaultFilters: defaultFilters
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -26,7 +36,9 @@ treeherder.provider('thResultStatus', function() {
|
|||
this.$get = function() {
|
||||
return function(job) {
|
||||
var rs = job.result;
|
||||
if (job.state !== "completed") {
|
||||
if (job.job_coalesced_to_guid !== null) {
|
||||
rs = 'coalesced';
|
||||
} else if (job.state !== "completed") {
|
||||
rs = job.state;
|
||||
}
|
||||
return rs;
|
||||
|
@ -43,7 +55,8 @@ treeherder.provider('thResultStatusObject', function() {
|
|||
'exception':0,
|
||||
'retry':0,
|
||||
'running':0,
|
||||
'pending':0
|
||||
'pending':0,
|
||||
'coalesced': 0
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -62,7 +75,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 100,
|
||||
isCollapsedResults: true,
|
||||
btnClass: "btn-default",
|
||||
showButtonIcon: "glyphicon glyphicon-time",
|
||||
jobButtonIcon: ""
|
||||
};
|
||||
|
||||
|
@ -72,7 +84,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 1,
|
||||
isCollapsedResults: false,
|
||||
btnClass: "btn-red",
|
||||
showButtonIcon: "glyphicon glyphicon-fire",
|
||||
jobButtonIcon: "glyphicon glyphicon-fire",
|
||||
countText: "busted"
|
||||
};
|
||||
|
@ -82,7 +93,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 2,
|
||||
isCollapsedResults: false,
|
||||
btnClass: "btn-purple",
|
||||
showButtonIcon: "glyphicon glyphicon-fire",
|
||||
jobButtonIcon: "glyphicon glyphicon-fire",
|
||||
countText: "exception"
|
||||
};
|
||||
|
@ -92,7 +102,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 3,
|
||||
isCollapsedResults: false,
|
||||
btnClass: "btn-orange",
|
||||
showButtonIcon: "glyphicon glyphicon-warning-sign",
|
||||
jobButtonIcon: "glyphicon glyphicon-warning-sign",
|
||||
countText: "failed"
|
||||
};
|
||||
|
@ -102,7 +111,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 4,
|
||||
isCollapsedResults: false,
|
||||
btnClass: "btn-black",
|
||||
showButtonIcon: "glyphicon glyphicon-warning-sign",
|
||||
jobButtonIcon: "",
|
||||
countText: "unknown"
|
||||
};
|
||||
|
@ -112,7 +120,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 5,
|
||||
isCollapsedResults: true,
|
||||
btnClass: "btn-pink",
|
||||
showButtonIcon: "glyphicon glyphicon-stop",
|
||||
jobButtonIcon: "",
|
||||
countText: "cancel"
|
||||
};
|
||||
|
@ -122,7 +129,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 6,
|
||||
isCollapsedResults: true,
|
||||
btnClass: "btn-dkblue",
|
||||
showButtonIcon: "glyphicon glyphicon-time",
|
||||
jobButtonIcon: "",
|
||||
countText: "retry"
|
||||
};
|
||||
|
@ -132,7 +138,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 7,
|
||||
isCollapsedResults: true,
|
||||
btnClass: "btn-green",
|
||||
showButtonIcon: "glyphicon glyphicon-ok",
|
||||
jobButtonIcon: "",
|
||||
countText: "success"
|
||||
};
|
||||
|
@ -142,7 +147,6 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 8,
|
||||
isCollapsedResults: true,
|
||||
btnClass: "btn-dkgray",
|
||||
showButtonIcon: "glyphicon glyphicon-time",
|
||||
jobButtonIcon: "",
|
||||
countText: "running"
|
||||
};
|
||||
|
@ -152,11 +156,19 @@ treeherder.provider('thResultStatusInfo', function() {
|
|||
severity: 100,
|
||||
isCollapsedResults: true,
|
||||
btnClass: "btn-ltgray",
|
||||
showButtonIcon: "glyphicon glyphicon-time",
|
||||
jobButtonIcon: "",
|
||||
countText: "pending"
|
||||
};
|
||||
break;
|
||||
case "coalesced":
|
||||
resultStatusInfo = {
|
||||
severity: 101,
|
||||
isCollapsedResults: true,
|
||||
btnClass: "btn-yellow",
|
||||
jobButtonIcon: "",
|
||||
countText: "coalesced"
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return resultStatusInfo;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
'use strict';
|
||||
|
||||
treeherder.factory('thBuildApi', [
|
||||
'$http', '$location', 'thUrl', 'thServiceDomain', 'ThLog',
|
||||
function($http, $location, thUrl, thServiceDomain, ThLog) {
|
||||
|
||||
var $log = new ThLog("thBuildApi");
|
||||
var selfServeUrl = "https://secure.pub.build.mozilla.org/buildapi/self-serve/";
|
||||
|
||||
return {
|
||||
retrigger: function(repoName, buildId) {
|
||||
|
||||
var params = {
|
||||
build_id: buildId
|
||||
};
|
||||
|
||||
return $http.post(selfServeUrl + repoName + "/build",
|
||||
{params: params}
|
||||
);
|
||||
},
|
||||
cancel: function(repoName, buildId) {
|
||||
return $http.delete(selfServeUrl + repoName + "/build/" + buildId);
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -22,8 +22,9 @@
|
|||
* must match at least one value in every field.
|
||||
*/
|
||||
treeherder.factory('thJobFilters', [
|
||||
'thResultStatusList', 'ThLog', '$rootScope', 'ThResultSetModel',
|
||||
'thPinboard', 'thNotify', 'thEvents', 'thResultStatus', 'ThRepositoryModel',
|
||||
'thResultStatusList', 'ThLog', '$rootScope',
|
||||
'ThResultSetModel', 'thPinboard', 'thNotify', 'thEvents',
|
||||
'thResultStatus', 'ThRepositoryModel',
|
||||
function(
|
||||
thResultStatusList, ThLog, $rootScope,
|
||||
ThResultSetModel, thPinboard, thNotify, thEvents,
|
||||
|
@ -43,7 +44,7 @@ treeherder.factory('thJobFilters', [
|
|||
var filters = {
|
||||
resultStatus: {
|
||||
matchType: matchType.exactstr,
|
||||
values: thResultStatusList.slice(),
|
||||
values: thResultStatusList.defaultFilters(),
|
||||
removeWhenEmpty: false
|
||||
},
|
||||
isClassified: {
|
||||
|
@ -98,8 +99,8 @@ treeherder.factory('thJobFilters', [
|
|||
if (field === api.resultStatus) {
|
||||
// resultStatus is a special case that spans two job fields
|
||||
var filterList = resultStatusList || filters[field].values;
|
||||
return _.contains(filterList, job.result) ||
|
||||
_.contains(filterList, job.state);
|
||||
var resultState = thResultStatus(job);
|
||||
return _.contains(filterList, resultState);
|
||||
} else if (field === api.isClassified) {
|
||||
// isClassified is a special case, too. Where value of 1 in the
|
||||
// job field of ``failure_classification_id`` is "not classified"
|
||||
|
@ -208,6 +209,7 @@ treeherder.factory('thJobFilters', [
|
|||
|
||||
$log.debug("adding ", field, ": ", value);
|
||||
$log.debug("filters", filters);
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
};
|
||||
|
||||
var removeFilter = function(field, value) {
|
||||
|
@ -220,6 +222,7 @@ treeherder.factory('thJobFilters', [
|
|||
if(idx > -1) {
|
||||
$log.debug("removing ", value);
|
||||
filters[field].values.splice(idx, 1);
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,6 +236,32 @@ treeherder.factory('thJobFilters', [
|
|||
$log.debug("filters", filters);
|
||||
};
|
||||
|
||||
var removeAllFilters = function(field, value) {
|
||||
var someRemoved = false;
|
||||
var removeAll = function(field) {
|
||||
if (!_.contains(['resultStatus', 'isClassified'], field)) {
|
||||
filters[field].values = [];
|
||||
someRemoved = true;
|
||||
}
|
||||
|
||||
// if this filer no longer has any values, then remove it
|
||||
// if it has the ``removeWhenEmpty`` setting
|
||||
if (filters[field].removeWhenEmpty) {
|
||||
delete filters[field];
|
||||
}
|
||||
};
|
||||
|
||||
_.forEach(filterKeys, removeAll);
|
||||
|
||||
if (someRemoved) {
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
}
|
||||
|
||||
|
||||
filterKeys = _.keys(filters);
|
||||
$log.debug("filters", filters);
|
||||
};
|
||||
|
||||
/**
|
||||
* used mostly for resultStatus doing group toggles
|
||||
*
|
||||
|
@ -246,6 +275,7 @@ treeherder.factory('thJobFilters', [
|
|||
for (var i = 0; i < values.length; i++) {
|
||||
action(field, values[i]);
|
||||
}
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
};
|
||||
|
||||
var copyResultStatusFilters = function() {
|
||||
|
@ -373,13 +403,19 @@ treeherder.factory('thJobFilters', [
|
|||
/**
|
||||
* Pin all jobs that pass the GLOBAL filters. Ignores toggling at
|
||||
* the result set level.
|
||||
*
|
||||
* If optional resultsetId is passed in, then only pin jobs from that
|
||||
* resultset.
|
||||
*/
|
||||
var pinAllShownJobs = function() {
|
||||
var pinAllShownJobs = function(resultsetId, resultStatusFilters) {
|
||||
var jobs = ThResultSetModel.getJobMap($rootScope.repoName);
|
||||
var jobsToPin = [];
|
||||
|
||||
var queuePinIfShown = function(jMap) {
|
||||
if (api.showJob(jMap.job_obj)) {
|
||||
if (resultsetId && jMap.job_obj.result_set_id !== resultsetId) {
|
||||
return;
|
||||
}
|
||||
if (api.showJob(jMap.job_obj, resultStatusFilters)) {
|
||||
jobsToPin.push(jMap.job_obj);
|
||||
}
|
||||
};
|
||||
|
@ -392,13 +428,14 @@ treeherder.factory('thJobFilters', [
|
|||
true);
|
||||
}
|
||||
|
||||
$rootScope.selectedJob = jobsToPin[0];
|
||||
if (!$rootScope.selectedJob) {
|
||||
$rootScope.selectedJob = jobsToPin[0];
|
||||
}
|
||||
_.forEach(jobsToPin, thPinboard.pinJob);
|
||||
};
|
||||
|
||||
$rootScope.$on(thEvents.showUnclassifiedFailures, function() {
|
||||
showUnclassifiedFailures();
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -411,6 +448,20 @@ treeherder.factory('thJobFilters', [
|
|||
};
|
||||
filters.resultStatus.values = ["busted", "testfailed", "exception"];
|
||||
filters.isClassified.values = [false];
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the non-field filters so that we only view coalesced jobs
|
||||
*/
|
||||
var showCoalesced = function() {
|
||||
stashedStatusFilterValues = {
|
||||
resultStatus: filters.resultStatus.values,
|
||||
isClassified: filters.isClassified.values
|
||||
};
|
||||
filters.resultStatus.values = ["coalesced"];
|
||||
filters.isClassified.values = [false, true];
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
};
|
||||
|
||||
var toggleInProgress = function() {
|
||||
|
@ -420,6 +471,7 @@ treeherder.factory('thJobFilters', [
|
|||
}
|
||||
func(api.resultStatus, 'pending');
|
||||
func(api.resultStatus, 'running');
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -436,8 +488,21 @@ treeherder.factory('thJobFilters', [
|
|||
* is used to undo the call to ``showUnclassifiedFailures``.
|
||||
*/
|
||||
var resetNonFieldFilters = function() {
|
||||
filters.resultStatus.values = thResultStatusList.defaultFilters();
|
||||
filters.isClassified.values = [true, false];
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Revert the filters back to what they were before one of the
|
||||
* showXXX functions was called.
|
||||
*/
|
||||
var revertNonFieldFilters = function() {
|
||||
filters.resultStatus.values = stashedStatusFilterValues.resultStatus;
|
||||
filters.isClassified.values = stashedStatusFilterValues.isClassified;
|
||||
$rootScope.$broadcast(thEvents.globalFilterChanged);
|
||||
|
||||
};
|
||||
|
||||
var toggleSkipExclusionProfiles = function() {
|
||||
|
@ -457,9 +522,11 @@ treeherder.factory('thJobFilters', [
|
|||
filters: filters,
|
||||
pinAllShownJobs: pinAllShownJobs,
|
||||
showUnclassifiedFailures: showUnclassifiedFailures,
|
||||
showCoalesced: showCoalesced,
|
||||
toggleInProgress: toggleInProgress,
|
||||
isUnclassifiedFailures: isUnclassifiedFailures,
|
||||
resetNonFieldFilters: resetNonFieldFilters,
|
||||
revertNonFieldFilters: revertNonFieldFilters,
|
||||
toggleSkipExclusionProfiles: toggleSkipExclusionProfiles,
|
||||
isSkippingExclusionProfiles: isSkippingExclusionProfiles,
|
||||
excludedJobs: excludedJobs,
|
||||
|
|
|
@ -9,10 +9,8 @@
|
|||
data-id="{{resultset.id}}">
|
||||
|
||||
<div class="result-set-title row">
|
||||
<span class="col-xs-5">
|
||||
<a class="btn btn-default btn-sm" ng-hide="true"><i class=" glyphicon glyphicon-pushpin"></i></a>
|
||||
<span class="col-xs-4 result-set-title-left">
|
||||
<span class="btn btn-default btn-sm glyphicon glyphicon-download" ng-show="isLoadingJobs"></span>
|
||||
<th-action-button ng-hide="isLoadingJobs"></th-action-button>
|
||||
<span class="timestamp-name">
|
||||
<span>
|
||||
<a href="{{revisionResultsetFilterUrl}}"
|
||||
|
@ -21,18 +19,25 @@
|
|||
<th-author author="{{resultset.author}}"></th-author>
|
||||
</span>
|
||||
</span>
|
||||
<span class="col-xs-3 revision-link">
|
||||
<span class="btn btn-default btn-xs"
|
||||
<span class="col-xs-4 result-set-buttons">
|
||||
<span class="revision-text">{{resultset.revision}}</span>
|
||||
<span class="btn btn-default btn-sm"
|
||||
title="copy revision link to clipboard"
|
||||
clip-copy="revisionResultsetFilterUrl"
|
||||
clip-click="revisionUrlCopied(resultset.revision)">
|
||||
<i class="glyphicon glyphicon-link"></i></span>
|
||||
{{resultset.revision}}
|
||||
<span class="btn btn-default btn-sm"
|
||||
title="pin all visible jobs in this resultset"
|
||||
ng-click="pinAllShownJobs()">
|
||||
<span class="glyphicon glyphicon-pushpin"></span>
|
||||
</span>
|
||||
<th-action-button ng-hide="isLoadingJobs"></th-action-button>
|
||||
</span>
|
||||
|
||||
<span class="col-xs-1 btn btn-default btn-sm revision-button"
|
||||
ng-click="toggleRevisions()"
|
||||
title="show revisions"><i class="fa fa-code-fork fa-lg"></i> {{resultset.revision_count}}</span>
|
||||
<th-result-counts class="col-xs-4"/>
|
||||
<th-result-counts class="col-xs-4 result-counts"/>
|
||||
</div>
|
||||
|
||||
<div th-clone-jobs ></div>
|
||||
|
|
|
@ -5,7 +5,13 @@
|
|||
<span class="pull-right">
|
||||
<span class="btn btn-default btn-xs"
|
||||
title="pin all jobs that pass the global filters"
|
||||
ng-click="pinAllShownJobs()"><i class="glyphicon glyphicon-pushpin"></i> pin all showing</span>
|
||||
ng-click="thJobFilters.pinAllShownJobs()"><i class="glyphicon glyphicon-pushpin"></i> pin all showing</span>
|
||||
<span class="btn btn-default btn-xs"
|
||||
title="show only coalesced jobs"
|
||||
ng-click="thJobFilters.showCoalesced()">coalesced only</span>
|
||||
<span class="btn btn-default btn-xs"
|
||||
title="reset to default status filters"
|
||||
ng-click="thJobFilters.resetNonFieldFilters()">reset</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
ng-class="{'btn-lg selected-job': (selectedJob==job), 'btn-xs': (selectedJob!=job)}"
|
||||
title="{{ hoverText }}"
|
||||
ng-click="viewJob(job)"
|
||||
ng-hide="job.job_coalesced_to_guid"
|
||||
ng-right-click="viewLog(job.resource_uri)"
|
||||
data-job-id="{{ job.job_id }}">
|
||||
{{ job.job_type_symbol }}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<span class="btn btn-default btn-sm result-status-total-count"
|
||||
ng-click="toggleJobs()"
|
||||
title="total job count - toggle jobs"><i class="fa fa-th-list fa-lg"></i> {{resultset.job_counts.total - totalExcluded()}}</span>
|
||||
title="total job count - toggle jobs"><i class="fa fa-list fa-lg"></i> {{resultset.job_counts.total - totalExcluded()}}</span>
|
||||
<span class="result-status-count-group">
|
||||
<th-result-status-count ng-repeat="resultStatus in statusList"/>
|
||||
</span>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
ng-click="toggleAllRevisions()"><i class="fa fa-code-fork fa-lg"></i></span>
|
||||
<span class="btn btn-view-nav btn-sm"
|
||||
title="collapse/expand all jobs"
|
||||
ng-click="toggleAllJobs()"><i class="fa fa-th-list fa-lg"></i></span>
|
||||
ng-click="toggleAllJobs()"><i class="fa fa-list fa-lg"></i></span>
|
||||
<div ng-controller="SearchCtrl" class="form-group form-inline">
|
||||
<input id="platform-job-text-search-field"
|
||||
ng-model="searchQuery" ng-keyup="search($event)" type="text"
|
||||
|
|
|
@ -4,12 +4,12 @@ treeherder.controller('PluginCtrl', [
|
|||
'$scope', '$rootScope', 'thUrl', 'ThJobClassificationModel',
|
||||
'thClassificationTypes', 'ThJobModel', 'thEvents', 'dateFilter',
|
||||
'numberFilter', 'ThBugJobMapModel', 'thResultStatus', 'thSocket',
|
||||
'ThResultSetModel', 'ThLog', '$q', 'thPinboard',
|
||||
'ThResultSetModel', 'ThLog', '$q', 'thPinboard', 'ThJobArtifactModel',
|
||||
function PluginCtrl(
|
||||
$scope, $rootScope, thUrl, ThJobClassificationModel,
|
||||
thClassificationTypes, ThJobModel, thEvents, dateFilter,
|
||||
numberFilter, ThBugJobMapModel, thResultStatus, thSocket,
|
||||
ThResultSetModel, ThLog, $q, thPinboard) {
|
||||
ThResultSetModel, ThLog, $q, thPinboard, ThJobArtifactModel) {
|
||||
|
||||
var $log = new ThLog("PluginCtrl");
|
||||
|
||||
|
@ -24,7 +24,7 @@ treeherder.controller('PluginCtrl', [
|
|||
$scope.job = newValue;
|
||||
|
||||
if(timeout_promise !== null){
|
||||
console.log("timing out previous job request");
|
||||
$log.debug("timing out previous job request");
|
||||
timeout_promise.resolve();
|
||||
}
|
||||
timeout_promise = $q.defer();
|
||||
|
@ -40,7 +40,16 @@ treeherder.controller('PluginCtrl', [
|
|||
$scope.logs = data.logs;
|
||||
});
|
||||
|
||||
$scope.artifacts = {};
|
||||
ThJobArtifactModel.get_list({
|
||||
name: "buildapi",
|
||||
"type": "json",
|
||||
job_id: $scope.job.id
|
||||
}, {timeout: timeout_promise})
|
||||
.then(function(data) {
|
||||
if (data.length === 1 && _.has(data[0], 'blob')){
|
||||
$scope.job.build_id = data[0].blob.id;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.visibleFields = {
|
||||
"Job Name": $scope.job.job_type_name,
|
||||
|
|
|
@ -8,8 +8,26 @@
|
|||
|
||||
</ul>
|
||||
<ul class="nav navbar-nav pull-right">
|
||||
<li ng-show="job.build_id">
|
||||
<a title="Cancel job"
|
||||
href=""
|
||||
target="_blank"
|
||||
ng-click="cancelJob()">
|
||||
<span class="fa fa-stop"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li ng-show="job.build_id">
|
||||
<a title="Retrigger job"
|
||||
href=""
|
||||
target="_blank"
|
||||
ng-click="retriggerJob()">
|
||||
<span class="fa fa-play"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li ng-show="isReftest()">
|
||||
<a title="Launch the Reftest Analyser in a new page" target="_blank" href="https://hg.mozilla.org/mozilla-central/raw-file/tip/layout/tools/reftest/reftest-analyzer.xhtml">
|
||||
<a title="Launch the Reftest Analyser in a new page"
|
||||
target="_blank"
|
||||
href="https://hg.mozilla.org/mozilla-central/raw-file/tip/layout/tools/reftest/reftest-analyzer.xhtml">
|
||||
<span class="fa fa-bar-chart-o"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -38,10 +56,10 @@
|
|||
<li>
|
||||
<a href="" ng-click="togglePinboardVisibility()">
|
||||
<span ng-hide="isPinboardVisible"
|
||||
title="show pinboard"
|
||||
title="Show the pinboard"
|
||||
class="glyphicon glyphicon-chevron-down"></span>
|
||||
<span ng-show="isPinboardVisible"
|
||||
title="hide pinboard"
|
||||
title="Hide the pinboard"
|
||||
class="glyphicon glyphicon-chevron-up"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
|
Загрузка…
Ссылка в новой задаче