change the layout of the bottom panel

This commit is contained in:
mdoglio 2013-12-03 22:36:06 +01:00
Родитель a0d4386031
Коммит 1f19d91fdf
15 изменённых файлов: 293 добавлений и 213 удалений

Просмотреть файл

@ -124,13 +124,43 @@ body {
}
.job-btn {
margin: 0 -4px 0 0;
margin: 0 -3px 0 0;
padding: 0 2px 0 2px;
}
.th-notes-accordion .accordion-toggle {
padding: 0;
}
div.navbar-fixed-bottom{
border-top: 1px solid #ccc;
padding:5px;
}
.table-super-condensed thead > tr > th,
.table-super-condensed tbody > tr > th,
.table-super-condensed tfoot > tr > th,
.table-super-condensed thead > tr > td,
.table-super-condensed tbody > tr > td,
.table-super-condensed tfoot > tr > td {
padding: 2px;
font-size: .9em;
}
div.navbar-fixed-bottom .panel{
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.1), 0px 0px 2px 0px rgba(0, 0, 0, 0.8) inset
}
div.navbar-fixed-bottom dt,
div.navbar-fixed-bottom dt {
font-size:.8em;
}
div.navbar-fixed-bottom .close-btn{
position:absolute;
top:-15px;
right:5px;
z-index:10;
}
/* Custom Job buttons*/
.btn-orange {

Просмотреть файл

@ -63,16 +63,13 @@
</div>
<!-- Footer -->
<div class="nav navbar navbar-default navbar-fixed-bottom"
ng-show="selectedJob">
<div class="container">
<button type="button"
class="close pull-right"
aria-hidden="true"
ng-click="clearJob()">&times;</button>
<div class="nav navbar navbar-default navbar-fixed-bottom" ng-show="selectedJob">
<button type="button" class="btn btn-xs close-btn btn-danger pull-right" ng-click="clearJob()">
<span class="glyphicon glyphicon-remove"></span>
</button>
<div ng-include src="'plugins/pluginpanel.html'"></div>
<div ng-include src="'plugins/pluginpanel.html'"></div>
</div>
</div>
<script src="vendor/angular/angular.js"></script>
@ -93,8 +90,9 @@
<script src="js/controllers/machines.js"></script>
<script src="js/controllers/timeline.js"></script>
<script src="plugins/controller.js"></script>
<script src="plugins/jobdetail/controller.js"></script>
<script src="plugins/jobfoo/controller.js"></script>
<script src="plugins/tinderbox/controller.js"></script>
<script src="plugins/tinderbox/directives.js"></script>
<script src="plugins/bugs/controller.js"></script>
<script src="js/filters.js"></script>
<script src="https://tbpl.mozilla.org/js/Config.js"></script>
</body>

Просмотреть файл

@ -82,7 +82,6 @@ treeherder.directive('thStar', function ($parse, thStarTypes) {
});
treeherder.directive('thShowJobs', function ($parse, thResultStatusInfo) {
return {
link: function(scope, element, attrs) {
scope.$watch('resultSeverity', function(newVal) {

Просмотреть файл

@ -100,3 +100,24 @@ treeherder.factory('thRepos',
}
};
}]);
treeherder.factory('thJobNote', function($resource, $http, thUrl) {
var JobNote = $resource(thUrl.getProjectUrl("/note/"));
// Workaround to the fact that $resource strips trailing slashes
// out of urls. This causes a 301 redirect on POST because it does a
// preflight OPTIONS call. Tastypie gives up on the POST after this
// and nothing happens. So this alternative "thSave" command avoids
// that by using the trailing slash directly in a POST call.
// @@@ This may be fixed in later versions of Angular. Or perhaps there's
// a better way?
JobNote.prototype.thSave = function() {
$http.post(thUrl.getProjectUrl("/note/"), {
job_id: this.job_id,
note: this.note,
who: this.who,
failure_classification_id: this.failure_classification_id
});
};
return JobNote;
});

Просмотреть файл

@ -0,0 +1,19 @@
"use strict";
treeherder.controller('BugsPluginCtrl',
function BugsPluginCtrl($scope, $rootScope, $log) {
$log.log("bugs plugin initialized");
$scope.$watch('jobArtifacts', function(newValue, oldValue){
$scope.open_bugs = []
$scope.closed_bugs = []
$log.log(newValue)
if (newValue && newValue.hasOwnProperty('Open bugs')){
$scope.open_bugs = newValue['Open bugs'].blob;
}
if (newValue && newValue.hasOwnProperty('Closed bugs')){
$scope.closed_bugs = newValue['Closed bugs'].blob;
}
});
}
);

16
ui/plugins/bugs/main.html Normal file
Просмотреть файл

@ -0,0 +1,16 @@
<div ng-controller="BugsPluginCtrl">
open bugs:
<ul >
<li ng-repeat="bug in open_bugs">
{{bug}}
</li>
</ul>
closed bugs:
<ul >
<li ng-repeat="bug in closed_bugs">
{{bug}}
</li>
</ul>
</div>

Просмотреть файл

@ -1,19 +1,107 @@
"use strict";
treeherder.controller('PluginCtrl',
function PluginCtrl($scope, $rootScope) {
function PluginCtrl($scope, $rootScope, $resource, $http,
thServiceDomain, thUrl, thJobNote, thStarTypes, $log) {
$scope.$watch('selectedJob', function(newValue, oldValue) {
// preferred way to get access to the selected job
if (newValue) {
$scope.job = newValue;
$scope.artifacts = {}
var undef = "---undefined---";
// fields that will show in the job detail panel
$scope.visibleFields = {
"Result": $scope.job.result || undef,
"Job GUID": $scope.job.job_guid || undef,
"Machine Platform Arch": $scope.job.machine_platform_architecture || undef,
"Machine Platform OS": $scope.job.machine_platform_os || undef,
"Build Platform": $scope.job.build_platform || undef,
"Build Arch": $scope.job.build_architecture || undef,
"Build OS": $scope.job.build_os || undef
};
/*this call retrieves (again) a job detail. can we avoid it?*/
$http.get(thServiceDomain + $scope.job.resource_uri).
success(function(data) {
$scope.logs = data.logs;
data.artifacts.forEach(function(artifact) {
if (artifact.name != "Structured Log") {
// we don't return the blobs with job, just
// resource_uris to them. For the Job Artifact,
// we want that blob, so we need to fetch the
// detail to get the blob which has the
// tinderbox_printlines, etc.
$scope.artifacts[artifact.name] =$resource(
thServiceDomain + artifact.resource_uri).get();
} else {
// for the structured log, we don't need the blob
// here, we have everything we need in the artifact
// as is, so just save it.
/*are we using this artifact here?*/
$scope.lvArtifact=artifact;
$scope.lvUrl = thUrl.getLogViewerUrl(artifact.id);
}
});
});
$scope.updateNotes();
}
}, true);
$scope.starTypes = thStarTypes;
var JobNote = thJobNote;
// load the list of existing notes (including possibly a new one just
// added).
$scope.updateNotes = function() {
$scope.notes = JobNote.query({job_id: $scope.job.job_id});
};
// when notes comes in, then set the latest note for the job
$scope.$watch('notes', function(newValue, oldValue) {
if (newValue && newValue.length > 0) {
$scope.job.note=newValue[0];
}
});
// open form to create a new note
$scope.addNote = function() {
var fci = 0;
if ($scope.notes && $scope.notes.length > 0) {
fci = $scope.notes[0].failure_classification_id;
}
$scope.newNote = new JobNote({
job_id: $scope.job.job_id,
note: "",
who: $scope.username,
failure_classification_id: fci
});
$scope.focusInput=true;
};
// done adding a new note, so clear and hide the form
$scope.clearNewNote = function() {
$scope.newNote = null;
};
// save the note and hide the form
$scope.saveNote = function() {
$scope.newNote.thSave();
$scope.updateNotes();
$scope.clearNewNote();
};
$scope.tabs = [
{
title: "Jobs Detail",
content: "plugins/jobdetail/main.html",
active: true
title: "Tinderbox",
content: "plugins/tinderbox/main.html"
},
{
title: "Jobs Foo",
content: "plugins/jobfoo/main.html"
title: "Bug suggestions",
content: "plugins/bugs/main.html"
}
];
}
);
);

Просмотреть файл

@ -1,112 +0,0 @@
"use strict";
treeherder.controller('JobDetailPluginCtrl',
function JobDetailPluginCtrl($scope, $resource, $http,
thServiceDomain, thUrl, thJobNote, thStarTypes) {
$scope.$watch('selectedJob', function(newValue, oldValue) {
// preferred way to get access to the selected job
if (newValue) {
$scope.job = newValue;
var undef = "---undefined---";
// fields that will show in the job detail panel
$scope.visibleFields = {
"Result": $scope.job.result || undef,
"Job GUID": $scope.job.job_guid || undef,
"Machine Platform Arch": $scope.job.machine_platform_architecture || undef,
"Machine Platform OS": $scope.job.machine_platform_os || undef,
"Build Platform": $scope.job.build_platform || undef,
"Build Arch": $scope.job.build_architecture || undef,
"Build OS": $scope.job.build_os || undef
};
$http.get(thServiceDomain + $scope.job.resource_uri).
success(function(data) {
$scope.logs = data.logs;
data.artifacts.forEach(function(artifact) {
if (artifact.name.indexOf("Job Artifact") !== -1) {
// we don't return the blobs with job, just
// resource_uris to them. For the Job Artifact,
// we want that blob, so we need to fetch the
// detail to get the blob which has the
// tinderbox_printlines, etc.
$scope.jobArtifact = $resource(
thServiceDomain + artifact.resource_uri).get();
} else if (artifact.name === "Structured Log") {
// for the structured log, we don't need the blob
// here, we have everything we need in the artifact
// as is, so just save it.
$scope.lvArtifact=artifact;
$scope.lvUrl = thUrl.getLogViewerUrl(artifact.id);
}
});
});
$scope.updateNotes();
}
}, true);
$scope.starTypes = thStarTypes;
var JobNote = thJobNote;
// load the list of existing notes (including possibly a new one just
// added).
$scope.updateNotes = function() {
$scope.notes = JobNote.query({job_id: $scope.job.job_id});
};
// when notes comes in, then set the latest note for the job
$scope.$watch('notes', function(newValue, oldValue) {
if (newValue && newValue.length > 0) {
$scope.job.note=newValue[0];
}
});
// open form to create a new note
$scope.addNote = function() {
var fci = 0;
if ($scope.notes && $scope.notes.length > 0) {
fci = $scope.notes[0].failure_classification_id;
}
$scope.newNote = new JobNote({
job_id: $scope.job.job_id,
note: "",
who: $scope.username,
failure_classification_id: fci
});
$scope.focusInput=true;
};
// done adding a new note, so clear and hide the form
$scope.clearNewNote = function() {
$scope.newNote = null;
};
// save the note and hide the form
$scope.saveNote = function() {
$scope.newNote.thSave();
$scope.updateNotes();
$scope.clearNewNote();
};
}
);
treeherder.factory('thJobNote', function($resource, $http, thUrl) {
var JobNote = $resource(thUrl.getProjectUrl("/note/"));
// Workaround to the fact that $resource strips trailing slashes
// out of urls. This causes a 301 redirect on POST because it does a
// preflight OPTIONS call. Tastypie gives up on the POST after this
// and nothing happens. So this alternative "thSave" command avoids
// that by using the trailing slash directly in a POST call.
// @@@ This may be fixed in later versions of Angular. Or perhaps there's
// a better way?
JobNote.prototype.thSave = function() {
$http.post(thUrl.getProjectUrl("/note/"), {
job_id: this.job_id,
note: this.note,
who: this.who,
failure_classification_id: this.failure_classification_id
});
};
return JobNote;
});

Просмотреть файл

@ -1,60 +0,0 @@
<div ng-controller="JobDetailPluginCtrl">
<div class="span12">
<div class="span7">
<button class="btn btn-default btn-xs"
title="add note"
ng-click="addNote()">
<i class="glyphicon glyphicon-comment"></i>
</button>
<div class="btn-group">
<button class="btn btn-default btn-xs disabled">Log:</button>
<div class="btn btn-default btn-xs"
ng-disabled="!lvArtifact">
<a target="_blank" href="{{ lvUrl }}">Structured</a>
</div>
<div class="btn btn-default btn-xs"
ng-repeat="joblog in logs">
<a target="_blank" href="{{ joblog.url }}">Raw</a>
</div>
</div>
<dl class="dl-horizontal">
<dt class="label label-info">Machine name</dt>
<dd><a href="https://secure.pub.build.mozilla.org/builddata/reports/slave_health/slave.html?name={{ $scope.job.machine_name }}">{{ job.machine_name }}</a></dd>
<span ng-repeat="(label, value) in visibleFields">
<dt class="label label-info" ng-bind="label"> </dt>
<dd ng-bind-html="value" target="_blank"> </dd>
</span>
</dl>
</div>
<ul class="span7" >
<li ng-repeat="line in jobArtifact.blob.tinderbox_printlines">
<div ng-bind-html="line"></div>
</li>
</ul>
</div>
<div class="span12">
<dl class="dl-horizontal">
<dt>
<i class="glyphicon glyphicon-plus" ng-click="addNote()" title="add note"></i>
<span class="label label-info">Notes</span>
</dt>
<dd class="th-notes-accordion">
<div ng-hide="notes.length==0">
<span th-star star-id="notes[0].failure_classification_id"></span> {{job.note.failure_classification_id}}{{ notes[0].note_timestamp*1000|date:'medium' }} <span class="label label-info" ng-bind="notes[0].who"></span> said <em>"<span ng-bind="notes[0].note"></span>"</em>
</div>
<span ng-show="notes.length==0">No notes</span>
</dd>
</dl>
<div ng-show="newNote">
<form ng-submit="saveNote()" class="form-inline">
<select ng-model="newNote.failure_classification_id">
<option ng-repeat="(value, star) in starTypes" value="{{value}}">{{star.name}}</option>
</select>
<input ng-model="newNote.note" focus-me="focusInput"/>
<input class="btn btn-primary" type="submit" value="save">
<a class="btn btn-default" ng-click="clearNewNote()">cancel</a>
</form>
</div>
</div>
</div>

Просмотреть файл

@ -1,13 +0,0 @@
"use strict";
treeherder.controller('JobFooPluginCtrl',
function JobFooPluginCtrl($scope) {
$scope.$watch('selectedJob', function(newValue, oldValue) {
// preferred way to get access to the selected job
if (newValue) {
$scope.job = newValue;
}
}, true);
}
);

Просмотреть файл

@ -1,3 +0,0 @@
<div ng-controller="JobFooPluginCtrl">
<p>I pitty the foo that don't like job_guid: {{ job.job_guid }}</p>
</div>

Просмотреть файл

@ -1,7 +1,69 @@
<div ng-controller="PluginCtrl">
<tabset class="tabs-below">
<tab ng-repeat="tab in tabs" heading="{{ tab.title }}" active="tab.active" disabled="tab.disabled">
<ng-include src="tab.content"></ng-include>
</tab>
</tabset>
<!--first panel begin-->
<div class="row">
<div class="col-sm-12 col-lg-5">
<div class="panel">
<div class="panel-body">
<button class="btn btn-default btn-xs"
title="add note"
ng-click="addNote()">
<i class="glyphicon glyphicon-comment"></i>
</button>
<div class="btn-group">
<button class="btn btn-default btn-xs disabled">Log:</button>
<div class="btn btn-default btn-xs"
ng-disabled="!lvArtifact">
<a target="_blank" href="{{ lvUrl }}">Structured</a>
</div>
<div class="btn btn-default btn-xs"
ng-repeat="joblog in logs">
<a target="_blank" href="{{ joblog.url }}">Raw</a>
</div>
</div>
<dl class="dl-horizontal">
<dt>Machine name</dt>
<dd><a href="https://secure.pub.build.mozilla.org/builddata/reports/slave_health/slave.html?name={{ $scope.job.machine_name }}">{{ job.machine_name }}</a></dd>
<span ng-repeat="(label, value) in visibleFields">
<dt>{{ label }}</dt>
<dd>{{ value }}</dd>
</span>
</dl>
<dl class="dl-horizontal">
<dt>
<i class="glyphicon glyphicon-plus" ng-click="addNote()" title="add note"></i>
<span class="label label-info">Notes</span>
</dt>
<dd class="th-notes-accordion">
<div ng-hide="notes.length==0">
<span th-star star-id="notes[0].failure_classification_id"></span> {{job.note.failure_classification_id}}{{ notes[0].note_timestamp*1000|date:'medium' }} <span class="label label-info" ng-bind="notes[0].who"></span> said <em>"<span ng-bind="notes[0].note"></span>"</em>
</div>
<span ng-show="notes.length==0">No notes</span>
</dd>
</dl>
<div ng-show="newNote">
<form ng-submit="saveNote()" class="form-inline">
<select ng-model="newNote.failure_classification_id">
<option ng-repeat="(value, star) in starTypes" value="{{value}}">{{star.name}}</option>
</select>
<input ng-model="newNote.note" focus-me="focusInput"/>
<input class="btn btn-primary" type="submit" value="save">
<a class="btn btn-default" ng-click="clearNewNote()">cancel</a>
</form>
</div>
</div>
</div>
</div>
<!--first panel end-->
<div class="col-sm-12 col-lg-7">
<div class="panel">
<div class="panel-body">
<tabset class="tabs-below">
<tab ng-repeat="tab in tabs" heading="{{ tab.title }}" active="tab.active" disabled="tab.disabled">
<ng-include src="tab.content"></ng-include>
</tab>
</tabset>
</div>
</div>
</div>
</div>
</div>

Просмотреть файл

@ -0,0 +1,15 @@
"use strict";
treeherder.controller('TinderboxPluginCtrl',
function TinderboxPluginCtrl($scope, $rootScope, $log) {
$log.log("Tinderbox plugin initialized");
$scope.$watch('artifacts', function(newValue, oldValue){
$scope.tinderbox_lines = []
$log.log(newValue)
if (newValue && newValue.hasOwnProperty('Job Info')){
$scope.tinderbox_lines = newValue['Job Info'].blob.tinderbox_printlines;
}
});
}
);

Просмотреть файл

@ -0,0 +1,12 @@
"use strict";
treeherder.directive('thPrintLine', function() {
console.log("thPrintline initialized")
return {
restrict: 'E',
scope: {
line: '=line'
},
template: '<span>{{line}}</span>'
};
});

Просмотреть файл

@ -0,0 +1,8 @@
<div ng-controller="TinderboxPluginCtrl">
<ul >
<li ng-repeat="line in tinderbox_lines">
{{line}}
</li>
</ul>
</div>