internal/web/templates/layout.html

6b2b26db548cdb89367154ba6ff4b0bcce21dd67
gitbay/internal/web/templates/layout.html history · blame · raw

136 lines · 10927 bytes

  1{{define "layout"}}<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4<meta charset="utf-8">
  5<meta name="viewport" content="width=device-width, initial-scale=1">
  6<title>{{template "title" .}}</title>
  7<link rel="stylesheet" href="/static/style.css">
  8<link rel="icon" href="/favicon.svg" type="image/svg+xml">
  9</head>
 10<body>
 11<a class="skip" href="#content">Skip to content</a>
 12<div class="shell">
 13
 14{{$here := ""}}{{with field . "Repo"}}{{$here = printf "%s/%s" .OwnerName .Name}}{{end}}
 15<nav class="rail" aria-label="Site">
 16  <a class="brand" href="/">{{template "mark"}}<span>{{.Site}}</span></a>
 17  <div class="railbody">
 18    <ul class="raillist">
 19      {{if .Viewer}}<li><a href="/">Dashboard</a></li>{{end}}
 20      <li><a {{if eq (str . "Tab") "explore"}}aria-current="page" {{end}}href="/explore">Explore</a></li>
 21      {{if .Viewer}}<li><a href="/new">New repository</a></li>{{end}}
 22    </ul>
 23    {{with .Rail.Pinned}}
 24    <div class="railgroup">
 25    <p class="raillabel" id="rail-pinned">Pinned</p>
 26    <ul class="raillist" aria-labelledby="rail-pinned">
 27      {{range .}}<li><a {{if eq $here (printf "%s/%s" .Owner .Name)}}aria-current="page" {{end}}href="/{{.Owner}}/{{.Name}}"><span class="owner">{{.Owner}}/</span>{{.Name}}</a></li>
 28      {{end}}
 29    </ul>
 30    </div>
 31    {{end}}
 32    {{with .Rail.Reviews}}
 33    <div class="railgroup">
 34    <p class="raillabel" id="rail-reviews">Waiting on you <b class="count">{{len .}}</b></p>
 35    <ul class="raillist wide" aria-labelledby="rail-reviews">
 36      {{range .}}<li><a href="/{{.RepoPath}}/mrs/{{.Number}}"><b>!{{.Number}} {{.Title}}</b><span class="owner">{{.RepoPath}}</span></a></li>
 37      {{end}}
 38    </ul>
 39    </div>
 40    {{end}}
 41  </div>
 42  <div class="railfoot">
 43    {{if .Viewer}}<a class="railuser" href="/{{.Viewer}}"><span class="avatar">{{initial .Viewer}}</span>{{.Viewer}}</a>
 44    <a class="railsettings" href="/settings" title="Account settings" aria-label="Account settings"><svg class="icon" width="14" height="14" viewBox="0 0 16 16" aria-hidden="true" fill="currentColor"><path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492ZM6.254 8a1.746 1.746 0 1 1 3.492 0 1.746 1.746 0 0 1-3.492 0Z"/><path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319Zm-2.153.425c.18-.613 1.048-.613 1.229 0l.093.319a2.373 2.373 0 0 0 3.416 1.416l.292-.16c.561-.306 1.175.308.87.87l-.16.292a2.373 2.373 0 0 0 1.415 3.416l.319.093c.613.18.613 1.048 0 1.229l-.319.093a2.373 2.373 0 0 0-1.416 3.416l.16.292c.305.561-.309 1.175-.87.87l-.292-.16a2.373 2.373 0 0 0-3.416 1.415l-.093.319c-.181.613-1.049.613-1.229 0l-.093-.319a2.373 2.373 0 0 0-3.416-1.416l-.292.16c-.561.305-1.175-.309-.87-.87l.16-.292a2.373 2.373 0 0 0-1.415-3.416l-.32-.093c-.612-.181-.612-1.049 0-1.229l.32-.093a2.373 2.373 0 0 0 1.416-3.416l-.16-.292c-.306-.561.308-1.175.87-.87l.292.16a2.373 2.373 0 0 0 3.416-1.416l.093-.318Z"/></svg></a>
 45    <form method="post" action="/logout"><button type="submit" class="linklike">Log out</button></form>
 46    {{else}}<a href="/login">Sign in</a>{{end}}
 47  </div>
 48</nav>
 49
 50<div class="pane">
 51{{with field . "Repo"}}
 52<header class="repohead">
 53  <div class="identity">
 54    {{if field $ "RepoHome"}}<h1 class="repotitle"><a class="owner" href="/{{.OwnerName}}">{{.OwnerName}}</a><span class="sep">/</span>{{.Name}}</h1>
 55    {{else}}<p class="repotitle"><a class="owner" href="/{{.OwnerName}}">{{.OwnerName}}</a><span class="sep">/</span><a href="/{{.OwnerName}}/{{.Name}}">{{.Name}}</a></p>{{end}}
 56    {{if eq .Visibility "private"}}<span class="chip">Private</span>{{end}}
 57    {{if .Settings.Archived}}<span class="chip">Archived</span>{{end}}
 58    <span class="grow"></span>
 59    {{if $.Viewer}}<form method="post" action="/{{.OwnerName}}/{{.Name}}/pin" class="inline"><button type="submit" class="btn" aria-pressed="{{if field $ "Pinned"}}true{{else}}false{{end}}">{{if field $ "Pinned"}}★ Pinned{{else}}☆ Pin{{end}}</button></form>{{end}}
 60  </div>
 61  {{with field $ "Desc"}}<p class="repodesc">{{.}}</p>{{end}}
 62  {{with field $ "Topics"}}<p class="topics">{{range .}}<a class="chip topic" href="/explore?q={{.}}">{{.}}</a> {{end}}</p>{{end}}
 63  {{with $.Repo.Settings.Website}}<p class="repometa"><a href="{{.}}" rel="nofollow">{{.}}</a></p>{{end}}
 64  {{range field $ "Mirrors"}}<p class="repometa">{{if eq .Direction "push"}}Mirrors to{{else}}Mirrors from{{end}} <a href="{{.URL}}" rel="nofollow">{{.Target}}</a>{{if .Error}} · <span class="bad">sync error: {{.Error}}</span>{{else if .Synced}} · synced {{.Synced}}{{end}}</p>
 65  {{end}}
 66  <nav class="tabs" aria-label="Repository">
 67    {{$top := topTab (str $ "Tab")}}
 68    <a {{if eq $top "code"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}">Code</a>
 69    <a {{if eq $top "issues"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/issues">Issues{{with field $ "OpenIssues"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a>
 70    <a {{if eq $top "mrs"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/mrs">Merge requests{{with field $ "OpenMRs"}}{{if .}} <i>{{.}}</i>{{end}}{{end}}</a>
 71    <a {{if eq $top "builds"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/builds">Builds</a>
 72    <a {{if eq $top "releases"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/releases">Releases</a>
 73    {{if field $ "HasWiki"}}<a {{if eq $top "wiki"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/wiki">Wiki</a>{{end}}
 74    {{if field $ "CanAdmin"}}<a {{if eq $top "settings"}}aria-current="page" {{end}}href="/{{.OwnerName}}/{{.Name}}/settings">Settings</a>{{end}}
 75  </nav>
 76</header>
 77{{end}}
 78
 79<main id="content" class="content">
 80{{template "content" .}}
 81</main>
 82
 83<footer>
 84  <p>Powered by <a href="https://gitbay.org/krz/gitbay">gitbay</a>{{with gitbayVersion}} · <code><a href="https://gitbay.org/krz/gitbay/commit/{{gitbayCommit}}">{{.}}</a></code>{{end}} · <a href="/privacy">Privacy</a></p>
 85</footer>
 86</div>
 87</div>
 88</body>
 89</html>{{end}}
 90
 91{{define "mark"}}<svg class="mark" width="19" height="19" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2.25 18.75 12H5.25z" fill="#ff6b3d"/><rect x="3" y="13.5" width="18" height="3" fill="currentColor"/><rect x="7.5" y="18" width="9" height="3" fill="currentColor"/></svg>{{end}}
 92
 93{{define "reporow"}}<li>
 94  <p class="reponame"><a href="/{{.OwnerName}}/{{.Name}}">{{.OwnerName}}<span class="sep">/</span><strong>{{.Name}}</strong></a>{{if eq .Visibility "private"}} <span class="chip">Private</span>{{end}}{{if .Settings.Archived}} <span class="chip">Archived</span>{{end}}</p>
 95  {{if .Desc}}<p class="desc">{{.Desc}}</p>{{end}}
 96  {{if .Topics}}<p class="topics">{{range .Topics}}<a class="chip topic" href="/explore?q={{.}}">{{.}}</a> {{end}}</p>{{end}}
 97  <p class="meta">{{template "branchicon"}} {{.DefaultBranch}}{{if .License}} · {{.License}}{{end}}{{if .Updated}} · updated {{.Updated}}{{end}}</p>
 98</li>{{end}}
 99
100{{define "refmenu"}}{{if .Branches}}<details class="refmenu">
101  <summary class="refchip">{{template "branchicon"}} {{.Ref}}</summary>
102  <div class="refdrop">
103  {{range .Branches}}<a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/{{$.RefKind}}/{{.Name}}/{{$.DirPath}}">{{.Name}}</a>
104  {{end}}<a class="allrefs" href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/refs">All refs →</a>
105  </div>
106</details>{{else}}<span class="refchip">{{template "branchicon"}} {{.Ref}}</span>{{end}}{{end}}
107
108{{define "branchicon"}}<svg class="icon" width="12" height="12" viewBox="0 0 16 16" aria-hidden="true" fill="currentColor"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628a2.25 2.25 0 0 1-1.5-2.122ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM3.5 3.25a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"/></svg>{{end}}
109
110{{define "sigbadge"}}<span class="badge badge-{{.State}}" title="{{.Fingerprint}}">{{sigLabel .State}}{{if .Signer}} · {{.Signer}}{{end}}</span>{{end}}
111
112{{define "authorname"}}{{if .User}}<a class="authorlink" href="/{{.User}}" title="{{.Email}}">{{.Name}}</a>{{else}}<span title="{{.Email}}">{{.Name}}</span>{{end}}{{end}}
113
114{{/* difffiles renders a parsed diff: one foldable section per file, with
115     line-number gutters and review threads inline. Base and Can are the
116     MR's comment endpoint and the viewer's write permission; the commit
117     page passes neither and gets the same diff without thread controls. */}}
118{{define "difffiles"}}{{$base := .Base}}{{$can := .Can}}
119{{range .Files}}<details class="difffold"{{if .Open}} open{{end}}>
120  <summary>
121    <span class="fpath">{{if eq .Status "renamed"}}<span class="was">{{.OldPath}} →</span> {{end}}{{.Path}}</span>
122    {{if ne .Status "modified"}}<span class="chip">{{.Status}}</span>{{end}}
123    <span class="fstat">{{if .Adds}}<span class="add">+{{.Adds}}</span>{{end}}{{if .Dels}} <span class="del">−{{.Dels}}</span>{{end}}</span>
124  </summary>
125  {{if .Binary}}<p class="none">Binary file not shown.</p>
126  {{else}}<div class="tablewrap"><table class="difftable">
127  {{range .Lines}}{{if eq .Class "hunk"}}<tr class="hunk"><td class="ln" colspan="2"></td><td class="code">{{.Text}}</td></tr>
128  {{else if eq .Class "meta"}}<tr class="dmeta"><td class="ln" colspan="2"></td><td class="code">{{.Text}}</td></tr>
129  {{else}}<tr class="{{.Class}}"><td class="ln">{{if .OldLine}}{{.OldLine}}{{end}}</td><td class="ln">{{if .NewLine}}{{.NewLine}}{{end}}</td><td class="code">{{if .Code}}{{.Code}}{{else}}{{.Content}}{{end}}</td></tr>
130  {{end}}{{range .Threads}}<tr class="threadrow"><td colspan="3"><div class="thread{{if .Resolved}} resolved{{end}}">{{if .Resolved}}<p class="threadstate">resolved by {{.Resolved}}</p>{{end}}{{range .Comments}}<p class="commenthead"><strong>{{.Author}}</strong> <span class="when">{{when .CreatedAt}}</span></p><div class="rendered">{{.BodyHTML}}</div>{{end}}{{template "threadact" dict "ID" .ID "Resolved" .Resolved "Base" $base "Can" $can}}</div></td></tr>
131  {{end}}{{end}}
132  </table></div>{{end}}
133</details>
134{{end}}{{end}}
135
136{{define "threadact"}}{{if .Can}}<form method="post" action="{{.Base}}/thread" class="threadact"><input type="hidden" name="thread" value="{{.ID}}"><button type="submit" name="action" value="{{if .Resolved}}unresolve{{else}}resolve{{end}}" class="linklike">{{if .Resolved}}Reopen thread{{else}}Resolve thread{{end}}</button></form>{{end}}{{end}}