mirror of
https://github.com/ohwgiles/laminar.git
synced 2024-10-27 20:34:20 +00:00
spinner+progress
This commit is contained in:
parent
1e0a2ebc36
commit
2b6cbc18b1
@ -58,7 +58,7 @@ add_custom_command(OUTPUT laminar.capnp.c++ laminar.capnp.h
|
|||||||
# Zip and compile statically served resources
|
# Zip and compile statically served resources
|
||||||
generate_compressed_bins(${CMAKE_SOURCE_DIR}/src/resources index.html js/app.js
|
generate_compressed_bins(${CMAKE_SOURCE_DIR}/src/resources index.html js/app.js
|
||||||
tpl/home.html tpl/job.html tpl/run.html tpl/browse.html
|
tpl/home.html tpl/job.html tpl/run.html tpl/browse.html
|
||||||
favicon.ico favicon-152.png icon.png)
|
favicon.ico favicon-152.png icon.png progress.png)
|
||||||
# Download 3rd-party frontend JS libs...
|
# Download 3rd-party frontend JS libs...
|
||||||
file(DOWNLOAD https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js
|
file(DOWNLOAD https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js
|
||||||
js/angular.min.js EXPECTED_MD5 b1137641dbb512a60e83d673f7e2d98f)
|
js/angular.min.js EXPECTED_MD5 b1137641dbb512a60e83d673f7e2d98f)
|
||||||
|
@ -30,6 +30,7 @@ Resources::Resources()
|
|||||||
INIT_RESOURCE("/", index_html);
|
INIT_RESOURCE("/", index_html);
|
||||||
INIT_RESOURCE("/favicon.ico", favicon_ico);
|
INIT_RESOURCE("/favicon.ico", favicon_ico);
|
||||||
INIT_RESOURCE("/favicon-152.png", favicon_152_png);
|
INIT_RESOURCE("/favicon-152.png", favicon_152_png);
|
||||||
|
INIT_RESOURCE("/progress.png", progress_png);
|
||||||
INIT_RESOURCE("/icon.png", icon_png);
|
INIT_RESOURCE("/icon.png", icon_png);
|
||||||
INIT_RESOURCE("/js/app.js", js_app_js);
|
INIT_RESOURCE("/js/app.js", js_app_js);
|
||||||
INIT_RESOURCE("/js/Chart.HorizontalBar.js", js_Chart_HorizontalBar_js);
|
INIT_RESOURCE("/js/Chart.HorizontalBar.js", js_Chart_HorizontalBar_js);
|
||||||
|
@ -32,8 +32,29 @@
|
|||||||
}
|
}
|
||||||
.progress {
|
.progress {
|
||||||
height: 10px;
|
height: 10px;
|
||||||
|
margin-top: 5px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
.spin {
|
||||||
|
-webkit-animation: rotation 2s infinite linear;
|
||||||
|
}
|
||||||
|
@-webkit-keyframes rotation {
|
||||||
|
from {-webkit-transform: rotate(0deg);}
|
||||||
|
to {-webkit-transform: rotate(359deg);}
|
||||||
|
}
|
||||||
|
img.spin.small {
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
}
|
||||||
|
img.spin {
|
||||||
|
-webkit-animation:spin 4s linear infinite;
|
||||||
|
-moz-animation:spin 4s linear infinite;
|
||||||
|
animation:spin 4s linear infinite;
|
||||||
|
}
|
||||||
|
@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
|
||||||
|
@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
|
||||||
|
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -59,9 +59,9 @@ angular.module('laminar',['ngRoute','ngSanitize'])
|
|||||||
$rootScope.title = data.title;
|
$rootScope.title = data.title;
|
||||||
// populate jobs
|
// populate jobs
|
||||||
$scope.jobsQueued = data.queued;
|
$scope.jobsQueued = data.queued;
|
||||||
|
data.running.forEach($rootScope.updateProgress);
|
||||||
$scope.jobsRunning = data.running;
|
$scope.jobsRunning = data.running;
|
||||||
$scope.jobsRecent = data.recent;
|
$scope.jobsRecent = data.recent;
|
||||||
|
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
|
|
||||||
// setup charts
|
// setup charts
|
||||||
@ -145,20 +145,8 @@ angular.module('laminar',['ngRoute','ngSanitize'])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
timeUpdater = $interval(function() {
|
var timeUpdater = $interval(function() {
|
||||||
$scope.jobsRunning.forEach(function(o){
|
$scope.jobsRunning.forEach($rootScope.updateProgress);
|
||||||
if(o.etc) {
|
|
||||||
var d = new Date();
|
|
||||||
var p = (d.getTime()/1000 - o.started) / (o.etc - o.started);
|
|
||||||
if(p > 1.2) {
|
|
||||||
o.overtime = true;
|
|
||||||
} else if(p >= 1) {
|
|
||||||
o.progress = 99;
|
|
||||||
} else {
|
|
||||||
o.progress = 100 * p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 1000);
|
}, 1000);
|
||||||
$scope.$on('$destroy', function() {
|
$scope.$on('$destroy', function() {
|
||||||
$interval.cancel(timeUpdater);
|
$interval.cancel(timeUpdater);
|
||||||
@ -259,7 +247,7 @@ angular.module('laminar',['ngRoute','ngSanitize'])
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.controller('RunController', function($rootScope, $scope, $routeParams, $ws) {
|
.controller('RunController', function($rootScope, $scope, $routeParams, $ws, $interval) {
|
||||||
$rootScope.bc = {
|
$rootScope.bc = {
|
||||||
nodes: [{ href: '/', label: 'Home' },
|
nodes: [{ href: '/', label: 'Home' },
|
||||||
{ href: '/jobs', label: 'Jobs' },
|
{ href: '/jobs', label: 'Jobs' },
|
||||||
@ -273,6 +261,7 @@ angular.module('laminar',['ngRoute','ngSanitize'])
|
|||||||
$ws.statusListener({
|
$ws.statusListener({
|
||||||
status: function(data) {
|
status: function(data) {
|
||||||
$rootScope.title = data.title;
|
$rootScope.title = data.title;
|
||||||
|
$rootScope.updateProgress(data);
|
||||||
$scope.job = data;
|
$scope.job = data;
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
},
|
},
|
||||||
@ -299,6 +288,12 @@ angular.module('laminar',['ngRoute','ngSanitize'])
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var timeUpdater = $interval(function() {
|
||||||
|
$rootScope.updateProgress($scope.job);
|
||||||
|
}, 1000);
|
||||||
|
$scope.$on('$destroy', function() {
|
||||||
|
$interval.cancel(timeUpdater);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.run(function($rootScope) {
|
.run(function($rootScope) {
|
||||||
angular.extend($rootScope, {
|
angular.extend($rootScope, {
|
||||||
@ -309,11 +304,26 @@ angular.module('laminar',['ngRoute','ngSanitize'])
|
|||||||
// TODO reimplement when toLocaleDateString() accepts formatting
|
// TODO reimplement when toLocaleDateString() accepts formatting
|
||||||
// options on most browsers
|
// options on most browsers
|
||||||
var d = new Date(1000 * unix);
|
var d = new Date(1000 * unix);
|
||||||
return d.getHours() + ':' + d.getMinutes() + ' on ' +
|
var m = d.getMinutes();
|
||||||
|
if(m < 10) m = '0' + m;
|
||||||
|
return d.getHours() + ':' + m + ' on ' +
|
||||||
['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][d.getDay()] + ' '
|
['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][d.getDay()] + ' '
|
||||||
+ d.getDate() + '. ' + ['Jan','Feb','Mar','Apr','May','Jun',
|
+ d.getDate() + '. ' + ['Jan','Feb','Mar','Apr','May','Jun',
|
||||||
'Jul','Aug','Sep', 'Oct','Nov','Dec'][d.getMonth()] + ' '
|
'Jul','Aug','Sep', 'Oct','Nov','Dec'][d.getMonth()] + ' '
|
||||||
+ d.getFullYear();
|
+ d.getFullYear();
|
||||||
|
},
|
||||||
|
updateProgress: function(o){
|
||||||
|
if(o.etc) {
|
||||||
|
var d = new Date();
|
||||||
|
var p = (d.getTime()/1000 - o.started) / (o.etc - o.started);
|
||||||
|
if(p > 1.2) {
|
||||||
|
o.overtime = true;
|
||||||
|
} else if(p >= 1) {
|
||||||
|
o.progress = 99;
|
||||||
|
} else {
|
||||||
|
o.progress = 100 * p;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
BIN
src/resources/progress.png
Normal file
BIN
src/resources/progress.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 816 B |
@ -6,7 +6,7 @@
|
|||||||
<td><a href="jobs/{{job.name}}">{{job.name}}</a> <i>queued</i></td>
|
<td><a href="jobs/{{job.name}}">{{job.name}}</a> <i>queued</i></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="animate-repeat" ng-repeat="job in jobsRunning track by $index">
|
<tr class="animate-repeat" ng-repeat="job in jobsRunning track by $index">
|
||||||
<td><a href="jobs/{{job.name}}">{{job.name}}</a> <a href="jobs/{{job.name}}/{{job.number}}">#{{job.number}}</a> <div class="progress">
|
<td><img class="spin small" src="/progress.png"> <a href="jobs/{{job.name}}">{{job.name}}</a> <a href="jobs/{{job.name}}/{{job.number}}">#{{job.number}}</a> <div class="progress">
|
||||||
<div class="progress-bar progress-bar-{{job.overtime?'warning':'info'}} progress-bar-striped {{job.etc?'':'active'}}" style="width:{{!job.etc?'100':job.progress}}%"></div>
|
<div class="progress-bar progress-bar-{{job.overtime?'warning':'info'}} progress-bar-striped {{job.etc?'':'active'}}" style="width:{{!job.etc?'100':job.progress}}%"></div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
@ -32,7 +32,10 @@
|
|||||||
<td colspan="4"><i>{{nQueued}} run(s) queued</i></td>
|
<td colspan="4"><i>{{nQueued}} run(s) queued</i></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="animate-repeat" ng-repeat="job in jobsRunning track by $index">
|
<tr class="animate-repeat" ng-repeat="job in jobsRunning track by $index">
|
||||||
<td><a href="jobs/{{job.name}}/{{job.number}}">#{{job.number}}</a> progressbar?</td>
|
<td><img class="spin small" src="/progress.png"> <a href="jobs/{{name}}/{{job.number}}">#{{job.number}}</a></td>
|
||||||
|
<td class="text-center">{{formatDate(job.started)}}</td>
|
||||||
|
<td class="text-center">--</td>
|
||||||
|
<td class="text-center hidden-xs">{{job.reason}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="animate-repeat" ng-repeat="job in jobsRecent track by $index">
|
<tr class="animate-repeat" ng-repeat="job in jobsRecent track by $index">
|
||||||
<td><span ng-bind-html="runIcon(job.result)"></span> <a href="jobs/{{name}}/{{job.number}}">#{{job.number}}</a></td>
|
<td><span ng-bind-html="runIcon(job.result)"></span> <a href="jobs/{{name}}/{{job.number}}">#{{job.number}}</a></td>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-5 col-md-6 col-lg-7">
|
<div class="col-sm-5 col-md-6 col-lg-7">
|
||||||
<h3 style="float:left"><span ng-bind-html="runIcon(job.result)"></span> {{name}} #{{num}}</h3>
|
<h3 style="float:left"><img class="spin" src="/progress.png" ng-hide="job.result"><span ng-bind-html="runIcon(job.result)"></span> {{name}} #{{num}}</h3>
|
||||||
<nav class="pull-left">
|
<nav class="pull-left">
|
||||||
<ul class="pagination" style="margin:15px 20px">
|
<ul class="pagination" style="margin:15px 20px">
|
||||||
<li><a href="jobs/{{name}}/{{num-1}}">«</a></li>
|
<li><a href="jobs/{{name}}/{{num-1}}">«</a></li>
|
||||||
@ -18,6 +18,9 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-7 col-md-6 col-lg-5">
|
<div class="col-sm-7 col-md-6 col-lg-5">
|
||||||
|
<div class="progress" ng-hide="job.result">
|
||||||
|
<div class="progress-bar progress-bar-{{job.overtime?'warning':'info'}} progress-bar-striped {{job.etc?'':'active'}}" style="width:{{!job.etc?'100':job.progress}}%;"></div>
|
||||||
|
</div>
|
||||||
<div class="panel panel-default" ng-show="job.artifacts.length">
|
<div class="panel panel-default" ng-show="job.artifacts.length">
|
||||||
<div class="panel-heading">Artifacts</div>
|
<div class="panel-heading">Artifacts</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
Loading…
Reference in New Issue
Block a user