diff options
Diffstat (limited to 'src/main/resources/webapp/apps')
20 files changed, 1007 insertions, 0 deletions
diff --git a/src/main/resources/webapp/apps/app.css b/src/main/resources/webapp/apps/app.css new file mode 100755 index 0000000..3088282 --- /dev/null +++ b/src/main/resources/webapp/apps/app.css @@ -0,0 +1,58 @@ +/* + * Badges + */ +/* + bronze = #8c7853 + bronze ii = #a67d3d + */ + +.badge-level-1 { background-color: #a67d3d; color: #000000 } +.badge-level-2 { background-color: silver; color: #000000 } +.badge-level-3 { background-color: #ffd700; color: #000000 } + +/* + * Avatar + */ + +/* This has to match the Gravatar image */ +.avatar80 { + width: 80px; + height: 80px; +} + +/* + * + */ + +#content { + background-color: #ffffff; + padding-bottom: 60px; +} + +#footer { + background-color: #f5f5f5; + border-top: 1px solid #ccc; + color: #000000; +} + +#footer .container { + padding: 60px 0; +} + +#footer abbr[title] { + border-bottom: 1px dotted #000; +} + +#footer p { + margin-bottom: 0; + color: #777; +} + +#footer-links { + margin: 10px 0; +} + +#footer-links li { + display: inline; + margin-right: 10px; +} diff --git a/src/main/resources/webapp/apps/app.js b/src/main/resources/webapp/apps/app.js new file mode 100755 index 0000000..068f454 --- /dev/null +++ b/src/main/resources/webapp/apps/app.js @@ -0,0 +1,97 @@ +var directives = angular.module('core.directives', []); + +directives.filter('countBadgeByLevel', function () { + return function (badges) { + // 5 levels + var levels = [0, 0, 0, 0, 0]; + angular.forEach(badges, function (value, key) { + levels[value.level - 1]++; + }); + return levels; + } +}); + +directives.filter('isodate', function () { + return function (date) { + return date.toISOString(); + } +}); + +directives.filter('gz', function () { + return function (num) { + if (angular.isArray(num)) { + var out = []; + angular.forEach(num, function (x) { + if (x > 0) { + out.push(x); + } + }); + + return out; + } + else if (angular.isNumber(num)) { + return num > 0; + } + console.log("fail"); + return undefined; + } +}); + +directives.directive('navbar', function () { + return { + restrict: 'E', + templateUrl: '/apps/core/navbar.html?noCache=' + noCache + }; +}); + +directives.directive('badge', function () { + return { + restrict: 'E', + scope: { + badgeDetail: '=badgeDetail' + }, + template: '<span class="badge-inverse badge-level-{{badgeDetail.badge.level}} badge">' + + ' <strong style="padding-right: 0.3em">{{badgeDetail.badge.name}}</strong>' + + ' <i class="icon-user"></i>' + + '</span>' + + ' awarded to ' + + '<a href="/#/person/{{badgeDetail.person.uuid}}">{{badgeDetail.person.name}}</a>. ' + + '<a href="/#/badge/{{badgeDetail.badge.uuid}}">More</a>' + } +}); + +directives.directive('badgeSpan', function () { + var template = + '<span class="badge-inverse badge-level-{{badge.level}} badge">' + + ' <strong style="padding-right: 0.3em">{{badge.name}}</strong>' + + ' <i class="icon-user"></i>' + + '</span>'; + + return { + restrict: 'E', + scope: { + badge: '=badge' + }, + template: template + } +}); + +directives.directive('personLink', function () { + return { + restrict: 'E', + scope: { + person: '=person' + }, + template: '<a href="/#/person/{{person.uuid}}">{{person.name}}</a>' + } +}); + +directives.directive('personAvatar', function () { + return { + restrict: 'E', + scope: { + person: '=person' + }, + template: '<img ng-src="{{person.gravatar}}?default=identicon" class="avatar-image avatar80" title="{{person.name}}"/>' + } +}); diff --git a/src/main/resources/webapp/apps/buildApp/build.html b/src/main/resources/webapp/apps/buildApp/build.html new file mode 100755 index 0000000..fec38d2 --- /dev/null +++ b/src/main/resources/webapp/apps/buildApp/build.html @@ -0,0 +1,30 @@ +<div class="container"> + + <div class="page-header"> + <h1>Build</h1> + </div> + + <div> + <h3>Participants</h3> + <table> + <tr> + <th>Date</th> + <td>{{build.build.timestamp | date:'medium'}}</td> + </tr> + <tr> + <th>Status</th> + <td> + <span ng-show="build.build.success">SUCCESS</span> + <span ng-hide="build.build.success">FAILURE</span> + </td> + </tr> + </table> + <h3>Participants</h3> + + <p ng-repeat="participant in build.participants"> + <span>{{participant.name}}</span> + </p> + + </div> + +</div> diff --git a/src/main/resources/webapp/apps/buildApp/buildApp.js b/src/main/resources/webapp/apps/buildApp/buildApp.js new file mode 100755 index 0000000..170af16 --- /dev/null +++ b/src/main/resources/webapp/apps/buildApp/buildApp.js @@ -0,0 +1,12 @@ +'use strict'; + +var buildApp = angular.module('buildApp', ['build', 'buildParticipant']).config(function ($routeProvider) { + $routeProvider. + when('/', {controller: BuildCtrl, templateUrl: '/apps/buildApp/build.html?noCache=' + noCache}); +}); + +function BuildCtrl($scope, Build, BuildParticipant) { + Build.get({uuid: uuid}, function(build) { + $scope.build = build; + }); +} diff --git a/src/main/resources/webapp/apps/core/CoreResources.js b/src/main/resources/webapp/apps/core/CoreResources.js new file mode 100644 index 0000000..b258c85 --- /dev/null +++ b/src/main/resources/webapp/apps/core/CoreResources.js @@ -0,0 +1,25 @@ +'use strict'; + +function Person($resource) { + return $resource('/resource/core/person/:uuid', {uuid: '@uuid'}); +} + +angular.module('person', ['ngResource']).factory('Person', Person); + +function Build($resource) { + return $resource('/resource/core/build/:uuid', {uuid: '@uuid'}); +} + +angular.module('build', ['ngResource']).factory('Build', Build); + +function BuildParticipant($resource) { + return $resource('/resource/core/build-participant/:uuid', {uuid: '@uuid'}); +} + +angular.module('buildParticipant', ['ngResource']).factory('BuildParticipant', BuildParticipant); + +function Badge($resource) { + return $resource('/resource/core/badge/:uuid', {uuid: '@uuid'}); +} + +angular.module('badge', ['ngResource']).factory('Badge', Badge); diff --git a/src/main/resources/webapp/apps/core/PagingTableService.js b/src/main/resources/webapp/apps/core/PagingTableService.js new file mode 100755 index 0000000..af593df --- /dev/null +++ b/src/main/resources/webapp/apps/core/PagingTableService.js @@ -0,0 +1,72 @@ +function PagingTableService() { + var create = function ($scope, fetchCallback, options) { + options = options || {}; + var watcher = options.watcher || function(){}; + var self = { + rows: [], + startIndex: options.startIndex || 0, + count: options.count || 10 + }; + + var update = function(){ + fetchCallback(self.startIndex, self.count, function(data) { + self.rows = data.rows; + watcher(); + }); + }; + + self.first = function () { + self.startIndex = 0; + update(); + }; + + self.next = function () { + self.startIndex += self.count; + update(); + }; + + self.prev = function () { + if (self.startIndex == 0) { + return; + } + self.startIndex -= self.count; + update(); + }; + + // Do an initial fetch + update(); + + return self; + }; + + var defaultCallback = function(Resource, args) { + args = args || {}; + return function(startIndex, count, cb) { + if(startIndex) { + args.startIndex = startIndex; + } + if(count) { + args.count = count; + } + console.log("fetching", args); + Resource.query(args, function(data, headers) { + var totalResults = headers("total-results"); + console.log("totalResults", totalResults); + console.log("got data", data); + cb({ + totalResults: totalResults, + rows: data + }); + }); + }; + }; + + return { + create: create, + defaultCallback: defaultCallback + } +} + +angular. + module('pagingTableService', ['ngResource']). + factory('PagingTableService', PagingTableService); diff --git a/src/main/resources/webapp/apps/core/navbar.html b/src/main/resources/webapp/apps/core/navbar.html new file mode 100755 index 0000000..914258e --- /dev/null +++ b/src/main/resources/webapp/apps/core/navbar.html @@ -0,0 +1,17 @@ +<div class="navbar"> + <div class="navbar-inner"> + <div class="container"> + <span class="brand"><a href="/">Wat</a></span> + <div class="nav-collapse collapse"> + <ul class="nav"> + <li class=""><a href="#/">Home</a></li> + <li class=""><a href="#/badge/">Badges</a></li> + <li class=""><a href="#/person/">People</a></li> + <li class=""><a href="#/build/">Builds</a></li> + <li class="divider-vertical"></li> + <li class=""><a href="/jenkins">Jenkins</a></li> + </ul> + </div> + </div> + </div> +</div> diff --git a/src/main/resources/webapp/apps/frontPageApp/badge.html b/src/main/resources/webapp/apps/frontPageApp/badge.html new file mode 100755 index 0000000..92fc7ae --- /dev/null +++ b/src/main/resources/webapp/apps/frontPageApp/badge.html @@ -0,0 +1,30 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>Badge</h1> + </div> + + <div class="row"> + <div class="span12"> + The badge <badge-span badge="badge.badge"></badge-span> was awarded to <person-link person="badge.person"></person-link> at + {{badge.badge.createdDate | date:'medium'}}. + </div> + </div> + + <div class="row" ng-switch="badge.badge.name"> + <div class="span12" ng-switch-when="UNBREAKABLE"> + <h2>Details</h2> + <p> + The badge was awarded for having {{badge.personalBadge.builds.length}} successful builds in a row: + </p> + <ul class="unstyled"> + <li ng-repeat="b in badge.personalBadge.builds"> + <a class="btn" href="/build/{{b}}">{{$index + 1}} <i class="icon-chevron-right"></i></a> + </li> + </ul> + </div> + </div> + +</div> diff --git a/src/main/resources/webapp/apps/frontPageApp/badgeList.html b/src/main/resources/webapp/apps/frontPageApp/badgeList.html new file mode 100755 index 0000000..7671a55 --- /dev/null +++ b/src/main/resources/webapp/apps/frontPageApp/badgeList.html @@ -0,0 +1,46 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>Badges Awarded</h1> + </div> + + <style> + .awarded-badge { + text-align: center; + margin-bottom: 1em; + margin-right: 1em; + } + + .avatar-image { + margin-bottom: 1em; + } + </style> + + <div class="row"> + <div class="span12"> + <div class="row" ng-repeat="(date, group) in badgeGroups"> + <div class="span12"> + <h2>{{date | date:'mediumDate'}}</h2> + </div> + <div class="span12"> + <div class="awarded-badge pull-left" ng-repeat="badge in group"> + <div><person-avatar person="badge.person"></person-avatar></div> + + <badge-span badge="badge.badge" ></badge-span> <br/> + <!--was awarded to<br/>--> + </div> + </div> + </div> + <ul class="pager"> + <li class="previous" ng-show="persons.startIndex > 0"> + <a ng-click="persons.prev()">← Prev</a> + </li> + <li class="next"> + <a ng-click="persons.next()">Next →</a> + </li> + </ul> + </div> + </div> +</div> diff --git a/src/main/resources/webapp/apps/frontPageApp/buildList.html b/src/main/resources/webapp/apps/frontPageApp/buildList.html new file mode 100755 index 0000000..13a1dc3 --- /dev/null +++ b/src/main/resources/webapp/apps/frontPageApp/buildList.html @@ -0,0 +1,50 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>Builds</h1> + </div> + + <style> + .avatar-image { + /* This has to match bootstrap's row margin. */ + margin-left: 30px; + padding-right: 1em; + float: left; + margin-top: 0; + } + </style> + + <div class="row"> + <div class="span12"> + <table class="table"> + <tbody ng-repeat="build in builds.rows"> + <tr class="{{{true: 'success', false: 'error'}[build.build.success]}}"> + <td>{{build.build.timestamp | date:'medium'}}</td> + <td> + <span ng-show="build.build.success">SUCCESS</span> + <span ng-hide="build.build.success">FAILURE</span> + </td> + <td><a class="btn" href="/build/{{build.build.uuid}}"><i class="icon-chevron-right"></i></a></td> + </tr> + <tr> + <td colspan="3"> + <span ng-repeat="p in build.participants"> + <person-avatar person="p"/> + </span> + </td> + </tr> + </tbody> + </table> + <ul class="pager"> + <li class="previous" ng-show="builds.startIndex > 0"> + <a ng-click="builds.prev()">← Prev</a> + </li> + <li class="next"> + <a ng-click="builds.next()">Next →</a> + </li> + </ul> + </div> + </div> +</div> diff --git a/src/main/resources/webapp/apps/frontPageApp/frontPage.html b/src/main/resources/webapp/apps/frontPageApp/frontPage.html new file mode 100755 index 0000000..c3db55c --- /dev/null +++ b/src/main/resources/webapp/apps/frontPageApp/frontPage.html @@ -0,0 +1,31 @@ +<div class="container"> + <navbar/> + + <div class="page-header"> + <h1>Recent</h1> + </div> + + <div class="row"> + <div class="span6"> + <h3>Badges</h3> + + <div> + <ul class="unstyled"> + <li ng-repeat="b in recentBadges"> + <badge badge-detail="b"/> + </li> + </ul> + </div> + </div> + + <div class="span6"> + <h3>Newcomers</h3> + + <ul class="unstyled"> + <li ng-repeat="person in persons"> + <a href="#/person/{{person.person.uuid}}">{{person.person.name}}</a> + </li> + </ul> + </div> + </div> +</div> diff --git a/src/main/resources/webapp/apps/frontPageApp/frontPageApp.js b/src/main/resources/webapp/apps/frontPageApp/frontPageApp.js new file mode 100755 index 0000000..6f80d0f --- /dev/null +++ b/src/main/resources/webapp/apps/frontPageApp/frontPageApp.js @@ -0,0 +1,110 @@ +'use strict'; + +var frontPageApp = angular.module('frontPageApp', ['ngGrid', 'person', 'badge', 'build', 'pagingTableService', 'core.directives']).config(function ($routeProvider) { + $routeProvider. + when('/', {controller: FrontPageCtrl, templateUrl: '/apps/frontPageApp/frontPage.html?noCache=' + noCache}). + when('/badge/', {controller: BadgeListCtrl, templateUrl: '/apps/frontPageApp/badgeList.html?noCache=' + noCache}). + when('/badge/:badgeUuid', {controller: BadgeCtrl, templateUrl: '/apps/frontPageApp/badge.html?noCache=' + noCache}). + when('/person/', {controller: PersonListCtrl, templateUrl: '/apps/frontPageApp/personList.html?noCache=' + noCache}). + when('/person/:personUuid', {controller: PersonCtrl, templateUrl: '/apps/frontPageApp/person.html?noCache=' + noCache}). + when('/build/', {controller: BuildListCtrl, templateUrl: '/apps/frontPageApp/buildList.html?noCache=' + noCache}); +}); + +function FrontPageCtrl($scope, Person, Badge) { + $scope.persons = Person.query(); + $scope.recentBadges = Badge.query(); +} + +function groupBy(array, size) { + var group = []; + var groups = []; + angular.forEach(array, function (element) { + group.push(element); + if (group.length == size) { + groups.push(group); + group = []; + } + }); + + if (group.length != 0) { + groups.push(group); + } + return groups; +} + +function BadgeListCtrl($scope, Badge, PagingTableService) { + var groupSize = 6; + + var personsWatcher = function () { + var withDay = _.map($scope.badges.rows, function(badge) { + badge.day = new Date(badge.badge.createdDate).clearTime().getTime(); +// badge.day.clearTime(); + return badge; + }); + + var byDay = _.groupBy(withDay, 'day'); + console.log("byDay", byDay); +// var dateGroups = _.map(byDay, function(group, date) { +// return {date: groupBy(group, groupSize)} +// }); + + $scope.badgeGroups = byDay; + }; + + $scope.badges = PagingTableService.create($scope, PagingTableService.defaultCallback(Badge), + {count: groupSize * 6, watcher: personsWatcher}); + + $scope.badgeGroups = []; +} + +function BadgeCtrl($scope, $routeParams, Badge) { + var badgeUuid = $routeParams.badgeUuid; + Badge.get({uuid: badgeUuid}, function (badge) { + $scope.badge = badge; + }); +} + +function PersonListCtrl($scope, Person, PagingTableService) { + var groupSize = 4; + var personsWatcher = function () { + $scope.personGroups = groupBy($scope.persons.rows, groupSize); + }; + + $scope.persons = PagingTableService.create($scope, PagingTableService.defaultCallback(Person, {orderBy: "name"}), + {count: groupSize * 6, watcher: personsWatcher}); + + $scope.personGroups = []; +} + +function PersonCtrl($scope, $routeParams, Person, Build, PagingTableService) { + var personUuid = $routeParams.personUuid; + + $scope.mode = 'overview'; + $scope.builds = PagingTableService.create($scope, PagingTableService.defaultCallback(Build, {person: personUuid})); + + $scope.setMode = function(mode) { + $scope.mode = mode; + switch(mode) { + case 'builds': + var builds = $scope.builds; + + console.log("$scope.builds.length=" + builds.rows.length); + if (builds.rows.length == 0) { + $scope.builds.first(); + } + break; + } + }; + + Person.get({uuid: personUuid}, function (person) { + $scope.person = person; + }); + + Build.query({person: personUuid}, function (builds) { + $scope.recentBuilds = builds; + }); +} + +function BuildListCtrl($scope, Build, PagingTableService) { + $scope.builds = PagingTableService.create($scope, PagingTableService.defaultCallback(Build, {fields: "detailed"})); +} diff --git a/src/main/resources/webapp/apps/frontPageApp/person.html b/src/main/resources/webapp/apps/frontPageApp/person.html new file mode 100755 index 0000000..ba5c18d --- /dev/null +++ b/src/main/resources/webapp/apps/frontPageApp/person.html @@ -0,0 +1,100 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>{{person.person.name}}</h1> + </div> + + <ul class="nav nav-tabs"> + <li ng-class="{active: mode == 'overview'}"><a ng-click="setMode('overview')">Overview</a></li> + <li ng-class="{active: mode == 'builds'}"><a ng-click="setMode('builds')">Builds</a></li> + </ul> + + <div id="overview" ng-show="mode == 'overview'" class="row"> + <div class="span6"> + <h3>Upcoming</h3> + <table> + <tr ng-repeat="badge in person.badgesInProgress"> + <td style="padding-right: 1em">{{badge.name}}</td> + <td style="width: 100%"> + <div class="progress" style="margin-bottom: 0;" title="Progress: {{badge.progress}} of {{badge.goal}}"> + <div class="bar" style="width: {{badge.progress / badge.goal * 100}}%;"></div> + </div> + </td> + </tr> + </table> + + <h3>Badges</h3> + <ul class="unstyled"> + <li ng-repeat="badge in person.badges"> + <!-- + <span class="badge-level-{{badge.level}} badge">{{badge.name}}</span> + --> + <strong>{{badge.name}}</strong> + <!-- + <i class="icon-user ng-class: {{{1: 'badge-level-1', 2: 'badge-level-2', 3: 'badge-level-3'}[badge.level]}}"></i> + --> + <span class="badge-level-{{badge.level}} badge"> + <i class="icon-user"></i> + </span> + + {{badge.createdDate | date:'medium'}} + </li> + </ul> + </div> + <div class="span6"> + <h3>Recent builds</h3> + <table class="table"> + <thead> + <!-- + <tr> + <th>Date</th> + <th>Success</th> + <th></th> + </tr> + --> + </thead> + <tbody> + <tr ng-repeat="build in recentBuilds" class="{{{true: 'success', false: 'error'}[build.success]}}"> + <td>{{build.timestamp | date:'medium'}}</td> + <td>{{{true: 'Success', false: 'Failure'}[build.success]}}</td> + <td><a href="/build/{{build.uuid}}">Details</a></td> + </tr> + </tbody> + </table> + </div> + </div> + + <div id="builds" ng-show="mode == 'builds'"> + <h3>Builds</h3> + <table class="table"> + <thead> + <tr> + <th>Date</th> + <th>Success</th> + </tr> + </thead> + <tbody> + <tr ng-repeat="build in builds.rows" class="{{{true: 'build-success', false: 'build-error'}[build.success]}}"> + <td>{{build.timestamp | date:'medium'}}</td> + <td>{{build.success}}</td> + </tr> + </tbody> + <tfoot> + <tr> + <td colspan="2"> + <ul class="pager"> + <li class="previous" ng-class="{disabled: builds.startIndex == 0}"> + <a ng-click="builds.prev()">← Older</a> + </li> + <li class="next"> + <a ng-click="builds.next()">Newer →</a> + </li> + </ul> + </td> + </tr> + </tfoot> + </table> + </div> +</div> diff --git a/src/main/resources/webapp/apps/frontPageApp/personList.html b/src/main/resources/webapp/apps/frontPageApp/personList.html new file mode 100755 index 0000000..5d7d8c6 --- /dev/null +++ b/src/main/resources/webapp/apps/frontPageApp/personList.html @@ -0,0 +1,47 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>People</h1> + </div> + + <style> + .avatar-image { + /* This has to match bootstrap's row margin. */ + margin-left: 30px; + padding-right: 1em; + float: left; + margin-top: 0; + + /* This has to match the Gravatar image */ + width: 80px; + height: 80px; + } + </style> + + <div class="row"> + <div class="span12"> + <div class="row" ng-repeat="group in personGroups"> + <div class="span3" ng-repeat="person in group" style="padding-bottom: 1em"> + <div class="row"> + <person-avatar person="person.person"></person-avatar> + <a href="/#/person/{{person.person.uuid}}">{{person.person.name}}</a> + <br/> + <span ng-repeat="level in person.badges | countBadgeByLevel | gz"> + <span class="badge-inverse badge-level-{{$index + 1}} badge"><i class="icon-user"></i> x {{level}}</span> + </span> + </div> + </div> + </div> + <ul class="pager"> + <li class="previous" ng-show="persons.startIndex > 0"> + <a ng-click="persons.prev()">← Prev</a> + </li> + <li class="next"> + <a ng-click="persons.next()">Next →</a> + </li> + </ul> + </div> + </div> +</div> diff --git a/src/main/resources/webapp/apps/jenkinsApp/JenkinsResources.js b/src/main/resources/webapp/apps/jenkinsApp/JenkinsResources.js new file mode 100644 index 0000000..89f3139 --- /dev/null +++ b/src/main/resources/webapp/apps/jenkinsApp/JenkinsResources.js @@ -0,0 +1,25 @@ +'use strict'; + +function JenkinsServer($resource) { + return $resource('/resource/jenkins/server/:uuid', {uuid: '@uuid'}); +} + +angular. + module('jenkinsServer', ['ngResource']). + factory('JenkinsServer', JenkinsServer); + +function JenkinsJob($resource) { + return $resource('/resource/jenkins/job/:uuid', {uuid: '@uuid'}); +} + +angular. + module('jenkinsJob', ['ngResource']). + factory('JenkinsJob', JenkinsJob); + +function JenkinsBuild($resource) { + return $resource('/resource/jenkins/build/:uuid', {uuid: '@uuid'}); +} + +angular. + module('jenkinsBuild', ['ngResource']). + factory('JenkinsBuild', JenkinsBuild); diff --git a/src/main/resources/webapp/apps/jenkinsApp/build.html b/src/main/resources/webapp/apps/jenkinsApp/build.html new file mode 100644 index 0000000..7239c90 --- /dev/null +++ b/src/main/resources/webapp/apps/jenkinsApp/build.html @@ -0,0 +1,43 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>Jenkins Build</h1> + </div> + + <ul class="breadcrumb"> + <li><a ng-click="showServers()">All Servers</a> <span class="divider">/</span></li> + <li><a ng-click="showServer()">Servers</a> <span class="divider">/</span></li> + <li><a ng-click="showJob()">Job</a> <span class="divider">/</span></li> + <li class="active">Build</li> + </ul> + + <h3>Overview</h3> + <table class="table"> + <tbody> + <tr> + <th>Timestamp</th> + <td>{{details.build.timestamp | date:'medium'}}</td> + </tr> + <tr> + <th>Number</th> + <td>{{details.build.number}}</td> + </tr> + <tr> + <th>Duration</th> + <td>{{details.build.duration / 1000 | number:0}}s</td> + </tr> + </tbody> + </table> + + <h3>Users</h3> + <table> + <tbody> + <tr ng-repeat="user in details.participants"> + <td>{{user.uuid}}</td> + </tr> + </tbody> + </table> + +</div> diff --git a/src/main/resources/webapp/apps/jenkinsApp/jenkinsApp.js b/src/main/resources/webapp/apps/jenkinsApp/jenkinsApp.js new file mode 100644 index 0000000..e42c67b --- /dev/null +++ b/src/main/resources/webapp/apps/jenkinsApp/jenkinsApp.js @@ -0,0 +1,57 @@ +'use strict'; + +var jenkinsApp = angular.module('jenkinsApp', ['jenkinsServer', 'jenkinsJob', 'jenkinsBuild', 'core.directives', 'pagingTableService']).config(function ($routeProvider) { + $routeProvider. + when('/', {controller: ServerListCtrl, templateUrl: '/apps/jenkinsApp/server-list.html?noCache=' + noCache}). + when('/server/:uuid', {controller: ServerCtrl, templateUrl: '/apps/jenkinsApp/server.html?noCache=' + noCache}). + when('/job/:uuid', {controller: JobCtrl, templateUrl: '/apps/jenkinsApp/job.html?noCache=' + noCache}). + when('/build/:uuid', {controller: BuildCtrl, templateUrl: '/apps/jenkinsApp/build.html?noCache=' + noCache}); +}); + +function ServerListCtrl($scope, $location, JenkinsServer) { + JenkinsServer.query(function (servers) { + $scope.servers = servers; + }); + + $scope.showServers = function () { $location.path('/'); }; + $scope.showServer = function (uuid) { $location.path('/server/' + uuid); }; +} + +function ServerCtrl($scope, $location, $routeParams, JenkinsServer, JenkinsJob, PagingTableService) { + var serverUuid = $routeParams.uuid; + + JenkinsServer.get({uuid: serverUuid}, function (server) { + $scope.server = server; + }); + + $scope.jobs = PagingTableService.create($scope, PagingTableService.defaultCallback(JenkinsJob, {server: serverUuid})); + + $scope.showServers = function () { $location.path('/'); }; + $scope.showJob = function (uuid) { $location.path('/job/' + uuid); }; +} + +function JobCtrl($scope, $location, $routeParams, JenkinsJob, JenkinsBuild, PagingTableService) { + var jobUuid = $routeParams.uuid; + + JenkinsJob.get({uuid: jobUuid}, function (details) { + $scope.details = details; + }); + + $scope.builds = PagingTableService.create($scope, PagingTableService.defaultCallback(JenkinsBuild, {job: jobUuid})); + + $scope.showServers = function () { $location.path('/'); }; + $scope.showServer = function () { $location.path('/server/' + $scope.job.server); }; + $scope.showBuild = function (uuid) { $location.path('/build/' + uuid); }; +} + +function BuildCtrl($scope, $location, $routeParams, JenkinsBuild) { + var buildUuid = $routeParams.uuid; + + JenkinsBuild.get({uuid: buildUuid}, function (details) { + $scope.details = details; + }); + + $scope.showServers = function () { $location.path('/'); }; + $scope.showServer = function (uuid) { $location.path('/server/' + $scope.server.uuid); }; + $scope.showJob = function (uuid) { $location.path('/job/' + $scope.build.job); }; +} diff --git a/src/main/resources/webapp/apps/jenkinsApp/job.html b/src/main/resources/webapp/apps/jenkinsApp/job.html new file mode 100755 index 0000000..8942ab7 --- /dev/null +++ b/src/main/resources/webapp/apps/jenkinsApp/job.html @@ -0,0 +1,61 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>Jenkins Job</h1> + </div> + + <ul class="breadcrumb"> + <li><a ng-click="showServers()">All Servers</a> <span class="divider">/</span></li> + <li><a ng-click="showServer()">Servers</a> <span class="divider">/</span></li> + <li class="active">Job</li> + </ul> + + <h3>Overview</h3> + + <table class="table"> + <tbody> + <tr> + <th>URL</th> + <td><a href="{{details.job.displayName}}">{{details.job.displayName}}</a></td> + </tr> + <tr> + <th>Build count</th> + <td>{{details.buildCount}}</td> + </tr> + </tbody> + </table> + + <h3>Recent Builds</h3> + <table class="table"> + <thead> + <tr> + <th>Build</th> + <th>Result</th> + <th></th> + </tr> + </thead> + <tbody> + <tr ng-repeat="build in builds.rows" class="{{{true: 'success', false: 'error'}[build.success]}}"> + <td>{{build.timestamp | date:'medium'}}</td> + <td>{{build.result}}</td> + <td><a class="btn" ng-click="showBuild(build.uuid)"><i class="icon-chevron-right"></i></a></td> + </tr> + </tbody> + <tfoot> + <tr> + <td colspan="3"> + <ul class="pager"> + <li class="previous" ng-class="{disabled: builds.startIndex == 0}"> + <a ng-click="builds.prev()">← Older</a> + </li> + <li class="next"> + <a ng-click="builds.next()">Newer →</a> + </li> + </ul> + </td> + </tr> + </tfoot> + </table> +</div> diff --git a/src/main/resources/webapp/apps/jenkinsApp/server-list.html b/src/main/resources/webapp/apps/jenkinsApp/server-list.html new file mode 100644 index 0000000..9e297e6 --- /dev/null +++ b/src/main/resources/webapp/apps/jenkinsApp/server-list.html @@ -0,0 +1,32 @@ +<div class="container"> + + <navbar/> + + <div class="page-header"> + <h1>Jenkins Servers</h1> + </div> + + <ul class="breadcrumb"> + <li class="active">All Servers</li> + </ul> + + <table class="table table-condensed"> + <thead> + <tr> + <th>URL</th> + <th>Enabled</th> + <th></th> + <th></th> + </tr> + </thead> + <tbody> + <tr ng-repeat="server in servers"> + <td>{{server.url}}</td> + <td>{{server.enabled}}</td> + <td><a href="{{server.url}}">Visit</a></td> + <td><a class="btn" ng-click="showServer(server.uuid)"><i class="icon-chevron-right"></i></a> + </td> + </tr> + </tbody> + </table> +</div> diff --git a/src/main/resources/webapp/apps/jenkinsApp/server.html b/src/main/resources/webapp/apps/jenkinsApp/server.html new file mode 100644 index 0000000..7fbd9f5 --- /dev/null +++ b/src/main/resources/webapp/apps/jenkinsApp/server.html @@ -0,0 +1,64 @@ +<div class="container"> + + <navbar/> + + + <div class="page-header"> + <h1>Jenkins Server</h1> + </div> + + <ul class="breadcrumb"> + <li><a ng-click="showServers()">All Servers</a> <span class="divider">/</span></li> + <li class="active">Server</li> + </ul> + + <h3>Overview</h3> + <table class="table"> + <tbody> + <tr> + <th>URL</th> + <td><a href="{{server.url}}">{{server.url}}</a></td> + </tr> + <tr> + <th>Enabled</th> + <td>{{server.enabled}}</td> + </tr> + <tr> + <th>Stats</th> + <td>{{server.jobCount}} jobs, {{server.buildCount}} builds</td> + </tr> + </tbody> + </table> + + <h3>Recent Jobs</h3> + <table class="table"> + <thead> + <tr> + <th>Job</th> + </tr> + </thead> + <tbody> + <tr ng-repeat="job in jobs.rows"> + <td>{{job.createdDate | date:'medium'}}</td> + <td>{{job.displayName}}</td> + <td>{{job.uuid}}</td> + <td><a class="btn" ng-click="showJob(job.uuid)"><i class="icon-chevron-right"></i></a></td> + </tr> + </tbody> + <tfoot> + <tr> + <td colspan="3"> + <ul class="pager"> + <li class="previous" ng-class="{disabled: jobs.startIndex == 0}"> + <a ng-click="jobs.prev()">← Older</a> + </li> + <li class="next"> + <a ng-click="jobs.next()">Newer →</a> + </li> + </ul> + </td> + </tr> + </tfoot> + </table> + +</div> |