tenseleyflow/shithub / 2a32492

Browse files

S22: pulls list/new/view templates + CSS

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
2a32492eb3369d047b84c8148112b6ede441c979
Parents
fd99b56
Tree
f326f1f

4 changed files

StatusFile+-
M internal/web/static/css/shithub.css 43 0
A internal/web/templates/repo/pull_new.html 46 0
A internal/web/templates/repo/pull_view.html 128 0
A internal/web/templates/repo/pulls_list.html 52 0
internal/web/static/css/shithub.cssmodified
@@ -1263,3 +1263,46 @@ code {
12631263
 .shithub-button-danger { color: #cf222e; }
12641264
 .shithub-error { padding: 0.75rem; background: #ffebe9; border: 1px solid #ffcecb; border-radius: 6px; color: #82061e; margin-bottom: 1rem; }
12651265
 .shithub-muted { color: var(--fg-muted); }
1266
+
1267
+/* ========== Pull Requests (S22) ========== */
1268
+.shithub-pulls, .shithub-pull-view {
1269
+  max-width: 64rem;
1270
+  margin: 1.5rem auto;
1271
+  padding: 0 1rem;
1272
+}
1273
+.shithub-pull-head { margin-bottom: 0.75rem; }
1274
+.shithub-pull-merged { background: #8250df22; color: #8250df; }
1275
+.shithub-pull-tabs {
1276
+  display: flex; gap: 1.5rem;
1277
+  border-bottom: 1px solid var(--border-default);
1278
+  margin: 0.75rem 0 1rem;
1279
+}
1280
+.shithub-pull-tab {
1281
+  color: var(--fg-muted);
1282
+  padding: 0.4rem 0;
1283
+  border-bottom: 2px solid transparent;
1284
+}
1285
+.shithub-pull-tab-active {
1286
+  color: var(--fg-default);
1287
+  border-bottom-color: var(--accent-emphasis, #0969da);
1288
+  font-weight: 600;
1289
+}
1290
+.shithub-pull-grid { display: grid; grid-template-columns: 1fr 16rem; gap: 1.5rem; }
1291
+@media (max-width: 768px) { .shithub-pull-grid { grid-template-columns: 1fr; } }
1292
+.shithub-pull-merge { padding: 0.75rem; border: 1px solid var(--border-default); border-radius: 6px; }
1293
+.shithub-pull-merge h3 { font-size: 0.85rem; text-transform: uppercase; color: var(--fg-muted); margin: 0 0 0.5rem; }
1294
+.shithub-pull-state-clean { color: #1a7f37; font-weight: 600; }
1295
+.shithub-pull-state-dirty { color: #cf222e; font-weight: 600; }
1296
+.shithub-pull-state-behind { color: #9a6700; }
1297
+.shithub-pull-state-unknown { color: var(--fg-muted); }
1298
+.shithub-pull-merge-form { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.5rem; }
1299
+.shithub-pull-merge-form select { padding: 0.4rem; border: 1px solid var(--border-default); border-radius: 6px; font: inherit; }
1300
+.shithub-pull-state-form { margin-top: 0.5rem; }
1301
+.shithub-pull-refs { display: flex; gap: 0.4rem; align-items: flex-end; }
1302
+.shithub-pull-refs label { flex: 1; }
1303
+.shithub-pull-arrow { font-size: 1.4rem; padding: 0 0.4rem; align-self: center; }
1304
+.shithub-pull-commits { list-style: none; padding: 0; }
1305
+.shithub-pull-commits li {
1306
+  padding: 0.4rem 0; border-bottom: 1px solid var(--border-default);
1307
+  display: flex; gap: 0.6rem; align-items: baseline;
1308
+}
internal/web/templates/repo/pull_new.htmladded
@@ -0,0 +1,46 @@
1
+{{ define "page" -}}
2
+<section class="shithub-issue-new">
3
+  <header class="shithub-issues-head">
4
+    <h1>
5
+      <a href="/{{ .Owner }}/{{ .Repo.Name }}">{{ .Owner }}/{{ .Repo.Name }}</a>
6
+      <span class="shithub-code-sep">/</span>
7
+      <a href="/{{ .Owner }}/{{ .Repo.Name }}/pulls">Pull requests</a>
8
+      <span class="shithub-code-sep">/</span>
9
+      New
10
+    </h1>
11
+  </header>
12
+
13
+  {{ if .Error }}<div class="shithub-error" role="alert">{{ .Error }}</div>{{ end }}
14
+
15
+  <form method="post" action="/{{ .Owner }}/{{ .Repo.Name }}/pulls" class="shithub-issue-form">
16
+    <input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
17
+    <div class="shithub-form-row shithub-pull-refs">
18
+      <label>
19
+        <span>Base</span>
20
+        <input type="text" name="base" value="{{ .Base }}" required>
21
+      </label>
22
+      <span class="shithub-pull-arrow">←</span>
23
+      <label>
24
+        <span>Head</span>
25
+        <input type="text" name="head" value="{{ .Head }}" required>
26
+      </label>
27
+    </div>
28
+    <label class="shithub-form-row">
29
+      <span>Title</span>
30
+      <input type="text" name="title" maxlength="256" required value="{{ .FormTitle }}" autofocus>
31
+    </label>
32
+    <label class="shithub-form-row">
33
+      <span>Body (Markdown)</span>
34
+      <textarea name="body" rows="14" maxlength="65535">{{ .FormBody }}</textarea>
35
+    </label>
36
+    <label class="shithub-form-row">
37
+      <input type="checkbox" name="draft" value="on">
38
+      Open as draft
39
+    </label>
40
+    <div class="shithub-form-actions">
41
+      <a href="/{{ .Owner }}/{{ .Repo.Name }}/pulls" class="shithub-button">Cancel</a>
42
+      <button type="submit" class="shithub-button shithub-button-primary">Create pull request</button>
43
+    </div>
44
+  </form>
45
+</section>
46
+{{- end }}
internal/web/templates/repo/pull_view.htmladded
@@ -0,0 +1,128 @@
1
+{{ define "page" -}}
2
+<section class="shithub-pull-view">
3
+  <header class="shithub-pull-head">
4
+    <h1>
5
+      <span>{{ .PR.ITitle }}</span>
6
+      <span class="shithub-issue-num">#{{ .PR.INumber }}</span>
7
+    </h1>
8
+    <div class="shithub-issue-meta">
9
+      {{ if .PR.MergedAt.Valid }}
10
+        <span class="shithub-pill shithub-pull-merged">⏵ Merged</span>
11
+      {{ else if eq (printf "%s" .PR.IState) "open" }}
12
+        <span class="shithub-pill shithub-issues-state-open">{{ if .PR.Draft }}◔ Draft{{ else }}● Open{{ end }}</span>
13
+      {{ else }}
14
+        <span class="shithub-pill shithub-issues-state-closed">✗ Closed</span>
15
+      {{ end }}
16
+      {{ if .AuthorName }}<a href="/{{ .AuthorName }}">{{ .AuthorName }}</a>{{ end }}
17
+      wants to merge <code>{{ .PR.HeadRef }}</code> into <code>{{ .PR.BaseRef }}</code>
18
+    </div>
19
+  </header>
20
+
21
+  <nav class="shithub-pull-tabs">
22
+    <a class="shithub-pull-tab {{ if eq .Tab "conversation" }}shithub-pull-tab-active{{ end }}"
23
+       href="/{{ .Owner }}/{{ .Repo.Name }}/pulls/{{ .PR.INumber }}">Conversation</a>
24
+    <a class="shithub-pull-tab {{ if eq .Tab "commits" }}shithub-pull-tab-active{{ end }}"
25
+       href="/{{ .Owner }}/{{ .Repo.Name }}/pulls/{{ .PR.INumber }}/commits">Commits</a>
26
+    <a class="shithub-pull-tab {{ if eq .Tab "files" }}shithub-pull-tab-active{{ end }}"
27
+       href="/{{ .Owner }}/{{ .Repo.Name }}/pulls/{{ .PR.INumber }}/files">Files changed</a>
28
+    <a class="shithub-pull-tab {{ if eq .Tab "checks" }}shithub-pull-tab-active{{ end }}"
29
+       href="/{{ .Owner }}/{{ .Repo.Name }}/pulls/{{ .PR.INumber }}/checks">Checks</a>
30
+  </nav>
31
+
32
+  {{ if eq .Tab "conversation" }}
33
+    <div class="shithub-pull-grid">
34
+      <article class="shithub-issue-thread">
35
+        <div class="shithub-comment">
36
+          <div class="shithub-comment-head">
37
+            {{ if .AuthorName }}<a href="/{{ .AuthorName }}">{{ .AuthorName }}</a>{{ end }}
38
+            <time datetime="{{ .PR.ICreatedAt.Time.Format "2006-01-02T15:04:05Z" }}">{{ relativeTime .PR.ICreatedAt.Time }}</time>
39
+          </div>
40
+          <div class="shithub-comment-body markdown-body">
41
+            {{ if .PR.IBodyHtmlCached.Valid }}{{ safeHTML .PR.IBodyHtmlCached.String }}{{ else }}<p>{{ .PR.IBody }}</p>{{ end }}
42
+          </div>
43
+        </div>
44
+        {{ range .Comments }}
45
+        <div class="shithub-comment">
46
+          <div class="shithub-comment-head">
47
+            {{ if .AuthorName }}<a href="/{{ .AuthorName }}">{{ .AuthorName }}</a>{{ end }}
48
+            commented
49
+            <time datetime="{{ .C.CreatedAt.Time.Format "2006-01-02T15:04:05Z" }}">{{ relativeTime .C.CreatedAt.Time }}</time>
50
+          </div>
51
+          <div class="shithub-comment-body markdown-body">
52
+            {{ if .C.BodyHtmlCached.Valid }}{{ safeHTML .C.BodyHtmlCached.String }}{{ else }}<p>{{ .C.Body }}</p>{{ end }}
53
+          </div>
54
+        </div>
55
+        {{ end }}
56
+        {{ range .Events }}
57
+        <div class="shithub-event">
58
+          <span class="shithub-event-kind">{{ .Kind }}</span>
59
+          <time datetime="{{ .CreatedAt.Time.Format "2006-01-02T15:04:05Z" }}">{{ relativeTime .CreatedAt.Time }}</time>
60
+        </div>
61
+        {{ end }}
62
+      </article>
63
+
64
+      <aside class="shithub-pull-merge">
65
+        {{ if .PR.MergedAt.Valid }}
66
+          <p>Merged via <code>{{ printf "%s" .PR.MergeMethod.PrMergeMethod }}</code>.</p>
67
+        {{ else if eq (printf "%s" .PR.IState) "closed" }}
68
+          <p>This PR is closed without being merged.</p>
69
+        {{ else }}
70
+          <h3>Mergeability</h3>
71
+          <p class="shithub-pull-state-{{ printf "%s" .PR.MergeableState }}">
72
+            {{ printf "%s" .PR.MergeableState }}
73
+          </p>
74
+          {{ if .Viewer.ID }}
75
+            {{ if eq (printf "%s" .PR.MergeableState) "clean" }}
76
+              <form method="post" action="/{{ .Owner }}/{{ .Repo.Name }}/pulls/{{ .PR.INumber }}/merge" class="shithub-pull-merge-form">
77
+                <input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
78
+                <select name="method">
79
+                  {{ if .Repo.AllowMergeCommit }}<option value="merge" {{ if eq (printf "%s" .Repo.DefaultMergeMethod) "merge" }}selected{{ end }}>Merge commit</option>{{ end }}
80
+                  {{ if .Repo.AllowSquashMerge }}<option value="squash" {{ if eq (printf "%s" .Repo.DefaultMergeMethod) "squash" }}selected{{ end }}>Squash and merge</option>{{ end }}
81
+                  {{ if .Repo.AllowRebaseMerge }}<option value="rebase" {{ if eq (printf "%s" .Repo.DefaultMergeMethod) "rebase" }}selected{{ end }}>Rebase and merge</option>{{ end }}
82
+                </select>
83
+                <button type="submit" class="shithub-button shithub-button-primary">Merge pull request</button>
84
+              </form>
85
+            {{ else if eq (printf "%s" .PR.MergeableState) "dirty" }}
86
+              <p class="shithub-error">This branch has conflicts that must be resolved manually.</p>
87
+            {{ else if eq (printf "%s" .PR.MergeableState) "behind" }}
88
+              <p class="shithub-muted">Head has no commits ahead of base.</p>
89
+            {{ else }}
90
+              <p class="shithub-muted">Mergeability is being computed…</p>
91
+            {{ end }}
92
+            <form method="post" action="/{{ .Owner }}/{{ .Repo.Name }}/pulls/{{ .PR.INumber }}/state" class="shithub-pull-state-form">
93
+              <input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
94
+              <button type="submit" name="state" value="closed" class="shithub-button">Close pull request</button>
95
+            </form>
96
+            {{ if .PR.Draft }}
97
+              <form method="post" action="/{{ .Owner }}/{{ .Repo.Name }}/pulls/{{ .PR.INumber }}/ready">
98
+                <input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
99
+                <button type="submit" class="shithub-button">Ready for review</button>
100
+              </form>
101
+            {{ end }}
102
+          {{ end }}
103
+        {{ end }}
104
+      </aside>
105
+    </div>
106
+  {{ else if eq .Tab "commits" }}
107
+    <ul class="shithub-pull-commits">
108
+      {{ range .Commits }}
109
+      <li>
110
+        <a href="/{{ $.Owner }}/{{ $.Repo.Name }}/commit/{{ .Sha }}"><code>{{ slice .Sha 0 7 }}</code></a>
111
+        {{ .Subject }}
112
+        <small>by {{ .AuthorName }}</small>
113
+      </li>
114
+      {{ else }}
115
+      <li class="shithub-muted">No commits.</li>
116
+      {{ end }}
117
+    </ul>
118
+  {{ else if eq .Tab "files" }}
119
+    {{ if .DiffHTML }}
120
+      <div class="shithub-diff">{{ safeHTML .DiffHTML }}</div>
121
+    {{ else }}
122
+      <p class="shithub-muted">No diff available.</p>
123
+    {{ end }}
124
+  {{ else if eq .Tab "checks" }}
125
+    <p class="shithub-muted">Check engine ships in S24. Today this tab is a placeholder.</p>
126
+  {{ end }}
127
+</section>
128
+{{- end }}
internal/web/templates/repo/pulls_list.htmladded
@@ -0,0 +1,52 @@
1
+{{ define "page" -}}
2
+<section class="shithub-pulls">
3
+  <header class="shithub-issues-head">
4
+    <h1>
5
+      <a href="/{{ .Owner }}/{{ .Repo.Name }}">{{ .Owner }}/{{ .Repo.Name }}</a>
6
+      <span class="shithub-code-sep">/</span>
7
+      Pull requests
8
+    </h1>
9
+    <div class="shithub-issues-actions">
10
+      <a href="/{{ .Owner }}/{{ .Repo.Name }}/compare/{{ .Repo.DefaultBranch }}...{{ .Repo.DefaultBranch }}" class="shithub-button shithub-button-primary">New pull request</a>
11
+    </div>
12
+  </header>
13
+
14
+  <nav class="shithub-issues-filter">
15
+    <a href="?state=open" class="shithub-issues-tab {{ if eq .State "open" }}shithub-issues-tab-active{{ end }}">
16
+      <span class="shithub-issues-dot shithub-issues-dot-open"></span>
17
+      {{ .OpenCount }} Open
18
+    </a>
19
+    <a href="?state=closed" class="shithub-issues-tab {{ if eq .State "closed" }}shithub-issues-tab-active{{ end }}">
20
+      <span class="shithub-issues-dot shithub-issues-dot-closed"></span>
21
+      {{ .ClosedCount }} Closed
22
+    </a>
23
+  </nav>
24
+
25
+  {{ if .Items }}
26
+  <ul class="shithub-issues-list">
27
+    {{ range .Items }}
28
+    <li class="shithub-issues-row">
29
+      <span class="shithub-issues-state shithub-issues-state-{{ printf "%s" .Row.State }}">
30
+        {{ if .Row.MergedAt.Valid }}⏵{{ else if eq (printf "%s" .Row.State) "open" }}{{ if .Row.Draft }}◔{{ else }}●{{ end }}{{ else }}✗{{ end }}
31
+      </span>
32
+      <div class="shithub-issues-body">
33
+        <a class="shithub-issues-title" href="/{{ $.Owner }}/{{ $.Repo.Name }}/pulls/{{ .Row.Number }}">
34
+          {{ .Row.Title }}
35
+        </a>
36
+        {{ if .Row.Draft }}<span class="shithub-pill">Draft</span>{{ end }}
37
+        <div class="shithub-issues-meta">
38
+          #{{ .Row.Number }}
39
+          <code>{{ .Row.HeadRef }}</code> → <code>{{ .Row.BaseRef }}</code>
40
+          opened
41
+          <time datetime="{{ .Row.CreatedAt.Time.Format "2006-01-02T15:04:05Z" }}">{{ relativeTime .Row.CreatedAt.Time }}</time>
42
+          {{ if .AuthorName }}by <a href="/{{ .AuthorName }}">{{ .AuthorName }}</a>{{ end }}
43
+        </div>
44
+      </div>
45
+    </li>
46
+    {{ end }}
47
+  </ul>
48
+  {{ else }}
49
+  <p class="shithub-issues-empty">No {{ .State }} pull requests.</p>
50
+  {{ end }}
51
+</section>
52
+{{- end }}