| <!DOCTYPE html> | |
| <html lang="en"> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Go Release Dashboard</title> | |
| <style> | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| body { | |
| font: 13px monospace; | |
| padding: 1rem; | |
| } | |
| a:link, | |
| a:visited { | |
| color: #00c; | |
| } | |
| .CountSummary { | |
| font-weight: bold; | |
| list-style: none; | |
| margin: .5em 0 1em; | |
| } | |
| .Header { | |
| display: flex; | |
| flex-wrap: wrap; | |
| font-weight: bold; | |
| justify-content: space-between; | |
| } | |
| .BurndownChart { | |
| height: 250px; | |
| width: 500px; | |
| } | |
| .Section { | |
| border-top: 1px solid #aaa; | |
| padding-bottom: 2em; | |
| } | |
| .Section-title { | |
| margin: .5em 0; | |
| } | |
| .Performance-separator { | |
| margin-left:4ch; | |
| } | |
| .Item { | |
| display: flex; | |
| } | |
| .Item-num { | |
| margin-left: 1ch; | |
| min-width: 12ch; | |
| } | |
| .Mark { | |
| width: 3ch; | |
| height: 1ch; | |
| text-align: center; | |
| vertical-align: middle; | |
| } | |
| .DirTitle { | |
| margin: 1em 0 .25em; | |
| } | |
| </style> | |
| <header class="Header"> | |
| <div class="Header-left"> | |
| <div>Release dashboard</div> | |
| <div>{{.LastUpdated}}</div> | |
| <ul class="CountSummary"> | |
| {{range .Sections}} | |
| <li><a href="#{{.Title}}">{{.Count}} {{.Title}}</a></li> | |
| {{end}} | |
| </ul> | |
| </div> | |
| <div class="BurndownChart"> | |
| <canvas class="js-burndownChart"></canvas> | |
| </div> | |
| </header> | |
| <main> | |
| {{range .Sections}} | |
| <section class="Section"> | |
| <h3 class="Section-title" id="{{.Title}}">{{.Title}}</h3> | |
| {{range .Groups}} | |
| {{if .Dir}}<h4 class="DirTitle">{{.Dir}}</h4>{{end}} | |
| {{range .Items}} | |
| {{if .FirstPerformance}}<h5 class="Performance-separator">performance</h5>{{end}} | |
| {{$i := .Issue}} | |
| {{if $i}} | |
| <div class="Item"> | |
| {{$currentBlocker := and (eq .Issue.Milestone.Title $.CurMilestone) .ReleaseBlocker}} | |
| {{if $currentBlocker}} | |
| <div class="Mark" title="{{.Issue.Milestone.Title}} release blocker">★</div> | |
| {{else if .ReleaseBlocker}} | |
| <div class="Mark" title="Release blocker">✩</div> | |
| {{else if .EarlyInCycle}} | |
| <div class="Mark" title="Early In Cycle">⏱󠄀</div> | |
| {{else}} | |
| <div class="Mark"> </div> | |
| {{end}} | |
| <a class="Item-num" href="https://golang.org/issue/{{.Issue.Number}}" target="_blank">#{{.Issue.Number}}</a> | |
| <span class="Item-title">{{.Issue.Title}}</span> | |
| </div> | |
| {{end}} | |
| {{range .CLs}} | |
| {{if not .Closed}} | |
| <div class="Item"> | |
| <div class="Mark"></div> | |
| <span class="Item-num"> | |
| {{if $i}}⤷{{end}} <a href="{{.ReviewURL}}" target="_blank">CL {{.Number}}</a> | |
| </span> | |
| <span class="Item-title">{{if $i}}⤷{{end}} {{.NoPrefixTitle}}</span> | |
| </div> | |
| {{end}} | |
| {{end}} | |
| {{end}} | |
| {{end}} | |
| </section> | |
| {{end}} | |
| </main> | |
| <script src="/js/Chart.min.js"></script> | |
| <script> | |
| const data = {{.BurndownJSON}} | |
| new Chart(document.querySelector('.js-burndownChart'), { | |
| type: 'line', | |
| data: { | |
| labels: data.entries.map(d => d.dateStr), | |
| datasets: [ | |
| { | |
| label: `${data.milestone} total issues`, | |
| yAxisID: 'total', | |
| data: data.entries.map(d => d.open), | |
| backgroundColor: 'transparent', | |
| borderColor: 'rgba(54, 162, 235, 0.8)', | |
| pointRadius: 0, | |
| }, | |
| { | |
| label: `${data.milestone} release blocking`, | |
| yAxisID: 'release-blocking', | |
| data: data.entries.map(d => d.blockers), | |
| backgroundColor: 'rgba(0,0,0,0)', | |
| borderColor: 'rgba(255, 99, 132, 0.8)', | |
| pointRadius: 0, | |
| }, | |
| ], | |
| }, | |
| options: { | |
| animation: { | |
| duration: 0, | |
| }, | |
| title: { | |
| display: true, | |
| text: `${data.milestone} Issues`, | |
| position: 'left', | |
| }, | |
| legend: { | |
| display: false, | |
| }, | |
| tooltips: { | |
| intersect: false, | |
| }, | |
| scales: { | |
| yAxes: [ | |
| { | |
| id: 'total', | |
| ticks: { | |
| beginAtZero: true, | |
| }, | |
| position: 'left', | |
| }, | |
| { | |
| id: 'release-blocking', | |
| ticks: { | |
| beginAtZero: true, | |
| }, | |
| position: 'right', | |
| }, | |
| ], | |
| }, | |
| }, | |
| }); | |
| </script> |