| <!DOCTYPE html> |
| <html lang="en"> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <title>Open Go Code Reviews</title> |
| <style> |
| * { |
| box-sizing: border-box; |
| margin: 0; |
| padding: 0; |
| } |
| body { |
| font: 13px system-ui, sans-serif; |
| padding: 1rem; |
| } |
| h2 { |
| margin: 1em 0 .35em; |
| } |
| h3:first-of-type { |
| padding: 0 |
| } |
| a:link, |
| a:visited { |
| color: #00c; |
| } |
| header { |
| border-bottom: 1px solid #666; |
| margin-bottom: 10px; |
| padding-bottom: 10px; |
| } |
| .header-subtitle { |
| color: #666; |
| font-size: .9em; |
| } |
| .filters { |
| display: block; |
| margin: 1em 0; |
| } |
| .filter-input { |
| font: inherit; |
| width: 30em; |
| } |
| .how-to { |
| cursor: pointer; |
| margin-top: 1em; |
| max-width: 40em; |
| } |
| .how-to-container { |
| padding: 0 1em; |
| } |
| .how-to ul { |
| list-style: none; |
| margin-top: .5em; |
| } |
| .how-to li { |
| margin: .25em 1em .75em; |
| } |
| .examples li { |
| margin: .25em 1em; |
| } |
| .row { |
| border-bottom: 1px solid #f1f2f3; |
| display: flex; |
| padding: .5em 0; |
| white-space: nowrap; |
| } |
| .date { |
| min-width: 6rem; |
| } |
| .owner { |
| min-width: 10rem; |
| max-width: 10rem; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| padding-right: 1em; |
| } |
| .icons, |
| .number { |
| flex-shrink: 0; |
| } |
| .icons { |
| height: 20px; |
| margin-right: 1.5em; |
| text-align: right; |
| width: 12em; |
| } |
| .number { |
| margin-right: 1.5em; |
| text-align: right; |
| width: 6ch; |
| } |
| .subject { |
| overflow: hidden; |
| text-overflow: ellipsis; |
| } |
| .pill, |
| .pill:link, |
| .pill:visited { |
| color: #000; |
| display: inline-block; |
| border-radius: 2px; |
| padding: 2px 5px; |
| text-decoration: none; |
| } |
| .plus-two:link, |
| .plus-two:visited, |
| .minus-two:link, |
| .minus-two:visited { |
| color: #fff; |
| } |
| .plus-two { |
| background-color: #2e7d32; |
| } |
| .plus-one { |
| background-color: #dcedc8; |
| } |
| .minus-one { |
| background-color: #fdaeb7; |
| } |
| .minus-two { |
| background-color: #b71c1c; |
| } |
| .no-human-comments { |
| background-color: #e0e0e0; |
| } |
| .release-milestone { |
| background-color: #a0e8ff; |
| } |
| [hidden] { |
| display: none; |
| } |
| </style> |
| <header> |
| <strong>{{.TotalChanges}} open changes</strong> |
| <div class="header-subtitle"> |
| Excluding those marked WIP, having hashtags "wait-author", "wait-release", "wait-issue", or description containing "DO NOT REVIEW". |
| </div> |
| <div class="header-subtitle"> |
| <a href="https://go.googlesource.com/build/+/master/devapp/reviews.go">Source code</a> |
| </div> |
| </header> |
| <div class="filters"> |
| <label class="filter-label">Filter: <input class="filter-input js-filter-input" type="text"></label> |
| <details class="how-to"> |
| <summary>Filters How-to</summary> |
| <div class="how-to-container"> |
| <ul> |
| <li>You can filter on any displayed field below, along with a few other fields not shown, such as reviewer. |
| <li>Exclude terms by prefixing them with a <code>-</code>. |
| <li>The <code>t:</code> operator is short for "tag" and coincides with the colored tags you see in the rows below. |
| <li>Supported tag values include "Changes without a human comment" (<code>t:attn</code>) and <code>Code-Review</code> |
| label values (<code>t:-2</code>, <code>t:+1</code>, and <code>t:+2</code>). |
| <li>All terms use substring matching, meaning that you can type <code>reviewer:iant</code> instead of <code>reviewer:iant@golang.org</code> |
| <li>The following operators are supported: <code>t:, repo:, reviewer:, cc:, involves:, and owner:</code> |
| </ul> |
| Examples: |
| <ul> |
| <li><a href="?q=reviewer%3Abradfitz+repo%3Anet">http2 changes in the net repo where brad is a reviewer</a> |
| <li><a href="?q=-involves%3Aaustin+runtime%3A">runtime changes that don't involve austin</a> |
| </ul> |
| </div> |
| </details> |
| </div> |
| {{range $p := .Projects}} |
| {{if .Changes}} |
| <section hidden> |
| <h2>{{.Project}}</h2> |
| {{range .Changes}} |
| <div class="row" data-terms="{{.SearchTerms}}"> |
| <span class="date">{{.FormattedLastUpdate}}</span> |
| <span class="owner">{{.Owner.Name}}</span> |
| <span class="icons"> |
| {{if .NoHumanComments}}<a class="pill no-human-comments" href="?q=t%3Aattn" title="Has no human comments">→</a>{{end}} |
| {{if .HasMinusTwo}}️<a class="pill minus-two" href="?q=t%3A-2" title="Code-Review: -2">-2</a>{{end}} |
| {{if .HasMinusOne}}<a class="pill minus-one" href="?q=t%3A-1" title="Code-Review: -1">-1</a>{{end}} |
| {{if .HasPlusOne}}<a class="pill plus-one" href="?q=t%3A%2B1" title="Code-Review: +1">+1</a>{{end}} |
| {{if .HasPlusTwo}}<a class="pill plus-two" href="?q=t%3A%2B2" title="Code-Review: +2">+2</a>{{end}} |
| {{if .TryBotMinusOne}}<a class="pill minus-one" href="?q=trybot%3A-1" title="Run-TryBot: -1">🤖-1</a>{{end}} |
| {{if .TryBotPlusOne}}<a class="pill plus-one" href="?q=trybot%3A%2B1" title="Run-TryBot: +1">🤖+1</a>{{end}} |
| {{if .ReleaseMilestone}}<a class="pill release-milestone" href="?q=release%3A{{.ReleaseMilestone}}" title="References an issue in Go{{.ReleaseMilestone}}">{{.ReleaseMilestone}}</a>{{end}} |
| </span> |
| <a class="number" href="https://{{$p.ReviewServer}}/{{.Number}}" target="_blank">{{.Number}}</a> |
| <span class="subject"> |
| {{.Subject}} |
| </span> |
| </div> |
| {{end}} |
| </section> |
| {{end}} |
| {{end}} |
| <script> |
| function filter(query) { |
| console.time('filter'); |
| query = query.toLowerCase(); |
| document.querySelectorAll('.row').forEach(el => { |
| const terms = el.dataset.terms; |
| const queryTerms = query.split(' '); |
| let match = true; |
| for (let i = 0; i < queryTerms.length; i++) { |
| let q = queryTerms[i].trim(); |
| if (q.length === 0 || q === '-') { continue; } |
| if (q.startsWith('-')) { |
| match = match && !terms.includes(q.substr(1)); |
| } else { |
| match = match && terms.includes(q); |
| } |
| } |
| el.hidden = !match; |
| }); |
| document.querySelectorAll('section').forEach(el => { |
| el.hidden = el.querySelectorAll('.row:not([hidden])').length === 0; |
| }); |
| console.timeEnd('filter'); |
| } |
| |
| let debounceTimerId = null; |
| const filterInputEl = document.querySelector('.js-filter-input') |
| filterInputEl.addEventListener('keyup', e => { |
| const q = e.target.value.trim(); |
| let url = new URL(window.location.href); |
| if (!!q) { |
| url.searchParams.set('q', q); |
| } else { |
| url.searchParams.delete('q'); |
| } |
| window.history.replaceState({}, null, url.toString()); |
| |
| if (debounceTimerId) { |
| window.clearTimeout(debounceTimerId); |
| debounceTimerId = null; |
| } |
| debounceTimerId = window.setTimeout(() => { filter(q); }, 200); |
| }); |
| |
| const initialQuery = (new URL(window.location.href)).searchParams.get('q') || ''; |
| filterInputEl.value = initialQuery; |
| filter(initialQuery); |
| </script> |