internal/web/templates/mr.html

144 lines · 7195 bytes

  1{{define "mrrange"}}<code>{{if .SourcePath}}{{.SourcePath}}:{{end}}{{.SourceRef}}</code> into <code>{{.TargetRef}}</code>{{end}}
  2{{define "title"}}!{{.MR.Number}} · {{.Repo.OwnerName}}/{{.Repo.Name}}{{end}}
  3{{define "content"}}
  4{{$base := printf "/%s/%s/mrs/%d" .Repo.OwnerName .Repo.Name .MR.Number}}
  5<h1 class="issuetitle">{{.MR.Title}} <span class="issuenumber">!{{.MR.Number}}</span></h1>
  6<p class="issuemeta"><span class="chip chip-{{.MR.State}}">{{.MR.State}}</span>
  7{{if and (eq .MR.State "merged") .MR.MergedAt}}
  8  {{if .MR.MergedBy}}<a href="/{{.MR.MergedBy}}">{{.MR.MergedBy}}</a> merged{{else}}Merged{{end}}
  9  {{template "mrrange" .MR}} on {{when .MR.MergedAt}}
 10{{else if and (eq .MR.State "closed") .MR.ClosedAt}}
 11  {{if .MR.ClosedBy}}<a href="/{{.MR.ClosedBy}}">{{.MR.ClosedBy}}</a> closed this{{else}}Closed{{end}}
 12  without merging {{template "mrrange" .MR}} on {{when .MR.ClosedAt}}
 13{{else if or (eq .MR.State "merged") (eq .MR.State "closed")}}
 14  {{template "mrrange" .MR}}
 15{{else}}
 16  <a href="/{{.MR.Author}}">{{.MR.Author}}</a> wants to merge {{template "mrrange" .MR}}
 17{{end}}</p>
 18
 19{{if .Notice}}<p class="error" role="alert">{{.Notice}}</p>{{end}}
 20
 21<div class="withaside">
 22<div class="mainside">
 23
 24<nav class="subtabs" aria-label="Merge request">
 25  <a {{if eq .View "conversation"}}aria-current="page" {{end}}href="{{$base}}">Conversation{{if .Comments}} <i>{{len .Comments}}</i>{{end}}</a>
 26  <a {{if eq .View "commits"}}aria-current="page" {{end}}href="{{$base}}?view=commits">Commits{{if .Commits}} <i>{{len .Commits}}</i>{{end}}</a>
 27  <a {{if eq .View "diff"}}aria-current="page" {{end}}href="{{$base}}?view=diff">Files changed{{if .Stat.Files}} <i>{{.Stat.Files}}</i>{{end}}</a>
 28</nav>
 29
 30{{if eq .View "conversation"}}
 31{{if .CanEdit}}<details class="editbox"><summary>Edit</summary>
 32<form method="post" action="{{$base}}/edit" class="commentform">
 33<p><input type="text" name="title" aria-label="Title" value="{{.MR.Title}}" required></p>
 34<p><textarea name="body" aria-label="Description" rows="8">{{.MR.Body}}</textarea></p>
 35<p><button type="submit">Save</button></p>
 36</form></details>{{end}}
 37{{if .BodyHTML}}<article class="comment">
 38  <header class="commenthead"><strong><a href="/{{.MR.Author}}">{{.MR.Author}}</a></strong></header>
 39  <div class="rendered">{{.BodyHTML}}</div>
 40</article>{{end}}
 41{{range .Comments}}
 42{{if eq .Kind "system"}}<div class="syscomment">{{.BodyHTML}} <span class="when">{{when .CreatedAt}}</span></div>
 43{{else}}<article class="comment">
 44  <header class="commenthead"><strong><a href="/{{.Author}}">{{.Author}}</a></strong> <span class="when">{{when .CreatedAt}}</span></header>
 45  <div class="rendered">{{.BodyHTML}}</div>
 46</article>{{end}}
 47{{end}}
 48{{if .DetachedThreads}}<h2>Threads on earlier revisions</h2>
 49{{range .DetachedThreads}}{{template "thread" dict "T" . "Base" $base "Viewer" $.Viewer "Class" "stale"}}{{end}}{{end}}
 50{{if .Viewer}}
 51<form method="post" action="{{$base}}/comment" class="commentform">
 52<p><textarea name="body" aria-label="Comment" rows="4" placeholder="Comment as {{.Viewer}}"></textarea></p>
 53<p><button type="submit">Comment</button></p>
 54</form>
 55{{end}}
 56
 57{{else if eq .View "commits"}}
 58<ul class="loglist">
 59{{range .Commits}}<li>
 60  <div class="commitmain">
 61    <p class="subject"><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.Subject}}</a></p>
 62    <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" ""}} · {{.Date}}</p>
 63  </div>
 64  <div class="commitside">
 65    {{template "sigbadge" .Sig}}
 66    <code><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.ShortSHA}}</a></code>
 67  </div>
 68</li>
 69{{else}}<li class="empty">no commits on this merge request</li>
 70{{end}}
 71</ul>
 72
 73{{else}}
 74<p class="diffstat">{{.Stat.Files}} file{{if ne .Stat.Files 1}}s{{end}} changed, <span class="add">+{{.Stat.Adds}}</span> <span class="del">−{{.Stat.Dels}}</span></p>
 75{{template "difffiles" dict "Files" .DiffFiles "Base" $base "Viewer" .Viewer}}
 76{{end}}
 77
 78</div>
 79
 80<aside class="aside">
 81  {{if and .CanWrite (or (eq .MR.State "open") (eq .MR.State "source_gone"))}}
 82  <div class="grp">
 83    <h2>Review</h2>
 84    <form method="post" action="{{$base}}/review" class="actions">
 85      <button type="submit" name="verdict" value="approve">Approve</button>
 86      <button type="submit" name="verdict" value="request-changes">Request changes</button>
 87    </form>
 88  </div>
 89  <div class="grp">
 90    <h2>Merge</h2>
 91    {{if .Unresolved}}<p class="row none">{{.Unresolved}} unresolved thread{{if ne .Unresolved 1}}s{{end}}</p>{{end}}
 92    <form method="post" action="{{$base}}/merge" class="actions">
 93      <label class="none" for="strategy">Strategy</label>
 94      <select id="strategy" name="strategy">
 95        <option value="auto">Automatic</option>
 96        <option value="ff">Fast-forward</option>
 97        <option value="merge">Merge commit</option>
 98        <option value="squash">Squash</option>
 99        <option value="rebase">Rebase</option>
100      </select>
101      <button type="submit" class="primary">Merge</button>
102    </form>
103    <form method="post" action="{{$base}}/close" class="actions">
104      <button type="submit">Close without merging</button>
105    </form>
106  </div>
107  {{end}}
108  {{if and .CanEdit (or (eq .MR.State "open") (eq .MR.State "source_gone"))}}
109  <div class="grp">
110    <h2>Target</h2>
111    <form method="post" action="{{$base}}/retarget" class="actions">
112      <label class="none" for="target">Branch</label>
113      <select id="target" name="target">
114        {{range .Branches}}<option value="{{.Name}}"{{if eq .Name $.MR.TargetRef}} selected{{end}}>{{.Name}}</option>{{end}}
115      </select>
116      <button type="submit">Retarget</button>
117    </form>
118    <p class="row none">Retargeting stales existing reviews.</p>
119  </div>
120  {{end}}
121  <div class="grp">
122    <h2>Reviews</h2>
123    {{range .Reviews}}<p class="row"><span class="dot {{if eq .Verdict "approve"}}ok{{else}}pend{{end}}"></span><a href="/{{.Reviewer}}">{{.Reviewer}}</a> {{.Verdict}}{{if .Stale}} <span class="chip chip-stale">stale</span>{{end}}<span class="sub">{{when .CreatedAt}}</span></p>
124    {{else}}<p class="none">No reviews yet</p>{{end}}
125  </div>
126  <div class="grp">
127    <h2>Checks</h2>
128    {{if .Checks}}<p class="row"><span class="badge check-{{.Combined}}">{{.Combined}}</span></p>
129    {{range .Checks}}<p class="row"><span class="dot {{if eq .State "success"}}ok{{else if eq .State "failure"}}bad{{else}}pend{{end}}"></span>{{if .TargetURL}}<a href="{{.TargetURL}}" rel="nofollow">{{.Context}}</a>{{else}}{{.Context}}{{end}} <span class="none">{{.State}}</span><span class="sub">{{when .UpdatedAt}}{{if .Duration}} · {{.Duration}}{{end}}</span></p>{{end}}
130    {{else}}<p class="none">No checks reported</p>{{end}}
131  </div>
132  <div class="grp">
133    <h2>Source</h2>
134    <p class="row"><code>{{if .MR.SourcePath}}{{.MR.SourcePath}}:{{end}}{{.MR.SourceRef}}</code></p>
135    <p class="row none">into <code>{{.MR.TargetRef}}</code> at <code>{{short .MR.HeadSHA}}</code></p>
136  </div>
137  {{if .MR.Milestone}}<div class="grp">
138    <h2>Milestone</h2>
139    <p class="row"><a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/milestones">{{.MR.Milestone}}</a></p>
140  </div>{{end}}
141</aside>
142</div>
143{{end}}
144