tenseleyflow/shithub / 748915b

Browse files

Surface branch PR entrypoints

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
748915b69f1b9d65b69e788570930b949da6f688
Parents
50a1a7e
Tree
e13ab22

3 changed files

StatusFile+-
M internal/web/handlers/repo/code.go 33 0
M internal/web/static/css/shithub.css 70 0
M internal/web/templates/repo/tree.html 38 0
internal/web/handlers/repo/code.gomodified
@@ -4,6 +4,7 @@ package repo
44
 
55
 import (
66
 	"bytes"
7
+	"context"
78
 	"errors"
89
 	"fmt"
910
 	"html/template"
@@ -66,6 +67,17 @@ type codeContext struct {
6667
 	subpath string // path inside the ref, no leading slash
6768
 }
6869
 
70
+type codeBranchCompare struct {
71
+	Show          bool
72
+	HasRecentPush bool
73
+	Base          string
74
+	Head          string
75
+	Ahead         int
76
+	Behind        int
77
+	CompareHref   string
78
+	PullNewHref   string
79
+}
80
+
6981
 // loadCodeContext does the resolve dance for tree/blob/raw/find. On
7082
 // any failure it writes the response and returns ok=false.
7183
 func (h *Handlers) loadCodeContext(w http.ResponseWriter, r *http.Request) (*codeContext, bool) {
@@ -132,6 +144,26 @@ func (cc *codeContext) isBranchRef() bool {
132144
 	return false
133145
 }
134146
 
147
+func codeBranchCompareData(ctx context.Context, cc *codeContext) codeBranchCompare {
148
+	if !cc.isBranchRef() || cc.ref == cc.row.DefaultBranch {
149
+		return codeBranchCompare{}
150
+	}
151
+	ahead, behind, err := repogit.AheadBehind(ctx, cc.gitDir, cc.row.DefaultBranch, cc.ref)
152
+	if err != nil {
153
+		return codeBranchCompare{}
154
+	}
155
+	return codeBranchCompare{
156
+		Show:          true,
157
+		HasRecentPush: ahead > 0,
158
+		Base:          cc.row.DefaultBranch,
159
+		Head:          cc.ref,
160
+		Ahead:         ahead,
161
+		Behind:        behind,
162
+		CompareHref:   compareURL(cc.owner, cc.row.Name, cc.row.DefaultBranch, cc.ref),
163
+		PullNewHref:   pullNewURL(cc.owner, cc.row.Name, cc.row.DefaultBranch, cc.ref),
164
+	}
165
+}
166
+
135167
 func (h *Handlers) canWriteRepo(r *http.Request, row reposdb.Repo) bool {
136168
 	viewer := middleware.CurrentUserFromContext(r.Context())
137169
 	if viewer.IsAnonymous() {
@@ -219,6 +251,7 @@ func (h *Handlers) renderRepoTree(w http.ResponseWriter, r *http.Request, cc *co
219251
 		"Head":          head,
220252
 		"HeadFound":     headFound,
221253
 		"HeadAuthor":    headAuthor,
254
+		"BranchCompare": codeBranchCompareData(r.Context(), cc),
222255
 		"CommitCount":   commitCount,
223256
 		"README":        template.HTML(readme.HTML), //nolint:gosec // sanitized by mdrender
224257
 		"READMEPath":    readme.Path,
internal/web/static/css/shithub.cssmodified
@@ -7895,6 +7895,65 @@ button.shithub-repo-action {
78957895
   margin: 0;
78967896
   color: var(--fg-muted);
78977897
 }
7898
+.shithub-branch-push-banner,
7899
+.shithub-branch-compare-bar {
7900
+  display: flex;
7901
+  align-items: center;
7902
+  justify-content: space-between;
7903
+  gap: 1rem;
7904
+  margin-bottom: 0.75rem;
7905
+  padding: 0.75rem 1rem;
7906
+  border: 1px solid var(--border-default);
7907
+  border-radius: 6px;
7908
+}
7909
+.shithub-branch-push-banner {
7910
+  border-color: rgba(187, 128, 9, 0.45);
7911
+  background: rgba(187, 128, 9, 0.12);
7912
+}
7913
+.shithub-branch-push-banner > div,
7914
+.shithub-branch-compare-bar > div {
7915
+  display: flex;
7916
+  align-items: center;
7917
+  gap: 0.4rem;
7918
+  min-width: 0;
7919
+  flex-wrap: wrap;
7920
+}
7921
+.shithub-branch-compare-bar {
7922
+  background: var(--canvas-subtle);
7923
+}
7924
+.shithub-contribute-menu {
7925
+  position: relative;
7926
+  flex: 0 0 auto;
7927
+}
7928
+.shithub-contribute-menu > summary {
7929
+  list-style: none;
7930
+}
7931
+.shithub-contribute-menu > summary::-webkit-details-marker {
7932
+  display: none;
7933
+}
7934
+.shithub-contribute-menu-panel {
7935
+  position: absolute;
7936
+  z-index: 60;
7937
+  right: 0;
7938
+  top: calc(100% + 0.25rem);
7939
+  width: min(26rem, calc(100vw - 2rem));
7940
+  padding: 1rem;
7941
+  color: var(--fg-default);
7942
+  background: var(--canvas-overlay, var(--canvas-default));
7943
+  border: 1px solid var(--border-default);
7944
+  border-radius: 8px;
7945
+  box-shadow: var(--shadow-large, 0 16px 32px rgba(1, 4, 9, 0.35));
7946
+}
7947
+.shithub-contribute-menu-panel p {
7948
+  margin: 0.25rem 0 0;
7949
+  color: var(--fg-muted);
7950
+}
7951
+.shithub-contribute-actions {
7952
+  display: flex;
7953
+  justify-content: flex-end;
7954
+  gap: 0.5rem;
7955
+  margin-top: 1rem;
7956
+}
78987957
 .shithub-range-editor {
78997958
   display: flex;
79007959
   align-items: center;
@@ -8284,6 +8343,17 @@ button.shithub-repo-action {
82848343
   .shithub-pull-new-sidebar {
82858344
     order: 2;
82868345
   }
8346
+  .shithub-branch-push-banner,
8347
+  .shithub-branch-compare-bar {
8348
+    align-items: stretch;
8349
+    flex-direction: column;
8350
+  }
8351
+  .shithub-contribute-menu,
8352
+  .shithub-contribute-menu > summary,
8353
+  .shithub-branch-push-banner .shithub-button {
8354
+    width: 100%;
8355
+    justify-content: center;
8356
+  }
82878357
 }
82888358
 .shithub-settings-branches form label { display: block; margin: 0.5rem 0; }
82898359
 .shithub-settings-branches form input[type=text],
internal/web/templates/repo/tree.htmlmodified
@@ -67,6 +67,44 @@
6767
           </div>
6868
         </header>
6969
 
70
+        {{ if .BranchCompare.Show }}
71
+        {{ if and .BranchCompare.HasRecentPush .HeadFound }}
72
+        <div class="shithub-branch-push-banner">
73
+          <div>
74
+            {{ octicon "git-pull-request" }}
75
+            <strong>{{ .BranchCompare.Head }}</strong> had recent pushes <time datetime="{{ .Head.AuthorWhen.Format "2006-01-02T15:04:05Z" }}">{{ relativeTime .Head.AuthorWhen }}</time>
76
+          </div>
77
+          <a href="{{ .BranchCompare.PullNewHref }}" class="shithub-button shithub-button-primary">Compare &amp; pull request</a>
78
+        </div>
79
+        {{ end }}
80
+        <div class="shithub-branch-compare-bar">
81
+          <div>
82
+            This branch is
83
+            <a href="{{ .BranchCompare.CompareHref }}">{{ .BranchCompare.Ahead }} {{ pluralize .BranchCompare.Ahead "commit" "commits" }} ahead</a>
84
+            of and
85
+            <a href="{{ .BranchCompare.CompareHref }}">{{ .BranchCompare.Behind }} {{ pluralize .BranchCompare.Behind "commit" "commits" }} behind</a>
86
+            <code>{{ .BranchCompare.Base }}</code>.
87
+          </div>
88
+          <details class="shithub-contribute-menu">
89
+            <summary class="shithub-button">{{ octicon "git-pull-request" }} Contribute {{ octicon "triangle-down" }}</summary>
90
+            <div class="shithub-contribute-menu-panel">
91
+              <div>
92
+                <strong>This branch is {{ .BranchCompare.Ahead }} {{ pluralize .BranchCompare.Ahead "commit" "commits" }} ahead of <code>{{ .BranchCompare.Base }}</code>.</strong>
93
+                <p>Open a pull request to contribute your changes upstream.</p>
94
+              </div>
95
+              <div class="shithub-contribute-actions">
96
+                <a href="{{ .BranchCompare.CompareHref }}" class="shithub-button">Compare</a>
97
+                {{ if gt .BranchCompare.Ahead 0 }}
98
+                <a href="{{ .BranchCompare.PullNewHref }}" class="shithub-button shithub-button-primary">Open pull request</a>
99
+                {{ else }}
100
+                <button type="button" class="shithub-button shithub-button-primary" disabled>Open pull request</button>
101
+                {{ end }}
102
+              </div>
103
+            </div>
104
+          </details>
105
+        </div>
106
+        {{ end }}
107
+
70108
         {{ if .Path }}
71109
         <nav class="shithub-code-crumbs" aria-label="Breadcrumb">
72110
           {{ range $i, $c := .Crumbs }}