2015-09-13 20:25:26 +00:00
<!doctype html>
2017-07-13 18:57:28 +00:00
< html >
2015-09-13 20:25:26 +00:00
< head >
< base href = "/" >
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
2015-11-01 10:34:18 +00:00
< meta name = "apple-mobile-web-app-capable" content = "yes" / >
2015-09-20 17:57:05 +00:00
< link rel = "apple-touch-icon-precomposed" href = "/favicon-152.png" >
2015-09-13 20:25:26 +00:00
< title > Laminar< / title >
2017-07-13 18:57:28 +00:00
< script src = "/js/vue.min.js" > < / script >
< script src = "/js/vue-router.min.js" > < / script >
< script src = "/js/ansi_up.js" > < / script >
2015-09-13 20:25:26 +00:00
< script src = "/js/Chart.min.js" > < / script >
< script src = "/js/Chart.HorizontalBar.js" > < / script >
< link href = "/css/bootstrap.min.css" rel = "stylesheet" >
2017-12-29 09:14:10 +00:00
< link href = "/custom/style.css" rel = "stylesheet" >
2017-07-13 18:57:28 +00:00
< script src = "/js/app.js" defer > < / script >
2015-09-13 20:25:26 +00:00
< style >
body, html { height: 100%; }
2017-12-02 18:52:34 +00:00
.navbar { margin-bottom: 0; border-radius: 0; }
2015-09-20 17:57:05 +00:00
.navbar-brand { margin: 0 -15px; padding: 7px 15px }
2015-09-26 20:54:27 +00:00
.navbar-brand>img { display: inline; }
2015-09-20 17:57:05 +00:00
a.navbar-btn { color: #9d9d9d; }
a.navbar-btn.active { color: #fff; }
a.navbar-btn:hover { color: #fff; text-decoration: none; }
a.navbar-btn:focus { color: #fff; }
2017-12-29 15:18:43 +00:00
.bell { margin: 8px 15px; color: #9d9d9d; }
.bell:hover { text-decoration: none; color: #9d9d9d; cursor: pointer; }
.bell.active { color: #333; }
2015-09-26 20:54:27 +00:00
dt,dd { line-height: 2; }
2015-09-13 20:25:26 +00:00
canvas {
width: 100% !important;
max-width: 800px;
height: auto !important;
}
.progress {
height: 10px;
2015-11-01 10:24:28 +00:00
margin-top: 5px;
2015-09-13 20:25:26 +00:00
margin-bottom: 0;
}
2017-07-13 18:57:28 +00:00
table#joblist tr:first-child td { border-top: 0; }
2017-12-23 15:15:48 +00:00
#popup-connecting {
position: fixed;
background: white;
border: 1px solid #ddd;
bottom: 10px;
right: 10px;
padding: 20px;
}
2015-09-13 20:25:26 +00:00
< / style >
< / head >
< body >
2017-07-13 18:57:28 +00:00
< template id = "home" > < div >
< ol class = "breadcrumb" > < li class = "active" > Home< / li > < / ol >
< div class = "container-fluid" > < div class = "row" >
< div class = "col-sm-5 col-md-4 col-lg-3 dash" >
< table class = "table table-bordered" >
< tr v-for = "job in jobsQueued" >
< td > < router-link :to = "'/jobs/'+job.name" > {{job.name}}< / router-link > < i > queued< / i > < / td >
< / tr >
< tr v-for = "job in jobsRunning" >
2017-12-02 16:30:45 +00:00
< td > < span v-html = "runIcon(job.result)" > < / span > < router-link :to = "'/jobs/'+job.name" > {{job.name}}< / router-link > < router-link :to = "'/jobs/'+job.name+'/'+job.number" > #{{job.number}}< / router-link >
2017-11-06 17:22:03 +00:00
< small class = "pull-right" > {{formatDuration(job.started, job.completed)}}< / small >
< div class = "progress" >
< div class = "progress-bar progress-bar-striped" :class = "'progress-bar-'+(job.overtime?'warning':'info')" :class = "job.etc?'':'active'" :style = "'width:'+(!job.etc?'100':job.progress)+'%'" > < / div >
2017-07-13 18:57:28 +00:00
< / div >
< / td >
< / tr >
< tr v-for = "job in jobsRecent" >
2017-11-06 17:08:14 +00:00
< td > < span v-html = "runIcon(job.result)" > < / span > < router-link :to = "'/jobs/'+job.name" > {{job.name}}< / router-link > < router-link :to = "'/jobs/'+job.name+'/'+job.number" > #{{job.number}}< / router-link > < br > < small > Took {{formatDuration(job.started, job.completed)}} at {{formatDate(job.started)}}< / small > < / td >
2017-07-13 18:57:28 +00:00
< / tr >
< / table >
< / div >
< div class = "col-sm-7 col-md-8 col-lg-9" > < div class = "row" >
< div class = "col-md-6" >
< div class = "panel panel-default" >
< div class = "panel-heading" > Total builds per day this week< / div >
< div class = "panel-body" >
< canvas id = "chartBpd" > < / canvas >
< / div >
< / div >
< / div >
< div class = "col-md-6" >
< div class = "panel panel-default" >
< div class = "panel-heading" > Builds per job in the last 24 hours< / div >
< div class = "panel-body" id = "chartStatus" >
< canvas id = "chartBpj" > < / canvas >
< / div >
< / div >
< / div >
< div class = "col-md-6" >
< div class = "panel panel-default" >
< div class = "panel-heading" > Average build time per job this week< / div >
< div class = "panel-body" >
< canvas id = "chartTpj" > < / canvas >
< / div >
< / div >
< / div >
< div class = "col-md-6" >
< div class = "panel panel-default" >
< div class = "panel-heading" > Current executor utilization< / div >
< div class = "panel-body" >
< canvas id = "chartUtil" > < / canvas >
< / div >
< / div >
< / div >
< / div > < / div >
< / div > < / div >
< / div > < / template >
< template id = "jobs" > < div >
< ol class = "breadcrumb" > < li > < router-link to = "/" > Home< / router-link > < / li > < li class = "active" > Jobs< / li > < / ol >
< div class = "container-fluid" > < div class = "row" >
< div class = "col-xs-12" >
< div class = "pull-right" >
< input class = "form-control" id = "jobFilter" v-model = "search" placeholder = "Filter..." >
< / div >
< ul class = "nav nav-tabs" >
< li :class = "{'active':tag==null}" > < a href v-on:click . prevent = "tag = null" > All Jobs< / a > < / li >
< li v-for = "t in tags" :class = "{'active':t==tag}" > < a href v-on:click . prevent = "tag = t" > {{t}}< / a > < / li >
< / ul >
< table class = "table table-striped" id = "joblist" >
< tr v-for = "job in filteredJobs" >
< td > < router-link :to = "'/jobs/'+job.name" > {{job.name}}< / router-link > < / td >
< td class = "text-center" > < span v-html = "runIcon(job.result)" > < / span > < router-link :to = "'/jobs/'+job.name+'/'+job.number" > #{{job.number}}< / router-link > < / td >
< td class = "text-center" > {{formatDate(job.started)}}< / td >
2017-11-07 06:21:01 +00:00
< td class = "text-center" > {{formatDuration(job.started,job.completed)}}< / td >
2017-07-13 18:57:28 +00:00
< / tr >
< / table >
< / div >
< / div > < / div >
< / div > < / template >
< template id = "job" > < div >
< ol class = "breadcrumb" > < li > < router-link to = "/" > Home< / router-link > < / li > < li > < router-link to = "/jobs" > Jobs< / router-link > < / li > < li class = "active" > {{$route.params.name}}< / li > < / ol > < / ol >
2015-09-13 20:25:26 +00:00
< div class = "container-fluid" >
2017-07-13 18:57:28 +00:00
< div class = "row" >
< div class = "col-sm-5 col-md-6 col-lg-7" >
< h3 > {{$route.params.name}}< / h3 >
< dl class = "dl-horizontal" >
< dt > Last Successful Run< / dt >
< dd > < router-link v-if = "lastSuccess" :to = "'/jobs/'+$route.params.name+'/'+lastSuccess.number" > #{{lastSuccess.number}}< / router-link > {{lastSuccess?' - at '+formatDate(lastSuccess.started):'never'}}< / dd >
< dt > Last Failed Run< / dt >
< dd > < router-link v-if = "lastFailed" :to = "'/jobs/'+$route.params.name+'/'+lastFailed.number" > #{{lastFailed.number}}< / router-link > {{lastFailed?' - at '+formatDate(lastFailed.started):'never'}}< / dd >
< / dl >
< / div >
< div class = "col-sm-7 col-md-6 col-lg-5" >
< div class = "panel panel-default" >
< div class = "panel-heading" > Build time< / div >
< div class = "panel-body" >
< canvas id = "chartBt" > < / canvas >
< / div >
< / div >
< / div >
2015-09-20 17:57:05 +00:00
< / div >
2017-07-13 18:57:28 +00:00
< div class = "row" > < div class = "col-xs-12" >
< table class = "table table-striped" > < thead >
< tr > < th > Run< / th > < th class = "text-center" > Started< / th > < th class = "text-center" > Duration< / th > < th class = "text-center hidden-xs" > Reason< / th > < / tr > < / thead >
< tr v-show = "nQueued" >
< td colspan = "4" > < i > {{nQueued}} run(s) queued< / i > < / td >
< / tr >
< tr v-for = "job in jobsRunning" track-by = "$index" >
2017-12-02 16:30:45 +00:00
< td > < span v-html = "runIcon(job.result)" > < / span > < router-link :to = "'/jobs/'+$route.params.name+'/'+job.number" > #{{job.number}}< / router-link > < / td >
2017-07-13 18:57:28 +00:00
< td class = "text-center" > {{formatDate(job.started)}}< / td >
2017-11-03 14:47:30 +00:00
< td class = "text-center" > {{formatDuration(job.started, job.completed)}}< / td >
2017-07-13 18:57:28 +00:00
< td class = "text-center hidden-xs" > {{job.reason}}< / td >
< / tr >
< tr v-for = "job in jobsRecent" track-by = "$index" >
< td > < span v-html = "runIcon(job.result)" > < / span > < router-link :to = "'/jobs/'+$route.params.name+'/'+job.number" > #{{job.number}}< / router-link > < / td >
< td class = "text-center" > {{formatDate(job.started)}}< / td >
2017-11-03 14:47:30 +00:00
< td class = "text-center" > {{formatDuration(job.started, job.completed)}}< / td >
2017-07-13 18:57:28 +00:00
< td class = "text-center hidden-xs" > {{job.reason}}< / td >
< / tr >
< / table >
< / div > < / div >
2015-09-13 20:25:26 +00:00
< / div >
2017-07-13 18:57:28 +00:00
< / div > < / template >
< template id = "run" > < div >
< ol class = "breadcrumb" > < li > < router-link to = "/" > Home< / router-link > < / li > < li > < router-link to = "/jobs" > Jobs< / router-link > < / li > < li > < router-link :to = "'/jobs/'+$route.params.name" > {{$route.params.name}}< / router-link > < / li > < li class = "active" > #{{$route.params.number}}< / li > < / ol > < / ol >
< div class = "container-fluid" >
< div class = "row" >
< div class = "col-sm-5 col-md-6 col-lg-7" >
2017-11-07 17:04:49 +00:00
< h3 style = "float:left" > < span v-html = "runIcon(job.result)" > < / span > {{$route.params.name}} #{{$route.params.number}}< / h3 >
2017-07-13 18:57:28 +00:00
< nav class = "pull-left" >
< ul class = "pagination" style = "margin:15px 20px" >
< li v-show = "$route.params.number > 1" > < router-link :to = "'/jobs/'+$route.params.name+'/'+($route.params.number-1)" > « < / router-link > < / li >
< li v-show = "latestNum > $route.params.number" > < router-link :to = "'/jobs/'+$route.params.name+'/'+(parseInt($route.params.number)+1)" > » < / router-link > < / li >
< / ul >
< / nav >
< div style = "clear:both;" > < / div >
< dl class = "dl-horizontal" >
< dt > Reason< / dt > < dd > {{job.reason}}< / dd >
< dt > Queued for< / dt > < dd > {{job.queued}}s< / dd >
< dt > Started< / dt > < dd > {{formatDate(job.started)}}< / dd >
< dt v-show = "runComplete(job)" > Completed< / dt > < dd v-show = "job.completed" > {{formatDate(job.completed)}}< / dd >
2017-11-03 14:47:30 +00:00
< dt > Duration< / dt > < dd > {{formatDuration(job.started, job.completed)}}< / dd >
2017-07-13 18:57:28 +00:00
< / dl >
< / div >
< div class = "col-sm-7 col-md-6 col-lg-5" >
< div class = "progress" v-show = "job.result == 'running'" >
< div class = "progress-bar progress-bar-striped" :class = "'progress-bar-'+(job.overtime?'warning':'info')" :class = "job.etc?'':'active'" :style = "{width:!job.etc?100:job.progress + '%'}" > < / div >
< / div >
< div class = "panel panel-default" v-show = "job.artifacts.length" >
< div class = "panel-heading" > Artifacts< / div >
< div class = "panel-body" >
< ul class = "list-unstyled" style = "margin-bottom: 0" >
2017-09-23 08:11:38 +00:00
< li v-for = "art in job.artifacts" > < a :href = "art.url" target = "_self" > {{art.filename}}< / a > < / li >
2017-07-13 18:57:28 +00:00
< / ul >
< / div >
< / div >
< / div >
< / div >
< div class = "row" > < div class = "col-xs-12" >
< button type = "button" class = "btn btn-default btn-xs pull-right" :class = "{'active':autoscroll}" v-on:click = "autoscroll = !autoscroll" style = "margin-top:10px" > Autoscroll< / button >
< h4 > Console output< / h4 >
< pre v-html = "log" > < / pre >
< / div > < / div >
< / div >
< / div > < / template >
< div id = "app" >
< nav class = "navbar navbar-inverse" >
2017-12-29 15:18:43 +00:00
< div >
< router-link to = "/" class = "navbar-brand" > < img src = "/icon.png" > {{title}}< / router-link >
< router-link to = "/jobs" class = "btn navbar-btn pull-right" > Jobs< / router-link >
2017-07-13 18:57:28 +00:00
< / div >
< / nav >
2017-12-29 15:18:43 +00:00
< a v-on:click = "toggleNotifications(!notify)" v-show = "supportsNotifications" class = "bell pull-right" :class = "{'active':notify}" :title = "(notify?'Disable':'Enable')+' notifications'" > 🔔 < / a >
2017-07-13 18:57:28 +00:00
< router-view > < / router-view >
2017-12-23 15:15:48 +00:00
< div v-show = "!connected" id = "popup-connecting" > < img src = "/spin.gif" > Connecting...< / div >
2017-07-13 18:57:28 +00:00
< / div >
2015-09-13 20:25:26 +00:00
< / body >
< / html >