Enhance registration and repository templates for improved UI and UX
DDavid committed on 2026-06-28 22:43 commit 88d9834
internal/interface/web/presenter/render.go +1 −1
package presenter
import (
"bytes"
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/alecthomas/chroma/v2/styles"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
)
var md = goldmark.New(goldmark.WithExtensions(extension.GFM))
// RenderMarkdown converts markdown to HTML. Raw HTML in the source is escaped
// (goldmark's default, no WithUnsafe), which keeps user content safe.
func RenderMarkdown(src []byte) string {
var buf bytes.Buffer
if err := md.Convert(src, &buf); err != nil {
return "<pre>" + string(src) + "</pre>"
}
return buf.String()
}
var (
- highlightStyle = styles.Get("github")
+ highlightStyle = styles.Get("github-dark")
highlightFormatter = chromahtml.New(chromahtml.WithClasses(false), chromahtml.WithLineNumbers(true))
)
// Highlight renders source code as highlighted HTML, choosing a lexer by filename.
func Highlight(code, filename string) string {
lexer := lexers.Match(filename)
if lexer == nil {
lexer = lexers.Analyse(code)
}
if lexer == nil {
lexer = lexers.Fallback
}
iterator, err := lexer.Tokenise(nil, code)
if err != nil {
return "<pre>" + code + "</pre>"
}
var buf bytes.Buffer
if err := highlightFormatter.Format(&buf, highlightStyle, iterator); err != nil {
return "<pre>" + code + "</pre>"
}
return buf.String()
}
internal/interface/web/templates/browse_blob.templ +14 −10
package templates
import "gitgud/internal/domain"
templ BrowseBlob(user *domain.User, repo *domain.Repository, ref string, blob *domain.FileBlob, highlighted string) {
@Layout(blob.Path+" · gitgud", user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "code")
- <div class="flex items-center justify-between mb-2">
- <div class="text-sm font-mono">{ blob.Path }</div>
- <div class="flex gap-3 text-sm">
- <span class="text-gray-500">{ humanSize(blob.Size) }</span>
- <a href={ templ.SafeURL(repoPath(repo, "/raw/"+ref+"/"+blob.Path)) }>Raw</a>
- </div>
+ @repoHeader(repo, "code")
+ <div class="mb-3 flex items-center gap-2 font-mono text-sm">
+ <span class="inline-flex items-center gap-2 rounded-md border border-line2 bg-panel2 px-2.5 py-1 text-xs text-ink">
+ <span class="inline-block size-2 rounded-full border-[1.5px] border-accent"></span>{ ref }
+ </span>
+ <span class="text-faint">/</span>
+ <span class="text-accent">{ blob.Path }</span>
+ </div>
+ <div class="card overflow-hidden">
+ <div class="flex items-center justify-between border-b border-line bg-[#0e1410] px-4 py-2.5 font-mono text-xs text-muted">
+ <span>{ humanSize(blob.Size) } · <span class="text-accent">{ langLabel(blob.Path) }</span></span>
+ <a class="rounded border border-line2 px-2.5 py-1 text-ink transition hover:border-faint hover:bg-panel2" href={ templ.SafeURL(repoPath(repo, "/raw/"+ref+"/"+blob.Path)) }>Raw</a>
</div>
if blob.IsBinary {
- <div class="border p-4 text-gray-500">Binary file not shown.</div>
+ <div class="px-4 py-10 text-center text-sm text-faint">Binary file not shown.</div>
} else {
- <div class="border overflow-x-auto text-sm">
+ <div class="overflow-x-auto bg-[#0a0e0b] text-xs leading-relaxed [&_pre]:!bg-transparent">
@templ.Raw(highlighted)
</div>
}
</div>
}
}
internal/interface/web/templates/browse_blob_templ.go +40 −18
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func BrowseBlob(user *domain.User, repo *domain.Repository, ref string, blob *domain.FileBlob, highlighted string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "code").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex items-center justify-between mb-2\"><div class=\"text-sm font-mono\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mb-3 flex items-center gap-2 font-mono text-sm\"><span class=\"inline-flex items-center gap-2 rounded-md border border-line2 bg-panel2 px-2.5 py-1 text-xs text-ink\"><span class=\"inline-block size-2 rounded-full border-[1.5px] border-accent\"></span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(blob.Path)
+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(ref)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 10, Col: 46}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 10, Col: 92}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div><div class=\"flex gap-3 text-sm\"><span class=\"text-gray-500\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"text-faint\">/</span> <span class=\"text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(humanSize(blob.Size))
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(blob.Path)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 12, Col: 55}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 13, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</span> <a href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"card overflow-hidden\"><div class=\"flex items-center justify-between border-b border-line bg-[#0e1410] px-4 py-2.5 font-mono text-xs text-muted\"><span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(repoPath(repo, "/raw/"+ref+"/"+blob.Path))
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
+ var templ_7745c5c3_Var5 string
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(humanSize(blob.Size))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 17, Col: 32}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">Raw</a></div></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " · <span class=\"text-accent\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var6 string
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(langLabel(blob.Path))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 17, Col: 86}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</span></span> <a class=\"rounded border border-line2 px-2.5 py-1 text-ink transition hover:border-faint hover:bg-panel2\" href=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(repoPath(repo, "/raw/"+ref+"/"+blob.Path))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">Raw</a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if blob.IsBinary {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"border p-4 text-gray-500\">Binary file not shown.</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"px-4 py-10 text-center text-sm text-faint\">Binary file not shown.</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"border overflow-x-auto text-sm\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"overflow-x-auto bg-[#0a0e0b] text-xs leading-relaxed [&_pre]:!bg-transparent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.Raw(highlighted).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(blob.Path+" · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/browse_tree.templ +33 −25
package templates
import "gitgud/internal/domain"
templ BrowseTree(user *domain.User, repo *domain.Repository, ref, path string, branches []string, entries []domain.TreeEntry, readme string) {
@Layout(repo.OwnerName+"/"+repo.Name+" · gitgud", user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "code")
- <div class="flex items-center justify-between mb-3">
+ @repoHeader(repo, "code")
+ <div class="mb-3 flex items-center justify-between gap-3">
+ <div class="flex items-center gap-3">
@branchSwitcher(repo, ref, branches)
- <a class="text-sm" href={ templ.SafeURL(repoPath(repo, "/commits/"+ref)) }>Commits</a>
- </div>
- <div class="text-sm mb-2">
- for i, c := range treeCrumbs(repo, ref, path) {
- if i > 0 {
- <span class="text-gray-400"> / </span>
+ <div class="font-mono text-sm">
+ for i, c := range treeCrumbs(repo, ref, path) {
+ if i > 0 {
+ <span class="text-faint"> / </span>
+ }
+ <a class="link" href={ templ.SafeURL(c.Href) }>{ c.Name }</a>
}
- <a href={ templ.SafeURL(c.Href) }>{ c.Name }</a>
- }
+ </div>
</div>
- <table class="w-full border mb-6 text-sm">
+ <a class="meta hover:text-ink" href={ templ.SafeURL(repoPath(repo, "/commits/"+ref)) }>Commits →</a>
+ </div>
+ <div class="card overflow-hidden">
+ <table class="w-full text-sm">
<tbody>
for _, e := range entries {
- <tr class="border-b">
- <td class="px-2 py-1">
- if e.IsDir {
- <span>📁</span>
- } else {
- <span>📄</span>
- }
- <a href={ templ.SafeURL(entryHref(repo, ref, e)) }>{ e.Name }</a>
+ <tr class="row border-b border-line last:border-0">
+ <td class="px-4 py-2.5">
+ <a class="flex items-center gap-2.5" href={ templ.SafeURL(entryHref(repo, ref, e)) }>
+ if e.IsDir {
+ <span class="text-accent">▸</span>
+ <span class="font-mono text-ink">{ e.Name }</span>
+ } else {
+ <span class="text-faint">·</span>
+ <span class="font-mono text-muted">{ e.Name }</span>
+ }
+ </a>
</td>
- <td class="px-2 py-1 text-right text-gray-500">
+ <td class="px-4 py-2.5 text-right font-mono text-xs text-faint">
if !e.IsDir {
{ humanSize(e.Size) }
}
</td>
</tr>
}
</tbody>
</table>
- if readme != "" {
- <div class="border p-4">
+ </div>
+ if readme != "" {
+ <div class="card mt-6 overflow-hidden">
+ <div class="border-b border-line px-5 py-2.5 font-mono text-xs text-muted">README.md</div>
+ <div class="prose-dark px-5 py-4">
@templ.Raw(readme)
</div>
- }
- </div>
+ </div>
+ }
}
}
internal/interface/web/templates/browse_tree_templ.go +68 −63
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func BrowseTree(user *domain.User, repo *domain.Repository, ref, path string, branches []string, entries []domain.TreeEntry, readme string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "code").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex items-center justify-between mb-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mb-3 flex items-center justify-between gap-3\"><div class=\"flex items-center gap-3\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = branchSwitcher(repo, ref, branches).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a class=\"text-sm\" href=\"")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL(repoPath(repo, "/commits/"+ref))
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">Commits</a></div><div class=\"text-sm mb-2\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"font-mono text-sm\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for i, c := range treeCrumbs(repo, ref, path) {
if i > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<span class=\"text-gray-400\">/ </span>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<span class=\"text-faint\">/ </span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " <a href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " <a class=\"link\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(c.Href)
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
+ var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL(c.Href)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var5 string
- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(c.Name)
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(c.Name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_tree.templ`, Line: 18, Col: 47}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_tree.templ`, Line: 16, Col: 61}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</a>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div><table class=\"w-full border mb-6 text-sm\"><tbody>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></div><a class=\"meta hover:text-ink\" href=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(repoPath(repo, "/commits/"+ref))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">Commits →</a></div><div class=\"card overflow-hidden\"><table class=\"w-full text-sm\"><tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, e := range entries {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<tr class=\"border-b\"><td class=\"px-2 py-1\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<tr class=\"row border-b border-line last:border-0\"><td class=\"px-4 py-2.5\"><a class=\"flex items-center gap-2.5\" href=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(entryHref(repo, ref, e))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if e.IsDir {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<span>📁</span> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<span class=\"text-accent\">▸</span> <span class=\"font-mono text-ink\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var7 string
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(e.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_tree.templ`, Line: 31, Col: 51}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<span>📄</span> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<span class=\"text-faint\">·</span> <span class=\"font-mono text-muted\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(e.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_tree.templ`, Line: 34, Col: 53}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<a href=\"")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
}
- var templ_7745c5c3_Var6 templ.SafeURL = templ.SafeURL(entryHref(repo, ref, e))
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(e.Name)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_tree.templ`, Line: 31, Col: 67}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</a></td><td class=\"px-2 py-1 text-right text-gray-500\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</a></td><td class=\"px-4 py-2.5 text-right font-mono text-xs text-faint\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !e.IsDir {
- var templ_7745c5c3_Var8 string
- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(humanSize(e.Size))
+ var templ_7745c5c3_Var9 string
+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(humanSize(e.Size))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_tree.templ`, Line: 35, Col: 28}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_tree.templ`, Line: 40, Col: 28}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</tbody></table>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</tbody></table></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if readme != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<div class=\"border p-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<div class=\"card mt-6 overflow-hidden\"><div class=\"border-b border-line px-5 py-2.5 font-mono text-xs text-muted\">README.md</div><div class=\"prose-dark px-5 py-4\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.Raw(readme).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(repo.OwnerName+"/"+repo.Name+" · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/commit_detail.templ +11 −21
package templates
import "gitgud/internal/domain"
templ CommitDetail(user *domain.User, repo *domain.Repository, commit *domain.Commit, diffs []domain.FileDiff) {
@Layout("Commit "+commit.ShortHash+" · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "code")
- <div class="border p-3 mb-4">
- <div class="font-medium">{ firstLine(commit.Message) }</div>
- <div class="text-xs text-gray-500">{ commit.Author } · <code>{ commit.Hash }</code></div>
+ @repoHeader(repo, "code")
+ <div class="card mb-5 overflow-hidden">
+ <div class="border-b border-line px-4 py-3">
+ <div class="text-base font-semibold text-ink">{ firstLine(commit.Message) }</div>
</div>
- for _, d := range diffs {
- <div class="border mb-4">
- <div class="bg-gray-100 px-3 py-1 text-sm flex justify-between">
- <span class="font-mono">{ d.Path }</span>
- <span class="text-xs">
- <span class="text-green-700">+{ itoa(d.Added) }</span>
- <span class="text-red-700">-{ itoa(d.Deleted) }</span>
- </span>
- </div>
- <div class="font-mono text-xs overflow-x-auto">
- for _, line := range diffLines(d.Patch) {
- <div class={ "whitespace-pre px-3 " + diffLineClass(line) }>{ line }</div>
- }
- </div>
- </div>
- }
+ <div class="flex items-center gap-2.5 px-4 py-3 text-xs text-muted">
+ @avatar(commit.Author, "size-5")
+ <span class="font-medium text-ink">{ commit.Author }</span>
+ <span>committed on { fmtTime(commit.When) }</span>
+ <span class="ml-auto font-mono text-faint">commit <span class="text-accent">{ commit.ShortHash }</span></span>
+ </div>
</div>
+ @diffFiles(diffs)
}
}
internal/interface/web/templates/commit_detail_templ.go +29 −98
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func CommitDetail(user *domain.User, repo *domain.Repository, commit *domain.Commit, diffs []domain.FileDiff) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "code").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"border p-3 mb-4\"><div class=\"font-medium\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"card mb-5 overflow-hidden\"><div class=\"border-b border-line px-4 py-3\"><div class=\"text-base font-semibold text-ink\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(firstLine(commit.Message))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 10, Col: 56}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 10, Col: 77}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div><div class=\"text-xs text-gray-500\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div></div><div class=\"flex items-center gap-2.5 px-4 py-3 text-xs text-muted\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = avatar(commit.Author, "size-5").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<span class=\"font-medium text-ink\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Author)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 11, Col: 54}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 14, Col: 54}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " · <code>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</span> <span>committed on ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(commit.Hash)
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmtTime(commit.When))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 11, Col: 79}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 15, Col: 45}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</code></div></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</span> <span class=\"ml-auto font-mono text-faint\">commit <span class=\"text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- for _, d := range diffs {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"border mb-4\"><div class=\"bg-gray-100 px-3 py-1 text-sm flex justify-between\"><span class=\"font-mono\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var6 string
- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(d.Path)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 16, Col: 38}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</span> <span class=\"text-xs\"><span class=\"text-green-700\">+")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(d.Added))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 18, Col: 52}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</span> <span class=\"text-red-700\">-")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var8 string
- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(d.Deleted))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 19, Col: 52}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</span></span></div><div class=\"font-mono text-xs overflow-x-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, line := range diffLines(d.Patch) {
- var templ_7745c5c3_Var9 = []any{"whitespace-pre px-3 " + diffLineClass(line)}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var10 string
- templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var9).String())
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 1, Col: 0}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var11 string
- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(line)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 24, Col: 73}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
+ var templ_7745c5c3_Var6 string
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(commit.ShortHash)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commit_detail.templ`, Line: 16, Col: 98}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</span></span></div></div>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div>")
+ templ_7745c5c3_Err = diffFiles(diffs).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Commit "+commit.ShortHash+" · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/commits.templ +15 −14
package templates
import "gitgud/internal/domain"
templ Commits(user *domain.User, repo *domain.Repository, ref string, commits []domain.Commit) {
@Layout("Commits · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "code")
- <h2 class="text-lg mb-3">Commits on { ref }</h2>
- <ul class="border">
- for _, c := range commits {
- <li class="border-b px-3 py-2 flex items-center justify-between">
- <div>
- <a class="block" href={ templ.SafeURL(repoPath(repo, "/commit/"+c.Hash)) }>{ firstLine(c.Message) }</a>
- <span class="text-xs text-gray-500">{ c.Author }</span>
- </div>
- <code class="text-xs">{ c.ShortHash }</code>
- </li>
- }
- </ul>
+ @repoHeader(repo, "code")
+ <div class="mb-4 flex items-center gap-2 text-sm">
+ <span class="text-muted">Commits on</span>
+ <span class="badge font-mono">{ ref }</span>
+ </div>
+ <div class="card overflow-hidden">
+ for _, c := range commits {
+ <div class="row flex items-center justify-between border-b border-line px-4 py-3 last:border-0">
+ <div class="min-w-0">
+ <a class="block truncate text-ink hover:text-accent" href={ templ.SafeURL(repoPath(repo, "/commit/"+c.Hash)) }>{ firstLine(c.Message) }</a>
+ <div class="meta mt-0.5">{ c.Author } · { fmtTime(c.When) }</div>
+ </div>
+ <a class="ml-4 shrink-0 rounded-md border border-line2 bg-panel2 px-2 py-1 font-mono text-xs text-muted hover:text-ink" href={ templ.SafeURL(repoPath(repo, "/commit/"+c.Hash)) }>{ c.ShortHash }</a>
+ </div>
+ }
</div>
}
}
internal/interface/web/templates/commits_templ.go +35 −17
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Commits(user *domain.User, repo *domain.Repository, ref string, commits []domain.Commit) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "code").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h2 class=\"text-lg mb-3\">Commits on ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mb-4 flex items-center gap-2 text-sm\"><span class=\"text-muted\">Commits on</span> <span class=\"badge font-mono\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(ref)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 9, Col: 44}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 10, Col: 38}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h2><ul class=\"border\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span></div><div class=\"card overflow-hidden\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, c := range commits {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<li class=\"border-b px-3 py-2 flex items-center justify-between\"><div><a class=\"block\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"row flex items-center justify-between border-b border-line px-4 py-3 last:border-0\"><div class=\"min-w-0\"><a class=\"block truncate text-ink hover:text-accent\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(repoPath(repo, "/commit/"+c.Hash))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(firstLine(c.Message))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 14, Col: 104}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 16, Col: 139}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a> <span class=\"text-xs text-gray-500\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</a><div class=\"meta mt-0.5\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(c.Author)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 15, Col: 53}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 17, Col: 41}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</span></div><code class=\"text-xs\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " · ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(c.ShortHash)
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmtTime(c.When))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 17, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 17, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</code></li>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></div><a class=\"ml-4 shrink-0 rounded-md border border-line2 bg-panel2 px-2 py-1 font-mono text-xs text-muted hover:text-ink\" href=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(repoPath(repo, "/commit/"+c.Hash))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var9 string
+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(c.ShortHash)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/commits.templ`, Line: 19, Col: 196}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</ul></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Commits · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/compare.templ +36 −30
package templates
import "gitgud/internal/domain"
templ Compare(user *domain.User, repo *domain.Repository, base, head string, branches []string, cmp *domain.Comparison, errMsg string) {
@Layout("Compare · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "pulls")
- <h2 class="text-lg mb-3">Compare changes</h2>
- if errMsg != "" {
- <p class="text-red-600 mb-3">{ errMsg }</p>
- }
- <form method="get" action={ templ.SafeURL(repoPath(repo, "/compare")) } class="flex items-center gap-2 mb-4 text-sm">
- <span>base</span>
- <select name="base" class="border px-2 py-1">
- @branchOptions(branches, base)
- </select>
- <span>←</span>
- <span>compare</span>
- <select name="head" class="border px-2 py-1">
- <option value="">select branch</option>
- @branchOptions(branches, head)
- </select>
- <button class="border px-3 py-1" type="submit">Compare</button>
- </form>
- if cmp != nil {
- <div class="mb-4 text-sm text-gray-600">{ itoa(len(cmp.Commits)) } commit(s), { itoa(len(cmp.Files)) } file(s) changed</div>
- if user != nil && cmp.Mergeable {
- <form method="post" action={ templ.SafeURL(repoPath(repo, "/pulls")) } class="flex flex-col gap-3 mb-6 border p-3">
+ @repoHeader(repo, "pulls")
+ <h2 class="mb-4 text-lg font-semibold tracking-tight">Compare changes</h2>
+ if errMsg != "" {
+ <div class="mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed">{ errMsg }</div>
+ }
+ <form method="get" action={ templ.SafeURL(repoPath(repo, "/compare")) } class="mb-6 flex flex-wrap items-center gap-2 text-sm">
+ <span class="text-muted">base</span>
+ <select name="base" class="select w-auto py-1.5 font-mono text-xs">
+ @branchOptions(branches, base)
+ </select>
+ <span class="text-faint">←</span>
+ <span class="text-muted">compare</span>
+ <select name="head" class="select w-auto py-1.5 font-mono text-xs">
+ <option value="">select branch</option>
+ @branchOptions(branches, head)
+ </select>
+ <button class="btn" type="submit">Compare</button>
+ </form>
+ if cmp != nil {
+ <div class="mb-5 flex items-center gap-2 text-sm text-muted">
+ <span class="badge"><span class="text-open">{ itoa(len(cmp.Commits)) }</span> commits</span>
+ <span class="badge"><span class="text-accent">{ itoa(len(cmp.Files)) }</span> files changed</span>
+ </div>
+ if user != nil && cmp.Mergeable {
+ <div class="card mb-6 p-5">
+ <h3 class="mb-3 font-semibold text-ink">Open a pull request</h3>
+ <form method="post" action={ templ.SafeURL(repoPath(repo, "/pulls")) } class="flex flex-col gap-3">
@csrfField()
<input type="hidden" name="base" value={ base }/>
<input type="hidden" name="head" value={ head }/>
- <input class="border px-2 py-1" type="text" name="title" placeholder="Title" value={ head }/>
- <textarea class="border px-2 py-1" name="body" rows="5" placeholder="Description (markdown supported)"></textarea>
- <div><button class="border px-3 py-1" type="submit">Create pull request</button></div>
+ <input class="input" type="text" name="title" placeholder="Title" value={ head }/>
+ <textarea class="textarea" name="body" rows="4" placeholder="Description (markdown supported)"></textarea>
+ <div class="flex justify-end">
+ <button class="btn btn-primary" type="submit">Create pull request</button>
+ </div>
</form>
- }
- @commitsList(repo, cmp.Commits)
- @diffFiles(cmp.Files)
+ </div>
}
- </div>
+ @commitsList(repo, cmp.Commits)
+ @diffFiles(cmp.Files)
+ }
}
}
templ branchOptions(branches []string, selected string) {
for _, b := range branches {
if b == selected {
<option value={ b } selected>{ b }</option>
} else {
<option value={ b }>{ b }</option>
}
}
}
internal/interface/web/templates/compare_templ.go +34 −42
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Compare(user *domain.User, repo *domain.Repository, base, head string, branches []string, cmp *domain.Comparison, errMsg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "pulls").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h2 class=\"text-lg mb-3\">Compare changes</h2>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <h2 class=\"mb-4 text-lg font-semibold tracking-tight\">Compare changes</h2>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if errMsg != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<p class=\"text-red-600 mb-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 11, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 10, Col: 107}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<form method=\"get\" action=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " <form method=\"get\" action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(repoPath(repo, "/compare"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" class=\"flex items-center gap-2 mb-4 text-sm\"><span>base</span> <select name=\"base\" class=\"border px-2 py-1\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" class=\"mb-6 flex flex-wrap items-center gap-2 text-sm\"><span class=\"text-muted\">base</span> <select name=\"base\" class=\"select w-auto py-1.5 font-mono text-xs\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = branchOptions(branches, base).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</select> <span>←</span> <span>compare</span> <select name=\"head\" class=\"border px-2 py-1\"><option value=\"\">select branch</option>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</select> <span class=\"text-faint\">←</span> <span class=\"text-muted\">compare</span> <select name=\"head\" class=\"select w-auto py-1.5 font-mono text-xs\"><option value=\"\">select branch</option>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = branchOptions(branches, head).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</select> <button class=\"border px-3 py-1\" type=\"submit\">Compare</button></form>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</select> <button class=\"btn\" type=\"submit\">Compare</button></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if cmp != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<div class=\"mb-4 text-sm text-gray-600\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"mb-5 flex items-center gap-2 text-sm text-muted\"><span class=\"badge\"><span class=\"text-open\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(cmp.Commits)))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 27, Col: 68}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 27, Col: 72}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " commit(s), ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</span> commits</span> <span class=\"badge\"><span class=\"text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(cmp.Files)))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 27, Col: 104}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 28, Col: 72}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " file(s) changed</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</span> files changed</span></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if user != nil && cmp.Mergeable {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<form method=\"post\" action=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"card mb-6 p-5\"><h3 class=\"mb-3 font-semibold text-ink\">Open a pull request</h3><form method=\"post\" action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\" class=\"flex flex-col gap-3 mb-6 border p-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" class=\"flex flex-col gap-3\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<input type=\"hidden\" name=\"base\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<input type=\"hidden\" name=\"base\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(base)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 31, Col: 51}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 35, Col: 51}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\"> <input type=\"hidden\" name=\"head\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\"> <input type=\"hidden\" name=\"head\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(head)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 32, Col: 51}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 36, Col: 51}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"> <input class=\"border px-2 py-1\" type=\"text\" name=\"title\" placeholder=\"Title\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\"> <input class=\"input\" type=\"text\" name=\"title\" placeholder=\"Title\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(head)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 33, Col: 95}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 37, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\"> <textarea class=\"border px-2 py-1\" name=\"body\" rows=\"5\" placeholder=\"Description (markdown supported)\"></textarea><div><button class=\"border px-3 py-1\" type=\"submit\">Create pull request</button></div></form>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"> <textarea class=\"textarea\" name=\"body\" rows=\"4\" placeholder=\"Description (markdown supported)\"></textarea><div class=\"flex justify-end\"><button class=\"btn btn-primary\" type=\"submit\">Create pull request</button></div></form></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = commitsList(repo, cmp.Commits).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = diffFiles(cmp.Files).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Compare · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func branchOptions(branches []string, selected string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
if templ_7745c5c3_Var11 == nil {
templ_7745c5c3_Var11 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
for _, b := range branches {
if b == selected {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<option value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<option value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(b)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 48, Col: 20}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 54, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\" selected>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" selected>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(b)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 48, Col: 35}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 54, Col: 35}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</option>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</option>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<option value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<option value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(b)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 50, Col: 20}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 56, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(b)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 50, Col: 26}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/compare.templ`, Line: 56, Col: 26}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</option>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</option>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/dashboard.templ +54 −18
package templates
import "gitgud/internal/domain"
templ Dashboard(user *domain.User, repos []*domain.Repository) {
@Layout("Dashboard · gitgud", user) {
- <div class="max-w-2xl mx-auto">
- <div class="flex items-center justify-between mb-4">
- <h1 class="text-2xl">Your repositories</h1>
- <a class="border px-3 py-1" href="/new">New repository</a>
+ <div class="grid gap-6 md:grid-cols-[230px_1fr]">
+ <aside class="space-y-5">
+ <div class="flex items-center gap-3">
+ @avatar(user.Username, "size-9")
+ <div class="min-w-0">
+ <div class="truncate text-sm font-semibold text-ink">{ user.Username }</div>
+ <div class="truncate font-mono text-[11px] text-faint">{ user.Username + "@self-hosted" }</div>
+ </div>
+ </div>
+ <a class="btn btn-primary w-full justify-center" href="/new">+ New repository</a>
+ <div>
+ <div class="mb-2.5 font-mono text-[11px] font-semibold tracking-wider text-faint uppercase">Repositories</div>
+ <div class="flex flex-col gap-0.5 font-mono text-[13px]">
+ <span class="rounded bg-panel2 px-2.5 py-1.5 text-ink">all <span class="text-faint">{ itoa(len(repos)) }</span></span>
+ <span class="rounded px-2.5 py-1.5 text-muted">public <span class="text-faint">{ itoa(countVisibility(repos, false)) }</span></span>
+ <span class="rounded px-2.5 py-1.5 text-muted">private <span class="text-faint">{ itoa(countVisibility(repos, true)) }</span></span>
+ </div>
+ </div>
+ </aside>
+ <div>
+ <h1 class="mb-4 text-base font-semibold text-ink">Your repositories</h1>
+ if len(repos) == 0 {
+ @emptyState("No repositories yet", "Create your first repository to start pushing code.", "/new", "Create repository")
+ } else {
+ @repoList(repos)
+ }
</div>
- if len(repos) == 0 {
- <p>You don't have any repositories yet. <a href="/new">Create one</a>.</p>
- } else {
- @repoList(repos)
- }
</div>
}
}
templ repoList(repos []*domain.Repository) {
- <ul class="flex flex-col gap-3">
+ <div class="flex flex-col">
for _, repo := range repos {
- <li class="border-b pb-2">
- <a class="text-lg" href={ templ.SafeURL("/" + repo.OwnerName + "/" + repo.Name) }>{ repo.OwnerName }/{ repo.Name }</a>
- if repo.IsPrivate {
- <span class="text-xs border px-1 ml-2">private</span>
- }
+ <a class="group block border-t border-line py-3.5 last:border-b" href={ templ.SafeURL("/" + repo.OwnerName + "/" + repo.Name) }>
+ <div class="mb-1.5 flex items-center gap-2">
+ <span class="font-mono text-sm font-semibold text-accent group-hover:underline">{ repo.OwnerName }/{ repo.Name }</span>
+ if repo.IsPrivate {
+ <span class="rounded border border-[#4a3d24] px-1.5 py-0.5 font-mono text-[10px] text-warn">private</span>
+ } else {
+ <span class="rounded border border-line2 px-1.5 py-0.5 font-mono text-[10px] text-faint">public</span>
+ }
+ </div>
if repo.Description != "" {
- <p class="text-sm text-gray-600">{ repo.Description }</p>
+ <p class="mb-2.5 line-clamp-2 text-[13px] text-muted">{ repo.Description }</p>
}
- </li>
+ <div class="flex items-center gap-1.5 font-mono text-xs text-faint">
+ <span class="size-2 rounded-full bg-accent"></span>
+ { repo.DefaultBranch }
+ </div>
+ </a>
}
- </ul>
+ </div>
+}
+
+templ emptyState(title, body, href, cta string) {
+ <div class="card flex flex-col items-center px-6 py-14 text-center">
+ <div class="mb-4 flex size-10 items-center justify-center rounded-full border border-line2 text-faint">·</div>
+ <h3 class="font-semibold text-ink">{ title }</h3>
+ <p class="mt-1 max-w-sm text-sm text-muted">{ body }</p>
+ if href != "" {
+ <a class="btn btn-primary mt-5" href={ templ.SafeURL(href) }>{ cta }</a>
+ }
+ </div>
}
internal/interface/web/templates/dashboard_templ.go +212 −30
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Dashboard(user *domain.User, repos []*domain.Repository) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-2xl mx-auto\"><div class=\"flex items-center justify-between mb-4\"><h1 class=\"text-2xl\">Your repositories</h1><a class=\"border px-3 py-1\" href=\"/new\">New repository</a></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"grid gap-6 md:grid-cols-[230px_1fr]\"><aside class=\"space-y-5\"><div class=\"flex items-center gap-3\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = avatar(user.Username, "size-9").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"min-w-0\"><div class=\"truncate text-sm font-semibold text-ink\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var3 string
+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 12, Col: 74}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div><div class=\"truncate font-mono text-[11px] text-faint\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username + "@self-hosted")
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 13, Col: 93}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div></div></div><a class=\"btn btn-primary w-full justify-center\" href=\"/new\">+ New repository</a><div><div class=\"mb-2.5 font-mono text-[11px] font-semibold tracking-wider text-faint uppercase\">Repositories</div><div class=\"flex flex-col gap-0.5 font-mono text-[13px]\"><span class=\"rounded bg-panel2 px-2.5 py-1.5 text-ink\">all <span class=\"text-faint\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var5 string
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(repos)))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 20, Col: 108}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</span></span> <span class=\"rounded px-2.5 py-1.5 text-muted\">public <span class=\"text-faint\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var6 string
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(countVisibility(repos, false)))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 21, Col: 122}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</span></span> <span class=\"rounded px-2.5 py-1.5 text-muted\">private <span class=\"text-faint\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var7 string
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(countVisibility(repos, true)))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 22, Col: 122}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</span></span></div></div></aside><div><h1 class=\"mb-4 text-base font-semibold text-ink\">Your repositories</h1>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(repos) == 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p>You don't have any repositories yet. <a href=\"/new\">Create one</a>.</p>")
+ templ_7745c5c3_Err = emptyState("No repositories yet", "Create your first repository to start pushing code.", "/new", "Create repository").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = repoList(repos).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Dashboard · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func repoList(repos []*domain.Repository) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var3 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var3 == nil {
- templ_7745c5c3_Var3 = templ.NopComponent
+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var8 == nil {
+ templ_7745c5c3_Var8 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<ul class=\"flex flex-col gap-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<div class=\"flex flex-col\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, repo := range repos {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<li class=\"border-b pb-2\"><a class=\"text-lg\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<a class=\"group block border-t border-line py-3.5 last:border-b\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL("/" + repo.OwnerName + "/" + repo.Name)
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
+ var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL("/" + repo.OwnerName + "/" + repo.Name)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\"><div class=\"mb-1.5 flex items-center gap-2\"><span class=\"font-mono text-sm font-semibold text-accent group-hover:underline\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var5 string
- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(repo.OwnerName)
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(repo.OwnerName)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 25, Col: 102}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 43, Col: 101}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "/")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "/")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var6 string
- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name)
+ var templ_7745c5c3_Var11 string
+ templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 25, Col: 116}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 43, Col: 115}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</a> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</span> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if repo.IsPrivate {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<span class=\"text-xs border px-1 ml-2\">private</span> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<span class=\"rounded border border-[#4a3d24] px-1.5 py-0.5 font-mono text-[10px] text-warn\">private</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span class=\"rounded border border-line2 px-1.5 py-0.5 font-mono text-[10px] text-faint\">public</span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
}
if repo.Description != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<p class=\"text-sm text-gray-600\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<p class=\"mb-2.5 line-clamp-2 text-[13px] text-muted\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Description)
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Description)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 30, Col: 56}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 51, Col: 77}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</li>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<div class=\"flex items-center gap-1.5 font-mono text-xs text-faint\"><span class=\"size-2 rounded-full bg-accent\"></span> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var13 string
+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(repo.DefaultBranch)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 55, Col: 25}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div></a>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func emptyState(title, body, href, cta string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var14 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var14 == nil {
+ templ_7745c5c3_Var14 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<div class=\"card flex flex-col items-center px-6 py-14 text-center\"><div class=\"mb-4 flex size-10 items-center justify-center rounded-full border border-line2 text-faint\">·</div><h3 class=\"font-semibold text-ink\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var15 string
+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(title)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 65, Col: 44}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</h3><p class=\"mt-1 max-w-sm text-sm text-muted\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var16 string
+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(body)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 66, Col: 52}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if href != "" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<a class=\"btn btn-primary mt-5\" href=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var17 templ.SafeURL = templ.SafeURL(href)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var17)))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var18 string
+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(cta)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/dashboard.templ`, Line: 68, Col: 69}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</ul>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/diff.templ +30 −14
package templates
import "gitgud/internal/domain"
templ diffFiles(files []domain.FileDiff) {
for _, d := range files {
- <div class="border mb-4">
- <div class="bg-gray-100 px-3 py-1 text-sm flex justify-between">
- <span class="font-mono">{ d.Path }</span>
- <span class="text-xs">
- <span class="text-green-700">+{ itoa(d.Added) }</span>
- <span class="text-red-700">-{ itoa(d.Deleted) }</span>
+ <div class="card mb-4 overflow-hidden">
+ <div class="flex items-center gap-3 border-b border-line bg-[#0e1410] px-4 py-2.5">
+ <span class="font-mono text-sm text-ink">{ d.Path }</span>
+ <span class="ml-auto flex items-center gap-2 font-mono text-xs">
+ <span class="text-open">+{ itoa(d.Added) }</span>
+ <span class="text-closed">−{ itoa(d.Deleted) }</span>
</span>
+ @statSquares(d.Added, d.Deleted)
</div>
- <div class="font-mono text-xs overflow-x-auto">
+ <div class="overflow-x-auto bg-panel2 font-mono text-xs leading-relaxed">
for _, line := range diffLines(d.Patch) {
- <div class={ "whitespace-pre px-3 " + diffLineClass(line) }>{ line }</div>
+ <div class={ "whitespace-pre px-4 " + diffLineClass(line) }>{ line }</div>
}
</div>
</div>
}
}
+templ statSquares(added, deleted int) {
+ <span class="flex gap-px">
+ for _, kind := range statBlocks(added, deleted) {
+ switch kind {
+ case "add":
+ <span class="size-2.5 bg-open"></span>
+ case "del":
+ <span class="size-2.5 bg-closed"></span>
+ default:
+ <span class="size-2.5 bg-line2"></span>
+ }
+ }
+ </span>
+}
+
templ commitsList(repo *domain.Repository, commits []domain.Commit) {
- <ul class="border mb-4">
+ <div class="card mb-4 overflow-hidden">
for _, c := range commits {
- <li class="border-b px-3 py-2 flex items-center justify-between">
- <a href={ templ.SafeURL(repoPath(repo, "/commit/"+c.Hash)) }>{ firstLine(c.Message) }</a>
- <code class="text-xs">{ c.ShortHash }</code>
- </li>
+ <div class="row flex items-center justify-between border-b border-line px-4 py-2.5 last:border-0">
+ <a class="truncate text-sm text-ink hover:text-accent" href={ templ.SafeURL(repoPath(repo, "/commit/"+c.Hash)) }>{ firstLine(c.Message) }</a>
+ <code class="ml-4 shrink-0 text-xs text-faint">{ c.ShortHash }</code>
+ </div>
}
- </ul>
+ </div>
}
internal/interface/web/templates/diff_templ.go +90 −30
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func diffFiles(files []domain.FileDiff) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
for _, d := range files {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"border mb-4\"><div class=\"bg-gray-100 px-3 py-1 text-sm flex justify-between\"><span class=\"font-mono\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"card mb-4 overflow-hidden\"><div class=\"flex items-center gap-3 border-b border-line bg-[#0e1410] px-4 py-2.5\"><span class=\"font-mono text-sm text-ink\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(d.Path)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 9, Col: 36}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 9, Col: 53}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"text-xs\"><span class=\"text-green-700\">+")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"ml-auto flex items-center gap-2 font-mono text-xs\"><span class=\"text-open\">+")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(d.Added))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 11, Col: 50}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 11, Col: 45}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span> <span class=\"text-red-700\">-")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span> <span class=\"text-closed\">−")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(d.Deleted))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 12, Col: 50}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 12, Col: 51}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</span></span></div><div class=\"font-mono text-xs overflow-x-auto\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</span></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = statSquares(d.Added, d.Deleted).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div><div class=\"overflow-x-auto bg-panel2 font-mono text-xs leading-relaxed\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, line := range diffLines(d.Patch) {
- var templ_7745c5c3_Var5 = []any{"whitespace-pre px-3 " + diffLineClass(line)}
+ var templ_7745c5c3_Var5 = []any{"whitespace-pre px-4 " + diffLineClass(line)}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var5).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(line)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 17, Col: 71}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 18, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
return nil
})
}
-func commitsList(repo *domain.Repository, commits []domain.Commit) templ.Component {
+func statSquares(added, deleted int) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
if templ_7745c5c3_Var8 == nil {
templ_7745c5c3_Var8 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<ul class=\"border mb-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<span class=\"flex gap-px\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, kind := range statBlocks(added, deleted) {
+ switch kind {
+ case "add":
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<span class=\"size-2.5 bg-open\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ case "del":
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<span class=\"size-2.5 bg-closed\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ default:
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<span class=\"size-2.5 bg-line2\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func commitsList(repo *domain.Repository, commits []domain.Commit) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var9 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var9 == nil {
+ templ_7745c5c3_Var9 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<div class=\"card mb-4 overflow-hidden\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, c := range commits {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<li class=\"border-b px-3 py-2 flex items-center justify-between\"><a href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div class=\"row flex items-center justify-between border-b border-line px-4 py-2.5 last:border-0\"><a class=\"truncate text-sm text-ink hover:text-accent\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(repoPath(repo, "/commit/"+c.Hash))
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
+ var templ_7745c5c3_Var10 templ.SafeURL = templ.SafeURL(repoPath(repo, "/commit/"+c.Hash))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var10 string
- templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(firstLine(c.Message))
+ var templ_7745c5c3_Var11 string
+ templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(firstLine(c.Message))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 28, Col: 87}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 44, Col: 139}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</a> <code class=\"text-xs\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</a> <code class=\"ml-4 shrink-0 text-xs text-faint\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var11 string
- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(c.ShortHash)
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(c.ShortHash)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 29, Col: 39}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/diff.templ`, Line: 45, Col: 64}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</code></li>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</code></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</ul>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/errors.templ +11 −8
package templates
import "gitgud/internal/domain"
templ Forbidden(user *domain.User) {
@Layout("Forbidden · gitgud", user) {
- <div class="max-w-2xl mx-auto">
- <h1 class="text-2xl mb-2">403</h1>
- <p>You don't have permission to do that.</p>
- </div>
+ @errorState("403", "Access denied", "You don't have permission to do that.")
}
}
templ ServerError(user *domain.User) {
@Layout("Error · gitgud", user) {
- <div class="max-w-2xl mx-auto">
- <h1 class="text-2xl mb-2">500</h1>
- <p>Something went wrong. Please try again.</p>
- </div>
+ @errorState("500", "Something went wrong", "An unexpected error occurred. Please try again.")
}
}
+
+templ errorState(code, title, body string) {
+ <div class="mx-auto max-w-md py-20 text-center">
+ <div class="mb-4 font-mono text-6xl font-bold text-accent/30">{ code }</div>
+ <h1 class="text-2xl font-semibold tracking-tight text-ink">{ title }</h1>
+ <p class="mt-2 text-sm text-muted">{ body }</p>
+ <a class="btn mt-6" href="/">← Back home</a>
+ </div>
+}
internal/interface/web/templates/errors_templ.go +70 −2
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Forbidden(user *domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-2xl mx-auto\"><h1 class=\"text-2xl mb-2\">403</h1><p>You don't have permission to do that.</p></div>")
+ templ_7745c5c3_Err = errorState("403", "Access denied", "You don't have permission to do that.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Forbidden · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func ServerError(user *domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
if templ_7745c5c3_Var3 == nil {
templ_7745c5c3_Var3 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"max-w-2xl mx-auto\"><h1 class=\"text-2xl mb-2\">500</h1><p>Something went wrong. Please try again.</p></div>")
+ templ_7745c5c3_Err = errorState("500", "Something went wrong", "An unexpected error occurred. Please try again.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Error · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func errorState(code, title, body string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var5 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var5 == nil {
+ templ_7745c5c3_Var5 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mx-auto max-w-md py-20 text-center\"><div class=\"mb-4 font-mono text-6xl font-bold text-accent/30\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var6 string
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(code)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/errors.templ`, Line: 19, Col: 70}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div><h1 class=\"text-2xl font-semibold tracking-tight text-ink\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var7 string
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(title)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/errors.templ`, Line: 20, Col: 68}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1><p class=\"mt-2 text-sm text-muted\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(body)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/errors.templ`, Line: 21, Col: 43}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p><a class=\"btn mt-6\" href=\"/\">← Back home</a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/helpers.go +105 −5
package templates
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"gitgud/internal/domain"
"gitgud/internal/interface/web/presenter"
)
type ctxKey int
const (
flashKey ctxKey = iota
csrfKey
)
func WithFlash(ctx context.Context, msg string) context.Context {
return context.WithValue(ctx, flashKey, msg)
}
func flashOf(ctx context.Context) string {
s, _ := ctx.Value(flashKey).(string)
return s
}
func WithCSRF(ctx context.Context, token string) context.Context {
return context.WithValue(ctx, csrfKey, token)
}
func csrfToken(ctx context.Context) string {
s, _ := ctx.Value(csrfKey).(string)
return s
}
func markdown(s string) string {
return presenter.RenderMarkdown([]byte(s))
}
func fmtTime(t time.Time) string {
return t.Format("2006-01-02 15:04")
}
func stateAction(state domain.IssueState) string {
if state == domain.IssueOpen {
return "/close"
}
return "/reopen"
}
func stateTabClass(current, want string) string {
if current == want {
- return "font-semibold"
+ return "font-semibold text-ink"
}
- return "text-gray-600"
+ return "text-muted hover:text-ink"
}
func cloneInstructions(repo *domain.Repository) string {
url := "http://localhost:8080/" + repo.OwnerName + "/" + repo.Name + ".git"
return fmt.Sprintf(`git clone %s
cd %s
echo "# %s" > README.md
git add README.md
git commit -m "first commit"
git push -u origin %s`, url, repo.Name, repo.Name, repo.DefaultBranch)
}
type Crumb struct {
Name string
Href string
}
func treeCrumbs(repo *domain.Repository, ref, p string) []Crumb {
base := "/" + repo.OwnerName + "/" + repo.Name + "/tree/" + ref
crumbs := []Crumb{{Name: repo.Name, Href: base}}
if p = strings.Trim(p, "/"); p != "" {
acc := base
for _, seg := range strings.Split(p, "/") {
acc += "/" + seg
crumbs = append(crumbs, Crumb{Name: seg, Href: acc})
}
}
return crumbs
}
func entryHref(repo *domain.Repository, ref string, e domain.TreeEntry) string {
kind := "blob"
if e.IsDir {
kind = "tree"
}
return "/" + repo.OwnerName + "/" + repo.Name + "/" + kind + "/" + ref + "/" + e.Path
}
func repoPath(repo *domain.Repository, sub string) string {
return "/" + repo.OwnerName + "/" + repo.Name + sub
}
func humanSize(n int64) string {
const unit = 1024
if n < unit {
return fmt.Sprintf("%d B", n)
}
div, exp := int64(unit), 0
for x := n / unit; x >= unit; x /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(n)/float64(div), "KMGTPE"[exp])
}
func itoa(n int) string {
return strconv.Itoa(n)
}
+func countVisibility(repos []*domain.Repository, private bool) int {
+ n := 0
+ for _, r := range repos {
+ if r.IsPrivate == private {
+ n++
+ }
+ }
+ return n
+}
+
+func initial(s string) string {
+ if s == "" {
+ return "?"
+ }
+ return strings.ToUpper(s[:1])
+}
+
func firstLine(s string) string {
if i := strings.IndexByte(s, '\n'); i >= 0 {
return s[:i]
}
return s
}
func diffLineClass(line string) string {
switch {
+ case strings.HasPrefix(line, "@@"):
+ return "diff-hunk"
case strings.HasPrefix(line, "+"):
- return "bg-green-100"
+ return "diff-add"
case strings.HasPrefix(line, "-"):
- return "bg-red-100"
+ return "diff-del"
default:
- return ""
+ return "text-muted"
+ }
+}
+
+// statBlocks renders a 5-square GitHub-style diffstat: green for additions,
+// red for deletions, proportional to the change, padded with neutral squares.
+func statBlocks(added, deleted int) []string {
+ blocks := make([]string, 5)
+ total := added + deleted
+ if total == 0 {
+ for i := range blocks {
+ blocks[i] = "none"
+ }
+ return blocks
+ }
+ greens := added * 5 / total
+ if added > 0 && greens == 0 {
+ greens = 1
+ }
+ reds := 5 - greens
+ if deleted > 0 && reds == 0 && greens > 0 {
+ greens--
+ reds = 1
+ }
+ for i := range blocks {
+ switch {
+ case i < greens:
+ blocks[i] = "add"
+ case i < greens+reds:
+ blocks[i] = "del"
+ default:
+ blocks[i] = "none"
+ }
+ }
+ return blocks
+}
+
+// langLabel maps a file path to a human language label for the blob header.
+func langLabel(path string) string {
+ ext := strings.ToLower(path)
+ if i := strings.LastIndexByte(ext, '.'); i >= 0 {
+ ext = ext[i+1:]
+ }
+ switch ext {
+ case "go":
+ return "Go"
+ case "js", "mjs", "cjs":
+ return "JavaScript"
+ case "ts", "tsx":
+ return "TypeScript"
+ case "py":
+ return "Python"
+ case "rs":
+ return "Rust"
+ case "rb":
+ return "Ruby"
+ case "java":
+ return "Java"
+ case "c", "h":
+ return "C"
+ case "cpp", "cc", "hpp":
+ return "C++"
+ case "sh", "bash", "zsh":
+ return "Shell"
+ case "html", "htm":
+ return "HTML"
+ case "css":
+ return "CSS"
+ case "json":
+ return "JSON"
+ case "yml", "yaml":
+ return "YAML"
+ case "md", "markdown":
+ return "Markdown"
+ case "sql":
+ return "SQL"
+ case "templ":
+ return "Templ"
+ case "":
+ return "Text"
+ default:
+ return strings.ToUpper(ext)
}
}
func diffLines(patch string) []string {
return strings.Split(strings.TrimRight(patch, "\n"), "\n")
}
internal/interface/web/templates/home.templ +19 −2
package templates
import "gitgud/internal/domain"
templ Home(user *domain.User) {
- @Layout("gitgud", user) {
- <div class="text-3xl">gitgud cool homepage</div>
+ @Layout("gitgud — minimal git hosting", user) {
+ <div class="mx-auto max-w-2xl py-16 text-center">
+ <div class="mx-auto mb-8 flex size-14 items-center justify-center rounded-2xl border border-accent/30 bg-accent/[.08] text-accent shadow-[0_0_40px_-6px_rgba(63,207,127,.6)]">
+ @gitLogo("size-7")
+ </div>
+ <h1 class="text-4xl font-bold tracking-tight text-ink sm:text-5xl">
+ git hosting,<br/><span class="text-accent">stripped down.</span>
+ </h1>
+ <p class="mx-auto mt-5 max-w-md text-muted">
+ Clone, push, browse, and review — a small, self-hosted home for your repositories.
+ </p>
+ <div class="mt-8 flex items-center justify-center gap-3">
+ <a class="btn btn-primary" href="/register">Get started</a>
+ <a class="btn" href="/login">Sign in</a>
+ </div>
+ <div class="mx-auto mt-12 max-w-md rounded-lg border border-line bg-panel2 px-4 py-3 text-left font-mono text-xs text-muted">
+ <span class="text-faint">$</span> git clone http://localhost:8080/<span class="text-accent">you</span>/<span class="text-accent">repo</span>.git
+ </div>
+ </div>
}
}
internal/interface/web/templates/home_templ.go +10 −2
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Home(user *domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"text-3xl\">gitgud cool homepage</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mx-auto max-w-2xl py-16 text-center\"><div class=\"mx-auto mb-8 flex size-14 items-center justify-center rounded-2xl border border-accent/30 bg-accent/[.08] text-accent shadow-[0_0_40px_-6px_rgba(63,207,127,.6)]\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = gitLogo("size-7").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div><h1 class=\"text-4xl font-bold tracking-tight text-ink sm:text-5xl\">git hosting,<br><span class=\"text-accent\">stripped down.</span></h1><p class=\"mx-auto mt-5 max-w-md text-muted\">Clone, push, browse, and review — a small, self-hosted home for your repositories.</p><div class=\"mt-8 flex items-center justify-center gap-3\"><a class=\"btn btn-primary\" href=\"/register\">Get started</a> <a class=\"btn\" href=\"/login\">Sign in</a></div><div class=\"mx-auto mt-12 max-w-md rounded-lg border border-line bg-panel2 px-4 py-3 text-left font-mono text-xs text-muted\"><span class=\"text-faint\">$</span> git clone http://localhost:8080/<span class=\"text-accent\">you</span>/<span class=\"text-accent\">repo</span>.git</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
- templ_7745c5c3_Err = Layout("gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
+ templ_7745c5c3_Err = Layout("gitgud — minimal git hosting", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/issue_detail.templ +41 −33
package templates
import "gitgud/internal/domain"
templ IssueDetail(user *domain.User, repo *domain.Repository, issue *domain.Issue, comments []*domain.IssueComment, canModify bool) {
@Layout(issue.Title+" · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "issues")
- <div class="flex items-center gap-2 mb-1">
- <h2 class="text-xl">{ issue.Title } <span class="text-gray-400">#{ itoa(issue.Number) }</span></h2>
- <span class="text-xs border px-2 py-0.5">{ string(issue.State) }</span>
- </div>
- <div class="text-xs text-gray-500 mb-4">opened by { issue.AuthorName } on { fmtTime(issue.CreatedAt) }</div>
- @commentCard(issue.AuthorName, fmtTime(issue.CreatedAt), issue.Body)
- for _, c := range comments {
- @commentCard(c.AuthorName, fmtTime(c.CreatedAt), c.Body)
- }
- if canModify {
- <form method="post" action={ templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+stateAction(issue.State))) } class="mb-4">
- @csrfField()
- if issue.State == domain.IssueOpen {
- <button class="border px-3 py-1 text-sm" type="submit">Close issue</button>
- } else {
- <button class="border px-3 py-1 text-sm" type="submit">Reopen issue</button>
- }
- </form>
- }
- if user != nil {
- <form method="post" action={ templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+"/comments")) } class="flex flex-col gap-2">
- @csrfField()
- <textarea class="border px-2 py-1" name="body" rows="4" placeholder="Leave a comment (markdown supported)"></textarea>
- <div>
- <button class="border px-3 py-1" type="submit">Comment</button>
- </div>
- </form>
+ @repoHeader(repo, "issues")
+ <div class="mb-1 flex items-start gap-3">
+ <h2 class="text-2xl font-semibold tracking-tight text-ink">{ issue.Title } <span class="font-normal text-faint">#{ itoa(issue.Number) }</span></h2>
+ </div>
+ <div class="mb-6 flex items-center gap-3">
+ if issue.State == domain.IssueOpen {
+ <span class="badge-open"><span class="size-2 rounded-full border-2 border-grassink"></span> Open</span>
} else {
- <p class="text-sm text-gray-500"><a href="/login">Sign in</a> to comment.</p>
+ <span class="badge-closed"><span class="size-2 rounded-full border-2 border-current"></span> Closed</span>
}
+ <span class="meta">{ issue.AuthorName } opened this on { fmtTime(issue.CreatedAt) }</span>
</div>
+ @commentCard(issue.AuthorName, fmtTime(issue.CreatedAt), issue.Body)
+ for _, c := range comments {
+ @commentCard(c.AuthorName, fmtTime(c.CreatedAt), c.Body)
+ }
+ if canModify {
+ <form method="post" action={ templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+stateAction(issue.State))) } class="mb-6">
+ @csrfField()
+ if issue.State == domain.IssueOpen {
+ <button class="btn btn-danger" type="submit">Close issue</button>
+ } else {
+ <button class="btn" type="submit">Reopen issue</button>
+ }
+ </form>
+ }
+ if user != nil {
+ <form method="post" action={ templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+"/comments")) } class="flex flex-col gap-3">
+ @csrfField()
+ <textarea class="textarea" name="body" rows="4" placeholder="Leave a comment… (markdown supported)"></textarea>
+ <div class="flex justify-end">
+ <button class="btn btn-primary" type="submit">Comment</button>
+ </div>
+ </form>
+ } else {
+ <p class="text-sm text-muted"><a class="text-accent hover:underline" href="/login">Sign in</a> to comment.</p>
+ }
}
}
templ commentCard(author, when, body string) {
- <div class="border mb-3">
- <div class="bg-gray-100 px-3 py-1 text-xs text-gray-600">{ author } commented on { when }</div>
- <div class="px-3 py-2">
+ <div class="card mb-4 overflow-hidden">
+ <div class="flex items-center gap-2 border-b border-line bg-[#0e1410] px-4 py-2.5">
+ @avatar(author, "size-5")
+ <span class="text-sm font-medium text-ink">{ author }</span>
+ <span class="meta">commented on { when }</span>
+ </div>
+ <div class="prose-dark px-4 py-3">
@templ.Raw(markdown(body))
</div>
</div>
}
internal/interface/web/templates/issue_detail_templ.go +70 −60
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func IssueDetail(user *domain.User, repo *domain.Repository, issue *domain.Issue, comments []*domain.IssueComment, canModify bool) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "issues").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex items-center gap-2 mb-1\"><h2 class=\"text-xl\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mb-1 flex items-start gap-3\"><h2 class=\"text-2xl font-semibold tracking-tight text-ink\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(issue.Title)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 10, Col: 37}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 9, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " <span class=\"text-gray-400\">#")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " <span class=\"font-normal text-faint\">#")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(issue.Number))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 10, Col: 89}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 9, Col: 136}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</span></h2><span class=\"text-xs border px-2 py-0.5\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></h2></div><div class=\"mb-6 flex items-center gap-3\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if issue.State == domain.IssueOpen {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<span class=\"badge-open\"><span class=\"size-2 rounded-full border-2 border-grassink\"></span> Open</span> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<span class=\"badge-closed\"><span class=\"size-2 rounded-full border-2 border-current\"></span> Closed</span> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<span class=\"meta\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(string(issue.State))
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(issue.AuthorName)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 11, Col: 66}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 17, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</span></div><div class=\"text-xs text-gray-500 mb-4\">opened by ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " opened this on ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(issue.AuthorName)
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmtTime(issue.CreatedAt))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 13, Col: 71}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 17, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " on ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmtTime(issue.CreatedAt))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 13, Col: 103}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</span></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = commentCard(issue.AuthorName, fmtTime(issue.CreatedAt), issue.Body).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, c := range comments {
templ_7745c5c3_Err = commentCard(c.AuthorName, fmtTime(c.CreatedAt), c.Body).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
if canModify {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<form method=\"post\" action=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<form method=\"post\" action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+stateAction(issue.State)))
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
+ var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+stateAction(issue.State)))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" class=\"mb-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" class=\"mb-6\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if issue.State == domain.IssueOpen {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<button class=\"border px-3 py-1 text-sm\" type=\"submit\">Close issue</button>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<button class=\"btn btn-danger\" type=\"submit\">Close issue</button>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<button class=\"border px-3 py-1 text-sm\" type=\"submit\">Reopen issue</button>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<button class=\"btn\" type=\"submit\">Reopen issue</button>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</form>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
if user != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<form method=\"post\" action=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<form method=\"post\" action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+"/comments"))
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
+ var templ_7745c5c3_Var8 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues/"+itoa(issue.Number)+"/comments"))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\" class=\"flex flex-col gap-2\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" class=\"flex flex-col gap-3\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<textarea class=\"border px-2 py-1\" name=\"body\" rows=\"4\" placeholder=\"Leave a comment (markdown supported)\"></textarea><div><button class=\"border px-3 py-1\" type=\"submit\">Comment</button></div></form>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<textarea class=\"textarea\" name=\"body\" rows=\"4\" placeholder=\"Leave a comment… (markdown supported)\"></textarea><div class=\"flex justify-end\"><button class=\"btn btn-primary\" type=\"submit\">Comment</button></div></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<p class=\"text-sm text-gray-500\"><a href=\"/login\">Sign in</a> to comment.</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<p class=\"text-sm text-muted\"><a class=\"text-accent hover:underline\" href=\"/login\">Sign in</a> to comment.</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(issue.Title+" · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func commentCard(author, when, body string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var10 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var10 == nil {
- templ_7745c5c3_Var10 = templ.NopComponent
+ templ_7745c5c3_Var9 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var9 == nil {
+ templ_7745c5c3_Var9 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<div class=\"border mb-3\"><div class=\"bg-gray-100 px-3 py-1 text-xs text-gray-600\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<div class=\"card mb-4 overflow-hidden\"><div class=\"flex items-center gap-2 border-b border-line bg-[#0e1410] px-4 py-2.5\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var11 string
- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(author)
+ templ_7745c5c3_Err = avatar(author, "size-5").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 45, Col: 67}
+ return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<span class=\"text-sm font-medium text-ink\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " commented on ")
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(author)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 51, Col: 54}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var12 string
- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(when)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</span> <span class=\"meta\">commented on ")
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 45, Col: 89}
+ return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ var templ_7745c5c3_Var11 string
+ templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(when)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_detail.templ`, Line: 52, Col: 41}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div><div class=\"px-3 py-2\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</span></div><div class=\"prose-dark px-4 py-3\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.Raw(markdown(body)).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/issue_new.templ +8 −8
package templates
import "gitgud/internal/domain"
templ IssueNew(user *domain.User, repo *domain.Repository, title, body, errMsg string) {
@Layout("New issue · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "issues")
- <h2 class="text-lg mb-3">New issue</h2>
+ @repoHeader(repo, "issues")
+ <div class="mx-auto max-w-2xl">
+ <h2 class="mb-4 text-lg font-semibold tracking-tight">Open a new issue</h2>
if errMsg != "" {
- <p class="text-red-600 mb-3">{ errMsg }</p>
+ <div class="mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed">{ errMsg }</div>
}
<form method="post" action={ templ.SafeURL(repoPath(repo, "/issues")) } class="flex flex-col gap-3">
@csrfField()
- <input class="border px-2 py-1" type="text" name="title" placeholder="Title" value={ title } autofocus/>
- <textarea class="border px-2 py-1" name="body" rows="8" placeholder="Leave a description (markdown supported)">{ body }</textarea>
- <div>
- <button class="border px-3 py-1" type="submit">Create issue</button>
+ <input class="input" type="text" name="title" placeholder="Title" value={ title } autofocus/>
+ <textarea class="textarea font-sans" name="body" rows="8" placeholder="Describe the issue… (markdown supported)">{ body }</textarea>
+ <div class="flex justify-end">
+ <button class="btn btn-primary" type="submit">Create issue</button>
</div>
</form>
</div>
}
}
internal/interface/web/templates/issue_new_templ.go +11 −15
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func IssueNew(user *domain.User, repo *domain.Repository, title, body, errMsg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "issues").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h2 class=\"text-lg mb-3\">New issue</h2>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mx-auto max-w-2xl\"><h2 class=\"mb-4 text-lg font-semibold tracking-tight\">Open a new issue</h2>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if errMsg != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<p class=\"text-red-600 mb-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_new.templ`, Line: 11, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_new.templ`, Line: 11, Col: 108}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<form method=\"post\" action=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<form method=\"post\" action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" class=\"flex flex-col gap-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" class=\"flex flex-col gap-3\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<input class=\"border px-2 py-1\" type=\"text\" name=\"title\" placeholder=\"Title\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<input class=\"input\" type=\"text\" name=\"title\" placeholder=\"Title\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_new.templ`, Line: 15, Col: 94}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_new.templ`, Line: 15, Col: 83}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" autofocus> <textarea class=\"border px-2 py-1\" name=\"body\" rows=\"8\" placeholder=\"Leave a description (markdown supported)\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" autofocus> <textarea class=\"textarea font-sans\" name=\"body\" rows=\"8\" placeholder=\"Describe the issue… (markdown supported)\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(body)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_new.templ`, Line: 16, Col: 121}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issue_new.templ`, Line: 16, Col: 125}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</textarea><div><button class=\"border px-3 py-1\" type=\"submit\">Create issue</button></div></form></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</textarea><div class=\"flex justify-end\"><button class=\"btn btn-primary\" type=\"submit\">Create issue</button></div></form></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("New issue · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/issues_list.templ +32 −21
package templates
import "gitgud/internal/domain"
templ IssuesList(user *domain.User, repo *domain.Repository, state string, issues []*domain.Issue, openCount, closedCount int) {
@Layout("Issues · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "issues")
- <div class="flex items-center justify-between mb-3">
- <div class="flex gap-4 text-sm">
- <a class={ stateTabClass(state, "open") } href={ templ.SafeURL(repoPath(repo, "/issues?state=open")) }>{ itoa(openCount) } Open</a>
- <a class={ stateTabClass(state, "closed") } href={ templ.SafeURL(repoPath(repo, "/issues?state=closed")) }>{ itoa(closedCount) } Closed</a>
- </div>
- if user != nil {
- <a class="border px-3 py-1 text-sm" href={ templ.SafeURL(repoPath(repo, "/issues/new")) }>New issue</a>
- }
+ @repoHeader(repo, "issues")
+ <div class="mb-4 flex items-center justify-between">
+ <div class="flex gap-5 text-sm">
+ <a class={ stateTabClass(state, "open") } href={ templ.SafeURL(repoPath(repo, "/issues?state=open")) }>{ itoa(openCount) } Open</a>
+ <a class={ stateTabClass(state, "closed") } href={ templ.SafeURL(repoPath(repo, "/issues?state=closed")) }>{ itoa(closedCount) } Closed</a>
</div>
- if len(issues) == 0 {
- <p class="text-gray-500">No issues to show.</p>
- } else {
- <ul class="border">
- for _, i := range issues {
- <li class="border-b px-3 py-2">
- <a href={ templ.SafeURL(repoPath(repo, "/issues/"+itoa(i.Number))) }>{ i.Title }</a>
- <div class="text-xs text-gray-500">#{ itoa(i.Number) } · { string(i.State) } · opened by { i.AuthorName }</div>
- </li>
- }
- </ul>
+ if user != nil {
+ <a class="btn btn-primary" href={ templ.SafeURL(repoPath(repo, "/issues/new")) }>+ New issue</a>
}
</div>
+ if len(issues) == 0 {
+ @emptyState("No issues here", "There are no "+state+" issues in this repository.", "", "")
+ } else {
+ <div class="card overflow-hidden">
+ for _, i := range issues {
+ <div class="row border-b border-line px-4 py-3 last:border-0">
+ <a class="flex items-start gap-2.5" href={ templ.SafeURL(repoPath(repo, "/issues/"+itoa(i.Number))) }>
+ @issueDot(string(i.State))
+ <span class="min-w-0">
+ <span class="block text-ink hover:text-accent">{ i.Title }</span>
+ <span class="meta">#{ itoa(i.Number) } · opened by { i.AuthorName } · { fmtTime(i.CreatedAt) }</span>
+ </span>
+ </a>
+ </div>
+ }
+ </div>
+ }
+ }
+}
+
+templ issueDot(state string) {
+ if state == "open" {
+ <span class="mt-1 size-3.5 shrink-0 rounded-full border-2 border-accent"></span>
+ } else {
+ <span class="mt-1 size-3.5 shrink-0 rounded-full border-2 border-faint"></span>
}
}
internal/interface/web/templates/issues_list_templ.go +73 −37
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func IssuesList(user *domain.User, repo *domain.Repository, state string, issues []*domain.Issue, openCount, closedCount int) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "issues").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex items-center justify-between mb-3\"><div class=\"flex gap-4 text-sm\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mb-4 flex items-center justify-between\"><div class=\"flex gap-5 text-sm\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 = []any{stateTabClass(state, "open")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a class=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<a class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var3).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues?state=open"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(openCount))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 11, Col: 125}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 10, Col: 124}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " Open</a> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " Open</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 = []any{stateTabClass(state, "closed")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<a class=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var7).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues?state=closed"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(closedCount))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 12, Col: 131}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 11, Col: 130}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " Closed</a></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " Closed</a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if user != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<a class=\"border px-3 py-1 text-sm\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<a class=\"btn btn-primary\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues/new"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">New issue</a>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\">+ New issue</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(issues) == 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<p class=\"text-gray-500\">No issues to show.</p>")
+ templ_7745c5c3_Err = emptyState("No issues here", "There are no "+state+" issues in this repository.", "", "").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<ul class=\"border\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<div class=\"card overflow-hidden\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, i := range issues {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<li class=\"border-b px-3 py-2\"><a href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"row border-b border-line px-4 py-3 last:border-0\"><a class=\"flex items-start gap-2.5\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 templ.SafeURL = templ.SafeURL(repoPath(repo, "/issues/"+itoa(i.Number)))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = issueDot(string(i.State)).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<span class=\"min-w-0\"><span class=\"block text-ink hover:text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(i.Title)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 24, Col: 85}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 26, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</a><div class=\"text-xs text-gray-500\">#")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</span> <span class=\"meta\">#")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(i.Number))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 25, Col: 59}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 27, Col: 44}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " · ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " · opened by ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
- templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(string(i.State))
+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(i.AuthorName)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 25, Col: 82}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 27, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " · opened by ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " · ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var16 string
- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(i.AuthorName)
+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmtTime(i.CreatedAt))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 25, Col: 112}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/issues_list.templ`, Line: 27, Col: 102}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div></li>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</span></span></a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</ul>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
return nil
})
templ_7745c5c3_Err = Layout("Issues · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func issueDot(state string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var17 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var17 == nil {
+ templ_7745c5c3_Var17 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ if state == "open" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<span class=\"mt-1 size-3.5 shrink-0 rounded-full border-2 border-accent\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<span class=\"mt-1 size-3.5 shrink-0 rounded-full border-2 border-faint\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/layout.templ +135 −20
package templates
import "gitgud/internal/domain"
templ Layout(title string, user *domain.User) {
<!DOCTYPE html>
- <html lang="en">
+ <html lang="en" class="dark">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>{ title }</title>
- <link rel="stylesheet" href="/static/css/main.css"/>
+ <link rel="preconnect" href="https://fonts.googleapis.com"/>
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
+ <link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
+ <style type="text/tailwindcss">
+ @theme {
+ --color-canvas: #080b09;
+ --color-panel: #0b100d;
+ --color-panel2: #141b16;
+ --color-line: #1e2820;
+ --color-line2: #25342a;
+ --color-ink: #eef4ef;
+ --color-muted: #8a978c;
+ --color-faint: #54605c;
+ --color-accent: #3fcf7f;
+ --color-accenthi: #6fe0a0;
+ --color-grass: #2ea04a;
+ --color-grasshi: #34b554;
+ --color-grassink: #06120a;
+ --color-open: #3fcf7f;
+ --color-closed: #ff7066;
+ --color-merged: #a371f7;
+ --color-warn: #e0c060;
+ --font-sans: "Geist", ui-sans-serif, system-ui, sans-serif;
+ --font-mono: "JetBrains Mono", ui-monospace, monospace;
+ }
+ @layer base {
+ html { color-scheme: dark; }
+ body { @apply bg-canvas text-ink font-sans antialiased; }
+ body::before {
+ content: "";
+ position: fixed;
+ inset: 0;
+ pointer-events: none;
+ z-index: 0;
+ background: radial-gradient(680px 320px at 50% -120px, rgba(63,207,127,.12), transparent 70%);
+ }
+ a { @apply transition-colors; }
+ code, pre, .mono { @apply font-mono; }
+ ::selection { background: rgba(63,207,127,.30); }
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
+ ::-webkit-scrollbar-thumb { background: #25342a; border-radius: 9999px; border: 2px solid #080b09; }
+ :focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(63,207,127,.55); border-radius: 6px; }
+ main { animation: rise .42s cubic-bezier(.22,1,.36,1) both; }
+ @keyframes rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
+ }
+ @layer components {
+ .btn { @apply inline-flex items-center gap-1.5 rounded-md border border-line2 bg-panel2 px-3 py-1.5 text-sm font-medium text-ink transition hover:border-faint hover:bg-line; }
+ .btn-primary { @apply border-transparent bg-grass font-semibold text-grassink shadow-[0_0_0_1px_rgba(46,160,74,.5),0_6px_20px_-10px_rgba(63,207,127,.8)] hover:bg-grasshi hover:border-transparent; }
+ .btn-danger { @apply text-closed hover:border-closed hover:bg-closed/10; }
+ .input, .textarea, .select { @apply w-full rounded-md border border-line2 bg-[#0e1410] px-3 py-2 text-sm text-ink placeholder:text-faint transition focus:border-accent; }
+ .card { @apply rounded-md border border-line bg-panel; }
+ .link { @apply text-ink hover:text-accent; }
+ .muted { @apply text-muted; }
+ .meta { @apply font-mono text-xs text-faint; }
+ .tab { @apply inline-flex items-center gap-2 border-b-2 border-transparent pb-2.5 text-sm text-muted transition hover:text-ink; }
+ .tab-active { @apply border-accent font-semibold text-ink; }
+ .badge { @apply inline-flex items-center gap-1 rounded border border-line2 px-2 py-0.5 text-xs font-medium text-muted; }
+ .badge-open { @apply gap-1.5 rounded-full border-transparent bg-grass px-3 py-1 font-semibold text-grassink; }
+ .badge-closed { @apply gap-1.5 rounded-full border-transparent bg-closed/16 px-3 py-1 font-medium text-[#ff8f86]; }
+ .badge-merged { @apply gap-1.5 rounded-full border-transparent bg-merged/16 px-3 py-1 font-medium text-[#c8a6f7]; }
+ .label-bug { @apply inline-flex items-center rounded-full bg-closed/16 px-2.5 py-0.5 text-[10px] font-medium text-[#ff8f86]; }
+ .label-enh { @apply inline-flex items-center rounded-full bg-accent/16 px-2.5 py-0.5 text-[10px] font-medium text-accenthi; }
+ .label-good { @apply inline-flex items-center rounded-full bg-warn/16 px-2.5 py-0.5 text-[10px] font-medium text-warn; }
+ .row { @apply transition hover:bg-panel2; }
+ .diff-add { @apply bg-accent/12 text-[#aee6c4]; }
+ .diff-del { @apply bg-closed/12 text-[#f2b8b3]; }
+ .diff-hunk { @apply bg-[#10171b] text-[#5aa0c8]; }
+ .prose-dark { @apply text-sm leading-relaxed text-muted; }
+ .prose-dark h1 { @apply mt-5 mb-3 text-xl font-semibold text-ink first:mt-0; }
+ .prose-dark h2 { @apply mt-5 mb-2 text-lg font-semibold text-ink first:mt-0; }
+ .prose-dark h3 { @apply mt-4 mb-2 font-semibold text-ink; }
+ .prose-dark p { @apply my-3; }
+ .prose-dark a { @apply text-accent hover:underline; }
+ .prose-dark strong { @apply font-semibold text-ink; }
+ .prose-dark ul { @apply my-3 list-disc pl-5; }
+ .prose-dark ol { @apply my-3 list-decimal pl-5; }
+ .prose-dark li { @apply my-1; }
+ .prose-dark code { @apply rounded border border-line2 bg-panel2 px-1.5 py-0.5 text-[.85em] text-accent; }
+ .prose-dark pre { @apply my-3 overflow-x-auto rounded-lg border border-line bg-panel2 p-4 text-xs; }
+ .prose-dark pre code { @apply bg-transparent p-0; }
+ .prose-dark blockquote { @apply my-3 border-l-2 border-line2 pl-4 text-faint; }
+ .prose-dark hr { @apply my-5 border-line; }
+ }
+ </style>
</head>
<body>
- <nav class="flex items-center justify-between px-6 py-3 border-b">
- <a href="/" class="font-bold">gitgud</a>
- <div class="flex items-center gap-4">
- if user != nil {
- <a href="/new">New</a>
- <span>{ user.Username }</span>
- <form method="post" action="/logout">
- @csrfField()
- <button type="submit">Sign out</button>
- </form>
- } else {
- <a href="/login">Sign in</a>
- <a href="/register">Register</a>
- }
+ <header class="sticky top-0 z-20 border-b border-line bg-canvas/80 backdrop-blur-xl">
+ <nav class="mx-auto flex h-14 max-w-5xl items-center justify-between px-6">
+ <a href="/" class="flex items-center gap-2.5">
+ <span class="text-accent">@gitLogo("size-5")</span>
+ <span class="font-mono font-semibold tracking-tight text-ink">gitgud</span>
+ </a>
+ <div class="flex items-center gap-4 text-sm">
+ if user != nil {
+ <a class="btn" href="/new">+ New</a>
+ <div class="flex items-center gap-2">
+ @avatar(user.Username, "size-6")
+ <a class="link mono text-muted" href={ templ.SafeURL("/" + user.Username) }>{ user.Username }</a>
+ </div>
+ <form method="post" action="/logout">
+ @csrfField()
+ <button class="text-muted transition hover:text-ink" type="submit">Sign out</button>
+ </form>
+ } else {
+ <a class="text-muted transition hover:text-ink" href="/login">Sign in</a>
+ <a class="btn btn-primary" href="/register">Register</a>
+ }
+ </div>
+ </nav>
+ </header>
+ if flashOf(ctx) != "" {
+ <div class="mx-auto max-w-5xl px-6 pt-4">
+ <div class="card flex items-center gap-2 border-accent/30 bg-accent/10 px-4 py-2.5 text-sm text-ink">
+ <span class="size-1.5 rounded-full bg-accent"></span>
+ { flashOf(ctx) }
+ </div>
</div>
- </nav>
- if flashOf(ctx) != "" {
- <div class="px-6 py-2 bg-blue-50 border-b border-blue-200 text-blue-800 text-sm">{ flashOf(ctx) }</div>
}
- <main class="p-6">
+ <main class="relative z-10 mx-auto max-w-5xl px-6 py-8">
{ children... }
</main>
</body>
</html>
}
templ csrfField() {
<input type="hidden" name="csrf_token" value={ csrfToken(ctx) }/>
}
+
+// gitLogo renders the gitgud branch-network mark. Color is inherited via currentColor.
+templ gitLogo(class string) {
+ <svg class={ class } viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
+ <circle cx="6" cy="5.5" r="2.5"></circle>
+ <circle cx="6" cy="18.5" r="2.5"></circle>
+ <circle cx="18" cy="12" r="2.5"></circle>
+ <path d="M6 8v8"></path>
+ <path d="M6 12h6.5a3 3 0 0 0 3-3V9.5"></path>
+ </svg>
+}
+
+// avatar renders a deterministic gradient avatar with the user's initial.
+templ avatar(name, class string) {
+ <span
+ class={ "inline-flex shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#1f7a48] font-semibold text-grassink", class }
+ style="font-size:.62em"
+ >{ initial(name) }</span>
+}
internal/interface/web/templates/layout_templ.go +162 −28
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Layout(title string, user *domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\" class=\"dark\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 11, Col: 17}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"stylesheet\" href=\"/static/css/main.css\"><script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\"></script></head><body><nav class=\"flex items-center justify-between px-6 py-3 border-b\"><a href=\"/\" class=\"font-bold\">gitgud</a><div class=\"flex items-center gap-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"preconnect\" href=\"https://fonts.googleapis.com\"><link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin><link href=\"https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap\" rel=\"stylesheet\"><script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\"></script><style type=\"text/tailwindcss\">\n\t\t\t\t@theme {\n\t\t\t\t\t--color-canvas: #080b09;\n\t\t\t\t\t--color-panel: #0b100d;\n\t\t\t\t\t--color-panel2: #141b16;\n\t\t\t\t\t--color-line: #1e2820;\n\t\t\t\t\t--color-line2: #25342a;\n\t\t\t\t\t--color-ink: #eef4ef;\n\t\t\t\t\t--color-muted: #8a978c;\n\t\t\t\t\t--color-faint: #54605c;\n\t\t\t\t\t--color-accent: #3fcf7f;\n\t\t\t\t\t--color-accenthi: #6fe0a0;\n\t\t\t\t\t--color-grass: #2ea04a;\n\t\t\t\t\t--color-grasshi: #34b554;\n\t\t\t\t\t--color-grassink: #06120a;\n\t\t\t\t\t--color-open: #3fcf7f;\n\t\t\t\t\t--color-closed: #ff7066;\n\t\t\t\t\t--color-merged: #a371f7;\n\t\t\t\t\t--color-warn: #e0c060;\n\t\t\t\t\t--font-sans: \"Geist\", ui-sans-serif, system-ui, sans-serif;\n\t\t\t\t\t--font-mono: \"JetBrains Mono\", ui-monospace, monospace;\n\t\t\t\t}\n\t\t\t\t@layer base {\n\t\t\t\t\thtml { color-scheme: dark; }\n\t\t\t\t\tbody { @apply bg-canvas text-ink font-sans antialiased; }\n\t\t\t\t\tbody::before {\n\t\t\t\t\t\tcontent: \"\";\n\t\t\t\t\t\tposition: fixed;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\tz-index: 0;\n\t\t\t\t\t\tbackground: radial-gradient(680px 320px at 50% -120px, rgba(63,207,127,.12), transparent 70%);\n\t\t\t\t\t}\n\t\t\t\t\ta { @apply transition-colors; }\n\t\t\t\t\tcode, pre, .mono { @apply font-mono; }\n\t\t\t\t\t::selection { background: rgba(63,207,127,.30); }\n\t\t\t\t\t::-webkit-scrollbar { width: 10px; height: 10px; }\n\t\t\t\t\t::-webkit-scrollbar-thumb { background: #25342a; border-radius: 9999px; border: 2px solid #080b09; }\n\t\t\t\t\t:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(63,207,127,.55); border-radius: 6px; }\n\t\t\t\t\tmain { animation: rise .42s cubic-bezier(.22,1,.36,1) both; }\n\t\t\t\t\t@keyframes rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }\n\t\t\t\t}\n\t\t\t\t@layer components {\n\t\t\t\t\t.btn { @apply inline-flex items-center gap-1.5 rounded-md border border-line2 bg-panel2 px-3 py-1.5 text-sm font-medium text-ink transition hover:border-faint hover:bg-line; }\n\t\t\t\t\t.btn-primary { @apply border-transparent bg-grass font-semibold text-grassink shadow-[0_0_0_1px_rgba(46,160,74,.5),0_6px_20px_-10px_rgba(63,207,127,.8)] hover:bg-grasshi hover:border-transparent; }\n\t\t\t\t\t.btn-danger { @apply text-closed hover:border-closed hover:bg-closed/10; }\n\t\t\t\t\t.input, .textarea, .select { @apply w-full rounded-md border border-line2 bg-[#0e1410] px-3 py-2 text-sm text-ink placeholder:text-faint transition focus:border-accent; }\n\t\t\t\t\t.card { @apply rounded-md border border-line bg-panel; }\n\t\t\t\t\t.link { @apply text-ink hover:text-accent; }\n\t\t\t\t\t.muted { @apply text-muted; }\n\t\t\t\t\t.meta { @apply font-mono text-xs text-faint; }\n\t\t\t\t\t.tab { @apply inline-flex items-center gap-2 border-b-2 border-transparent pb-2.5 text-sm text-muted transition hover:text-ink; }\n\t\t\t\t\t.tab-active { @apply border-accent font-semibold text-ink; }\n\t\t\t\t\t.badge { @apply inline-flex items-center gap-1 rounded border border-line2 px-2 py-0.5 text-xs font-medium text-muted; }\n\t\t\t\t\t.badge-open { @apply gap-1.5 rounded-full border-transparent bg-grass px-3 py-1 font-semibold text-grassink; }\n\t\t\t\t\t.badge-closed { @apply gap-1.5 rounded-full border-transparent bg-closed/16 px-3 py-1 font-medium text-[#ff8f86]; }\n\t\t\t\t\t.badge-merged { @apply gap-1.5 rounded-full border-transparent bg-merged/16 px-3 py-1 font-medium text-[#c8a6f7]; }\n\t\t\t\t\t.label-bug { @apply inline-flex items-center rounded-full bg-closed/16 px-2.5 py-0.5 text-[10px] font-medium text-[#ff8f86]; }\n\t\t\t\t\t.label-enh { @apply inline-flex items-center rounded-full bg-accent/16 px-2.5 py-0.5 text-[10px] font-medium text-accenthi; }\n\t\t\t\t\t.label-good { @apply inline-flex items-center rounded-full bg-warn/16 px-2.5 py-0.5 text-[10px] font-medium text-warn; }\n\t\t\t\t\t.row { @apply transition hover:bg-panel2; }\n\t\t\t\t\t.diff-add { @apply bg-accent/12 text-[#aee6c4]; }\n\t\t\t\t\t.diff-del { @apply bg-closed/12 text-[#f2b8b3]; }\n\t\t\t\t\t.diff-hunk { @apply bg-[#10171b] text-[#5aa0c8]; }\n\t\t\t\t\t.prose-dark { @apply text-sm leading-relaxed text-muted; }\n\t\t\t\t\t.prose-dark h1 { @apply mt-5 mb-3 text-xl font-semibold text-ink first:mt-0; }\n\t\t\t\t\t.prose-dark h2 { @apply mt-5 mb-2 text-lg font-semibold text-ink first:mt-0; }\n\t\t\t\t\t.prose-dark h3 { @apply mt-4 mb-2 font-semibold text-ink; }\n\t\t\t\t\t.prose-dark p { @apply my-3; }\n\t\t\t\t\t.prose-dark a { @apply text-accent hover:underline; }\n\t\t\t\t\t.prose-dark strong { @apply font-semibold text-ink; }\n\t\t\t\t\t.prose-dark ul { @apply my-3 list-disc pl-5; }\n\t\t\t\t\t.prose-dark ol { @apply my-3 list-decimal pl-5; }\n\t\t\t\t\t.prose-dark li { @apply my-1; }\n\t\t\t\t\t.prose-dark code { @apply rounded border border-line2 bg-panel2 px-1.5 py-0.5 text-[.85em] text-accent; }\n\t\t\t\t\t.prose-dark pre { @apply my-3 overflow-x-auto rounded-lg border border-line bg-panel2 p-4 text-xs; }\n\t\t\t\t\t.prose-dark pre code { @apply bg-transparent p-0; }\n\t\t\t\t\t.prose-dark blockquote { @apply my-3 border-l-2 border-line2 pl-4 text-faint; }\n\t\t\t\t\t.prose-dark hr { @apply my-5 border-line; }\n\t\t\t\t}\n\t\t\t</style></head><body><header class=\"sticky top-0 z-20 border-b border-line bg-canvas/80 backdrop-blur-xl\"><nav class=\"mx-auto flex h-14 max-w-5xl items-center justify-between px-6\"><a href=\"/\" class=\"flex items-center gap-2.5\"><span class=\"text-accent\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = gitLogo("size-5").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span> <span class=\"font-mono font-semibold tracking-tight text-ink\">gitgud</span></a><div class=\"flex items-center gap-4 text-sm\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if user != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a href=\"/new\">New</a> <span>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<a class=\"btn\" href=\"/new\">+ New</a><div class=\"flex items-center gap-2\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
+ templ_7745c5c3_Err = avatar(user.Username, "size-6").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 21, Col: 27}
+ return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<a class=\"link mono text-muted\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</span><form method=\"post\" action=\"/logout\">")
+ var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL("/" + user.Username)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 110, Col: 99}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</a></div><form method=\"post\" action=\"/logout\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<button type=\"submit\">Sign out</button></form>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<button class=\"text-muted transition hover:text-ink\" type=\"submit\">Sign out</button></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a href=\"/login\">Sign in</a> <a href=\"/register\">Register</a>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a class=\"text-muted transition hover:text-ink\" href=\"/login\">Sign in</a> <a class=\"btn btn-primary\" href=\"/register\">Register</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></nav>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div></nav></header>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if flashOf(ctx) != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"px-6 py-2 bg-blue-50 border-b border-blue-200 text-blue-800 text-sm\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"mx-auto max-w-5xl px-6 pt-4\"><div class=\"card flex items-center gap-2 border-accent/30 bg-accent/10 px-4 py-2.5 text-sm text-ink\"><span class=\"size-1.5 rounded-full bg-accent\"></span> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(flashOf(ctx))
+ var templ_7745c5c3_Var5 string
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(flashOf(ctx))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 33, Col: 99}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 127, Col: 20}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<main class=\"p-6\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<main class=\"relative z-10 mx-auto max-w-5xl px-6 py-8\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</main></body></html>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</main></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func csrfField() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var5 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var5 == nil {
- templ_7745c5c3_Var5 = templ.NopComponent
+ templ_7745c5c3_Var6 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var6 == nil {
+ templ_7745c5c3_Var6 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<input type=\"hidden\" name=\"csrf_token\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<input type=\"hidden\" name=\"csrf_token\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var6 string
- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(csrfToken(ctx))
+ var templ_7745c5c3_Var7 string
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(csrfToken(ctx))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 43, Col: 62}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 139, Col: 62}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// gitLogo renders the gitgud branch-network mark. Color is inherited via currentColor.
+func gitLogo(class string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var8 == nil {
+ templ_7745c5c3_Var8 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ var templ_7745c5c3_Var9 = []any{class}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<svg class=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var9).String())
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 1, Col: 0}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"6\" cy=\"5.5\" r=\"2.5\"></circle> <circle cx=\"6\" cy=\"18.5\" r=\"2.5\"></circle> <circle cx=\"18\" cy=\"12\" r=\"2.5\"></circle> <path d=\"M6 8v8\"></path> <path d=\"M6 12h6.5a3 3 0 0 0 3-3V9.5\"></path></svg>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+// avatar renders a deterministic gradient avatar with the user's initial.
+func avatar(name, class string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var11 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var11 == nil {
+ templ_7745c5c3_Var11 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ var templ_7745c5c3_Var12 = []any{"inline-flex shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#1f7a48] font-semibold text-grassink", class}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<span class=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var13 string
+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var12).String())
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 1, Col: 0}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" style=\"font-size:.62em\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var14 string
+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(initial(name))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 158, Col: 17}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/login.templ +24 −19
package templates
import "gitgud/internal/domain"
templ Login(user *domain.User, username, errMsg string) {
- @Layout("Log in · gitgud", user) {
- <div class="max-w-sm mx-auto">
- <h1 class="text-2xl mb-4">Log in</h1>
- if errMsg != "" {
- <p class="text-red-600 mb-3">{ errMsg }</p>
- }
- <form method="post" action="/login" class="flex flex-col gap-3">
- @csrfField()
- <label class="flex flex-col gap-1">
- <span>Username</span>
- <input class="border px-2 py-1" type="text" name="username" value={ username } autofocus/>
- </label>
- <label class="flex flex-col gap-1">
- <span>Password</span>
- <input class="border px-2 py-1" type="password" name="password"/>
- </label>
- <button class="border px-3 py-1" type="submit">Log in</button>
- </form>
- <p class="mt-3 text-sm">No account? <a href="/register">Register</a></p>
+ @Layout("Sign in · gitgud", user) {
+ <div class="mx-auto max-w-sm py-10">
+ <div class="mb-6 flex flex-col items-center gap-3">
+ <span class="text-accent">@gitLogo("size-9")</span>
+ <h1 class="text-lg font-semibold text-ink">Sign in to <span class="font-mono text-accent">gitgud</span></h1>
+ </div>
+ <div class="card p-6">
+ if errMsg != "" {
+ <div class="mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed">{ errMsg }</div>
+ }
+ <form method="post" action="/login" class="flex flex-col gap-4">
+ @csrfField()
+ <label class="flex flex-col gap-1.5">
+ <span class="text-xs font-medium text-muted">Username</span>
+ <input class="input" type="text" name="username" value={ username } autofocus/>
+ </label>
+ <label class="flex flex-col gap-1.5">
+ <span class="text-xs font-medium text-muted">Password</span>
+ <input class="input" type="password" name="password"/>
+ </label>
+ <button class="btn btn-primary mt-1 justify-center" type="submit">Sign in</button>
+ </form>
+ </div>
+ <p class="mt-4 text-center text-sm text-muted">No account? <a class="text-accent hover:underline" href="/register">Register</a></p>
</div>
}
}
internal/interface/web/templates/login_templ.go +17 −9
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Login(user *domain.User, username, errMsg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-sm mx-auto\"><h1 class=\"text-2xl mb-4\">Log in</h1>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mx-auto max-w-sm py-10\"><div class=\"mb-6 flex flex-col items-center gap-3\"><span class=\"text-accent\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = gitLogo("size-9").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span><h1 class=\"text-lg font-semibold text-ink\">Sign in to <span class=\"font-mono text-accent\">gitgud</span></h1></div><div class=\"card p-6\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if errMsg != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"text-red-600 mb-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/login.templ`, Line: 10, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/login.templ`, Line: 14, Col: 109}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<form method=\"post\" action=\"/login\" class=\"flex flex-col gap-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<form method=\"post\" action=\"/login\" class=\"flex flex-col gap-4\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<label class=\"flex flex-col gap-1\"><span>Username</span> <input class=\"border px-2 py-1\" type=\"text\" name=\"username\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<label class=\"flex flex-col gap-1.5\"><span class=\"text-xs font-medium text-muted\">Username</span> <input class=\"input\" type=\"text\" name=\"username\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(username)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/login.templ`, Line: 16, Col: 81}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/login.templ`, Line: 20, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" autofocus></label> <label class=\"flex flex-col gap-1\"><span>Password</span> <input class=\"border px-2 py-1\" type=\"password\" name=\"password\"></label> <button class=\"border px-3 py-1\" type=\"submit\">Log in</button></form><p class=\"mt-3 text-sm\">No account? <a href=\"/register\">Register</a></p></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" autofocus></label> <label class=\"flex flex-col gap-1.5\"><span class=\"text-xs font-medium text-muted\">Password</span> <input class=\"input\" type=\"password\" name=\"password\"></label> <button class=\"btn btn-primary mt-1 justify-center\" type=\"submit\">Sign in</button></form></div><p class=\"mt-4 text-center text-sm text-muted\">No account? <a class=\"text-accent hover:underline\" href=\"/register\">Register</a></p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
- templ_7745c5c3_Err = Layout("Log in · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
+ templ_7745c5c3_Err = Layout("Sign in · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/new_repo.templ +29 −25
package templates
import "gitgud/internal/domain"
templ NewRepo(user *domain.User, name, description string, private bool, errMsg string) {
@Layout("New repository · gitgud", user) {
- <div class="max-w-md mx-auto">
- <h1 class="text-2xl mb-4">New repository</h1>
- if errMsg != "" {
- <p class="text-red-600 mb-3">{ errMsg }</p>
- }
- <form method="post" action="/new" class="flex flex-col gap-3">
- @csrfField()
- <label class="flex flex-col gap-1">
- <span>Name</span>
- <input class="border px-2 py-1" type="text" name="name" value={ name } autofocus/>
- </label>
- <label class="flex flex-col gap-1">
- <span>Description</span>
- <input class="border px-2 py-1" type="text" name="description" value={ description }/>
- </label>
- <label class="flex items-center gap-2">
- if private {
- <input type="checkbox" name="private" checked/>
- } else {
- <input type="checkbox" name="private"/>
- }
- <span>Private</span>
- </label>
- <button class="border px-3 py-1" type="submit">Create repository</button>
- </form>
+ <div class="mx-auto max-w-lg">
+ <h1 class="mb-1 text-xl font-semibold tracking-tight">Create a new repository</h1>
+ <p class="mb-6 text-sm text-muted">A repository contains all your project's files and history.</p>
+ <div class="card p-6">
+ if errMsg != "" {
+ <div class="mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed">{ errMsg }</div>
+ }
+ <form method="post" action="/new" class="flex flex-col gap-4">
+ @csrfField()
+ <label class="flex flex-col gap-1.5">
+ <span class="text-xs font-medium text-muted">Repository name</span>
+ <input class="input font-mono" type="text" name="name" value={ name } placeholder="my-project" autofocus/>
+ </label>
+ <label class="flex flex-col gap-1.5">
+ <span class="text-xs font-medium text-muted">Description <span class="text-faint">(optional)</span></span>
+ <input class="input" type="text" name="description" value={ description }/>
+ </label>
+ <label class="flex cursor-pointer items-center gap-2.5 rounded-md border border-line bg-panel2 px-3 py-2.5">
+ if private {
+ <input type="checkbox" name="private" class="accent-accent" checked/>
+ } else {
+ <input type="checkbox" name="private" class="accent-accent"/>
+ }
+ <span class="text-sm text-ink">Private</span>
+ <span class="text-xs text-faint">— only you can see it</span>
+ </label>
+ <button class="btn btn-primary mt-1 justify-center" type="submit">Create repository</button>
+ </form>
+ </div>
</div>
}
}
internal/interface/web/templates/new_repo_templ.go +13 −13
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func NewRepo(user *domain.User, name, description string, private bool, errMsg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-md mx-auto\"><h1 class=\"text-2xl mb-4\">New repository</h1>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mx-auto max-w-lg\"><h1 class=\"mb-1 text-xl font-semibold tracking-tight\">Create a new repository</h1><p class=\"mb-6 text-sm text-muted\">A repository contains all your project's files and history.</p><div class=\"card p-6\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if errMsg != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"text-red-600 mb-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/new_repo.templ`, Line: 10, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/new_repo.templ`, Line: 12, Col: 109}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<form method=\"post\" action=\"/new\" class=\"flex flex-col gap-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<form method=\"post\" action=\"/new\" class=\"flex flex-col gap-4\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<label class=\"flex flex-col gap-1\"><span>Name</span> <input class=\"border px-2 py-1\" type=\"text\" name=\"name\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<label class=\"flex flex-col gap-1.5\"><span class=\"text-xs font-medium text-muted\">Repository name</span> <input class=\"input font-mono\" type=\"text\" name=\"name\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/new_repo.templ`, Line: 16, Col: 73}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/new_repo.templ`, Line: 18, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" autofocus></label> <label class=\"flex flex-col gap-1\"><span>Description</span> <input class=\"border px-2 py-1\" type=\"text\" name=\"description\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" placeholder=\"my-project\" autofocus></label> <label class=\"flex flex-col gap-1.5\"><span class=\"text-xs font-medium text-muted\">Description <span class=\"text-faint\">(optional)</span></span> <input class=\"input\" type=\"text\" name=\"description\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(description)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/new_repo.templ`, Line: 20, Col: 87}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/new_repo.templ`, Line: 22, Col: 77}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\"></label> <label class=\"flex items-center gap-2\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\"></label> <label class=\"flex cursor-pointer items-center gap-2.5 rounded-md border border-line bg-panel2 px-3 py-2.5\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if private {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<input type=\"checkbox\" name=\"private\" checked> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<input type=\"checkbox\" name=\"private\" class=\"accent-accent\" checked> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<input type=\"checkbox\" name=\"private\"> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<input type=\"checkbox\" name=\"private\" class=\"accent-accent\"> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<span>Private</span></label> <button class=\"border px-3 py-1\" type=\"submit\">Create repository</button></form></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<span class=\"text-sm text-ink\">Private</span> <span class=\"text-xs text-faint\">— only you can see it</span></label> <button class=\"btn btn-primary mt-1 justify-center\" type=\"submit\">Create repository</button></form></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("New repository · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/not_found.templ +1 −4
package templates
import "gitgud/internal/domain"
templ NotFound(user *domain.User) {
@Layout("Not found · gitgud", user) {
- <div class="max-w-2xl mx-auto">
- <h1 class="text-2xl mb-2">404</h1>
- <p>The page you're looking for doesn't exist.</p>
- </div>
+ @errorState("404", "This page doesn't exist", "The page you're looking for can't be found, or you don't have access to it.")
}
}
internal/interface/web/templates/not_found_templ.go +1 −1
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func NotFound(user *domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-2xl mx-auto\"><h1 class=\"text-2xl mb-2\">404</h1><p>The page you're looking for doesn't exist.</p></div>")
+ templ_7745c5c3_Err = errorState("404", "This page doesn't exist", "The page you're looking for can't be found, or you don't have access to it.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Not found · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/profile.templ +13 −7
package templates
import "gitgud/internal/domain"
templ Profile(user *domain.User, owner string, repos []*domain.Repository) {
@Layout(owner+" · gitgud", user) {
- <div class="max-w-2xl mx-auto">
- <h1 class="text-2xl mb-4">{ owner }</h1>
- if len(repos) == 0 {
- <p>No repositories to show.</p>
- } else {
- @repoList(repos)
- }
+ <div class="mb-6 flex items-center gap-4">
+ <div class="flex size-14 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#a78bfa] font-mono text-xl font-bold text-white shadow-[0_0_24px_-6px_rgba(110,107,240,.6)]">
+ { initial(owner) }
+ </div>
+ <div>
+ <h1 class="text-xl font-semibold tracking-tight">{ owner }</h1>
+ <p class="meta mt-0.5">{ itoa(len(repos)) } repositories</p>
+ </div>
</div>
+ if len(repos) == 0 {
+ @emptyState("Nothing here yet", "This user has no repositories to show.", "", "")
+ } else {
+ @repoList(repos)
+ }
}
}
internal/interface/web/templates/profile_templ.go +31 −9
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Profile(user *domain.User, owner string, repos []*domain.Repository) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-2xl mx-auto\"><h1 class=\"text-2xl mb-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mb-6 flex items-center gap-4\"><div class=\"flex size-14 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#a78bfa] font-mono text-xl font-bold text-white shadow-[0_0_24px_-6px_rgba(110,107,240,.6)]\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(owner)
+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(initial(owner))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/profile.templ`, Line: 8, Col: 36}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/profile.templ`, Line: 9, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div><div><h1 class=\"text-xl font-semibold tracking-tight\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(owner)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/profile.templ`, Line: 12, Col: 60}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1><p class=\"meta mt-0.5\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var5 string
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(repos)))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/profile.templ`, Line: 13, Col: 45}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " repositories</p></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(repos) == 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<p>No repositories to show.</p>")
+ templ_7745c5c3_Err = emptyState("Nothing here yet", "This user has no repositories to show.", "", "").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = repoList(repos).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(owner+" · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/pull_detail.templ +56 −41
package templates
import "gitgud/internal/domain"
templ PullDetail(user *domain.User, repo *domain.Repository, pr *domain.PullRequest, cmp *domain.Comparison, comments []*domain.PRComment, canMerge bool, errMsg string) {
@Layout(pr.Title+" · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "pulls")
- <div class="flex items-center gap-2 mb-1">
- <h2 class="text-xl">{ pr.Title } <span class="text-gray-400">#{ itoa(pr.Number) }</span></h2>
- <span class="text-xs border px-2 py-0.5">{ string(pr.State) }</span>
- </div>
- <div class="text-xs text-gray-500 mb-4">
- { pr.AuthorName } wants to merge <code>{ pr.HeadBranch }</code> into <code>{ pr.BaseBranch }</code>
- </div>
- if errMsg != "" {
- <p class="text-red-600 mb-3">{ errMsg }</p>
+ @repoHeader(repo, "pulls")
+ <h2 class="mb-2 text-2xl font-semibold tracking-tight text-ink">{ pr.Title } <span class="font-normal text-faint">#{ itoa(pr.Number) }</span></h2>
+ <div class="mb-6 flex flex-wrap items-center gap-3">
+ if pr.State == domain.PROpen {
+ <span class="badge-open"><span class="size-2 rounded-full border-2 border-grassink"></span> Open</span>
+ } else if pr.State == domain.PRMerged {
+ <span class="badge-merged"><span class="size-2 rounded-full bg-current"></span> Merged</span>
+ } else {
+ <span class="badge-closed"><span class="size-2 rounded-full border-2 border-current"></span> Closed</span>
}
- @commentCard(pr.AuthorName, fmtTime(pr.CreatedAt), pr.Body)
- for _, c := range comments {
- @commentCard(c.AuthorName, fmtTime(c.CreatedAt), c.Body)
- }
- <div class="border p-3 mb-4">
- if pr.State == domain.PRMerged {
- <div class="text-purple-700">This pull request was merged.</div>
- } else if pr.State == domain.PRClosed {
- <div class="text-gray-600">This pull request was closed.</div>
- } else if canMerge {
- <form method="post" action={ templ.SafeURL(repoPath(repo, "/pulls/"+itoa(pr.Number)+"/merge")) }>
+ <span class="text-sm text-muted">
+ <span class="font-medium text-ink">{ pr.AuthorName }</span> wants to merge <span class="badge font-mono text-accent">{ pr.HeadBranch }</span> into <span class="badge font-mono text-accent">{ pr.BaseBranch }</span>
+ </span>
+ </div>
+ if errMsg != "" {
+ <div class="mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed">{ errMsg }</div>
+ }
+ @commentCard(pr.AuthorName, fmtTime(pr.CreatedAt), pr.Body)
+ for _, c := range comments {
+ @commentCard(c.AuthorName, fmtTime(c.CreatedAt), c.Body)
+ }
+ <div class="card mb-6 p-4">
+ if pr.State == domain.PRMerged {
+ <div class="flex items-center gap-2 text-merged"><span class="size-2 rounded-full bg-merged"></span> This pull request was merged.</div>
+ } else if pr.State == domain.PRClosed {
+ <div class="flex items-center gap-2 text-muted"><span class="size-2 rounded-full bg-faint"></span> This pull request was closed.</div>
+ } else if canMerge {
+ <div class="-mx-4 -mb-4 overflow-hidden rounded-md border border-accent/30">
+ <div class="flex items-center gap-3 bg-accent/[.07] px-4 py-3.5">
+ <span class="flex size-7 shrink-0 items-center justify-center rounded-full bg-grass font-bold text-grassink">✓</span>
+ <div>
+ <div class="text-sm font-semibold text-ink">This branch has no conflicts with the base branch</div>
+ <div class="text-xs text-muted">Merging can be performed automatically.</div>
+ </div>
+ </div>
+ <form class="flex gap-2 px-4 pb-4" method="post" action={ templ.SafeURL(repoPath(repo, "/pulls/"+itoa(pr.Number)+"/merge")) }>
@csrfField()
- <button class="border px-3 py-1 bg-green-700 text-white" type="submit">Merge pull request</button>
+ <button class="btn btn-primary" type="submit">Merge pull request</button>
</form>
- } else if user != nil {
- <div class="text-gray-600">You cannot merge this pull request.</div>
- } else {
- <div class="text-gray-600"><a href="/login">Sign in</a> to act on this pull request.</div>
- }
- </div>
- if cmp != nil {
- <h3 class="text-md mb-2">Commits</h3>
- @commitsList(repo, cmp.Commits)
- <h3 class="text-md mb-2">Files changed</h3>
- @diffFiles(cmp.Files)
- }
- if user != nil {
- <form method="post" action={ templ.SafeURL(repoPath(repo, "/pulls/"+itoa(pr.Number)+"/comments")) } class="flex flex-col gap-2 mt-4">
- @csrfField()
- <textarea class="border px-2 py-1" name="body" rows="4" placeholder="Leave a comment (markdown supported)"></textarea>
- <div><button class="border px-3 py-1" type="submit">Comment</button></div>
- </form>
+ </div>
+ } else if user != nil {
+ <div class="text-sm text-muted">You don't have permission to merge this pull request.</div>
+ } else {
+ <div class="text-sm text-muted"><a class="text-accent hover:underline" href="/login">Sign in</a> to act on this pull request.</div>
}
</div>
+ if cmp != nil {
+ <h3 class="mb-2 text-sm font-semibold text-muted">{ itoa(len(cmp.Commits)) } commits</h3>
+ @commitsList(repo, cmp.Commits)
+ <h3 class="mb-2 text-sm font-semibold text-muted">Files changed</h3>
+ @diffFiles(cmp.Files)
+ }
+ if user != nil {
+ <form method="post" action={ templ.SafeURL(repoPath(repo, "/pulls/"+itoa(pr.Number)+"/comments")) } class="mt-4 flex flex-col gap-3">
+ @csrfField()
+ <textarea class="textarea" name="body" rows="4" placeholder="Leave a comment… (markdown supported)"></textarea>
+ <div class="flex justify-end">
+ <button class="btn btn-primary" type="submit">Comment</button>
+ </div>
+ </form>
+ }
}
}
internal/interface/web/templates/pull_detail_templ.go +77 −57
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func PullDetail(user *domain.User, repo *domain.Repository, pr *domain.PullRequest, cmp *domain.Comparison, comments []*domain.PRComment, canMerge bool, errMsg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "pulls").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex items-center gap-2 mb-1\"><h2 class=\"text-xl\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <h2 class=\"mb-2 text-2xl font-semibold tracking-tight text-ink\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(pr.Title)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 10, Col: 34}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 8, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " <span class=\"text-gray-400\">#")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " <span class=\"font-normal text-faint\">#")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(pr.Number))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 10, Col: 83}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 8, Col: 134}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</span></h2><span class=\"text-xs border px-2 py-0.5\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></h2><div class=\"mb-6 flex flex-wrap items-center gap-3\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if pr.State == domain.PROpen {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<span class=\"badge-open\"><span class=\"size-2 rounded-full border-2 border-grassink\"></span> Open</span> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else if pr.State == domain.PRMerged {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<span class=\"badge-merged\"><span class=\"size-2 rounded-full bg-current\"></span> Merged</span> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<span class=\"badge-closed\"><span class=\"size-2 rounded-full border-2 border-current\"></span> Closed</span> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<span class=\"text-sm text-muted\"><span class=\"font-medium text-ink\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(string(pr.State))
+ templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(pr.AuthorName)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 11, Col: 63}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 18, Col: 54}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</span></div><div class=\"text-xs text-gray-500 mb-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</span> wants to merge <span class=\"badge font-mono text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(pr.AuthorName)
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(pr.HeadBranch)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 14, Col: 19}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 18, Col: 136}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " wants to merge <code>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</span> into <span class=\"badge font-mono text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(pr.HeadBranch)
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(pr.BaseBranch)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 14, Col: 58}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 18, Col: 208}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</code> into <code>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var8 string
- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(pr.BaseBranch)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 14, Col: 94}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</code></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</span></span></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if errMsg != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<p class=\"text-red-600 mb-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var9 string
- templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 17, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 22, Col: 107}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
templ_7745c5c3_Err = commentCard(pr.AuthorName, fmtTime(pr.CreatedAt), pr.Body).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, c := range comments {
templ_7745c5c3_Err = commentCard(c.AuthorName, fmtTime(c.CreatedAt), c.Body).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"border p-3 mb-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " <div class=\"card mb-6 p-4\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if pr.State == domain.PRMerged {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"text-purple-700\">This pull request was merged.</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<div class=\"flex items-center gap-2 text-merged\"><span class=\"size-2 rounded-full bg-merged\"></span> This pull request was merged.</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else if pr.State == domain.PRClosed {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<div class=\"text-gray-600\">This pull request was closed.</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div class=\"flex items-center gap-2 text-muted\"><span class=\"size-2 rounded-full bg-faint\"></span> This pull request was closed.</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else if canMerge {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<form method=\"post\" action=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<div class=\"-mx-4 -mb-4 overflow-hidden rounded-md border border-accent/30\"><div class=\"flex items-center gap-3 bg-accent/[.07] px-4 py-3.5\"><span class=\"flex size-7 shrink-0 items-center justify-center rounded-full bg-grass font-bold text-grassink\">✓</span><div><div class=\"text-sm font-semibold text-ink\">This branch has no conflicts with the base branch</div><div class=\"text-xs text-muted\">Merging can be performed automatically.</div></div></div><form class=\"flex gap-2 px-4 pb-4\" method=\"post\" action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var10 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls/"+itoa(pr.Number)+"/merge"))
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10)))
+ var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls/"+itoa(pr.Number)+"/merge"))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<button class=\"border px-3 py-1 bg-green-700 text-white\" type=\"submit\">Merge pull request</button></form>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<button class=\"btn btn-primary\" type=\"submit\">Merge pull request</button></form></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else if user != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<div class=\"text-gray-600\">You cannot merge this pull request.</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<div class=\"text-sm text-muted\">You don't have permission to merge this pull request.</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<div class=\"text-gray-600\"><a href=\"/login\">Sign in</a> to act on this pull request.</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<div class=\"text-sm text-muted\"><a class=\"text-accent hover:underline\" href=\"/login\">Sign in</a> to act on this pull request.</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if cmp != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<h3 class=\"text-md mb-2\">Commits</h3>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<h3 class=\"mb-2 text-sm font-semibold text-muted\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(cmp.Commits)))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pull_detail.templ`, Line: 54, Col: 77}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " commits</h3>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = commitsList(repo, cmp.Commits).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " <h3 class=\"text-md mb-2\">Files changed</h3>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " <h3 class=\"mb-2 text-sm font-semibold text-muted\">Files changed</h3>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = diffFiles(cmp.Files).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
if user != nil {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<form method=\"post\" action=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<form method=\"post\" action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls/"+itoa(pr.Number)+"/comments"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" class=\"flex flex-col gap-2 mt-4\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" class=\"mt-4 flex flex-col gap-3\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<textarea class=\"border px-2 py-1\" name=\"body\" rows=\"4\" placeholder=\"Leave a comment (markdown supported)\"></textarea><div><button class=\"border px-3 py-1\" type=\"submit\">Comment</button></div></form>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<textarea class=\"textarea\" name=\"body\" rows=\"4\" placeholder=\"Leave a comment… (markdown supported)\"></textarea><div class=\"flex justify-end\"><button class=\"btn btn-primary\" type=\"submit\">Comment</button></div></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(pr.Title+" · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/pulls_list.templ +34 −21
package templates
import "gitgud/internal/domain"
templ PullsList(user *domain.User, repo *domain.Repository, state string, prs []*domain.PullRequest, openCount, mergedCount, closedCount int) {
@Layout("Pull requests · "+repo.Name, user) {
- <div class="max-w-3xl mx-auto">
- @repoHeader(repo, "pulls")
- <div class="flex items-center justify-between mb-3">
- <div class="flex gap-4 text-sm">
- <a class={ stateTabClass(state, "open") } href={ templ.SafeURL(repoPath(repo, "/pulls?state=open")) }>{ itoa(openCount) } Open</a>
- <a class={ stateTabClass(state, "merged") } href={ templ.SafeURL(repoPath(repo, "/pulls?state=merged")) }>{ itoa(mergedCount) } Merged</a>
- <a class={ stateTabClass(state, "closed") } href={ templ.SafeURL(repoPath(repo, "/pulls?state=closed")) }>{ itoa(closedCount) } Closed</a>
- </div>
- <a class="border px-3 py-1 text-sm" href={ templ.SafeURL(repoPath(repo, "/compare")) }>New pull request</a>
+ @repoHeader(repo, "pulls")
+ <div class="mb-4 flex items-center justify-between">
+ <div class="flex gap-5 text-sm">
+ <a class={ stateTabClass(state, "open") } href={ templ.SafeURL(repoPath(repo, "/pulls?state=open")) }>{ itoa(openCount) } Open</a>
+ <a class={ stateTabClass(state, "merged") } href={ templ.SafeURL(repoPath(repo, "/pulls?state=merged")) }>{ itoa(mergedCount) } Merged</a>
+ <a class={ stateTabClass(state, "closed") } href={ templ.SafeURL(repoPath(repo, "/pulls?state=closed")) }>{ itoa(closedCount) } Closed</a>
</div>
- if len(prs) == 0 {
- <p class="text-gray-500">No pull requests to show.</p>
- } else {
- <ul class="border">
- for _, p := range prs {
- <li class="border-b px-3 py-2">
- <a href={ templ.SafeURL(repoPath(repo, "/pulls/"+itoa(p.Number))) }>{ p.Title }</a>
- <div class="text-xs text-gray-500">#{ itoa(p.Number) } · { string(p.State) } · { p.HeadBranch } → { p.BaseBranch } · by { p.AuthorName }</div>
- </li>
- }
- </ul>
- }
+ <a class="btn btn-primary" href={ templ.SafeURL(repoPath(repo, "/compare")) }>+ New pull request</a>
</div>
+ if len(prs) == 0 {
+ @emptyState("No pull requests", "There are no "+state+" pull requests in this repository.", "", "")
+ } else {
+ <div class="card overflow-hidden">
+ for _, p := range prs {
+ <div class="row border-b border-line px-4 py-3 last:border-0">
+ <a class="flex items-start gap-2.5" href={ templ.SafeURL(repoPath(repo, "/pulls/"+itoa(p.Number))) }>
+ @prDot(string(p.State))
+ <span class="min-w-0">
+ <span class="block text-ink hover:text-accent">{ p.Title }</span>
+ <span class="meta">#{ itoa(p.Number) } · <span class="font-mono">{ p.HeadBranch }</span> → <span class="font-mono">{ p.BaseBranch }</span> · by { p.AuthorName }</span>
+ </span>
+ </a>
+ </div>
+ }
+ </div>
+ }
+ }
+}
+
+templ prDot(state string) {
+ if state == "open" {
+ <span class="mt-1 size-3.5 shrink-0 rounded-full border-2 border-accent"></span>
+ } else if state == "merged" {
+ <span class="mt-1 size-3.5 shrink-0 rounded-full border-2 border-merged"></span>
+ } else {
+ <span class="mt-1 size-3.5 shrink-0 rounded-full border-2 border-faint"></span>
}
}
internal/interface/web/templates/pulls_list_templ.go +84 −56
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func PullsList(user *domain.User, repo *domain.Repository, state string, prs []*domain.PullRequest, openCount, mergedCount, closedCount int) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-3xl mx-auto\">")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
templ_7745c5c3_Err = repoHeader(repo, "pulls").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex items-center justify-between mb-3\"><div class=\"flex gap-4 text-sm\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mb-4 flex items-center justify-between\"><div class=\"flex gap-5 text-sm\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 = []any{stateTabClass(state, "open")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a class=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<a class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var3).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls?state=open"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(openCount))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 11, Col: 124}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 10, Col: 123}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " Open</a> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " Open</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 = []any{stateTabClass(state, "merged")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<a class=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var7).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls?state=merged"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(mergedCount))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 12, Col: 130}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 11, Col: 129}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " Merged</a> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " Merged</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 = []any{stateTabClass(state, "closed")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<a class=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<a class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var11).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls?state=closed"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var13)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(closedCount))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 13, Col: 130}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 12, Col: 129}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " Closed</a></div><a class=\"border px-3 py-1 text-sm\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " Closed</a></div><a class=\"btn btn-primary\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 templ.SafeURL = templ.SafeURL(repoPath(repo, "/compare"))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var15)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">New pull request</a></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\">+ New pull request</a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(prs) == 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<p class=\"text-gray-500\">No pull requests to show.</p>")
+ templ_7745c5c3_Err = emptyState("No pull requests", "There are no "+state+" pull requests in this repository.", "", "").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<ul class=\"border\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<div class=\"card overflow-hidden\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, p := range prs {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<li class=\"border-b px-3 py-2\"><a href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div class=\"row border-b border-line px-4 py-3 last:border-0\"><a class=\"flex items-start gap-2.5\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var16 templ.SafeURL = templ.SafeURL(repoPath(repo, "/pulls/"+itoa(p.Number)))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var16)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = prDot(string(p.State)).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<span class=\"min-w-0\"><span class=\"block text-ink hover:text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(p.Title)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 23, Col: 84}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 25, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</a><div class=\"text-xs text-gray-500\">#")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</span> <span class=\"meta\">#")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Number))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 24, Col: 59}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 26, Col: 44}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " · ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " · <span class=\"font-mono\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var19 string
- templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(string(p.State))
+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(p.HeadBranch)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 24, Col: 82}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 26, Col: 88}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, " · ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</span> → <span class=\"font-mono\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var20 string
- templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(p.HeadBranch)
+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(p.BaseBranch)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 24, Col: 102}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 26, Col: 140}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " → ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</span> · by ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var21 string
- templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(p.BaseBranch)
+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(p.AuthorName)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 24, Col: 123}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 26, Col: 170}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " · by ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var22 string
- templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(p.AuthorName)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/pulls_list.templ`, Line: 24, Col: 146}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</div></li>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</span></span></a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</ul>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</div>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
return nil
})
templ_7745c5c3_Err = Layout("Pull requests · "+repo.Name, user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func prDot(state string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var22 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var22 == nil {
+ templ_7745c5c3_Var22 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ if state == "open" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<span class=\"mt-1 size-3.5 shrink-0 rounded-full border-2 border-accent\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else if state == "merged" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<span class=\"mt-1 size-3.5 shrink-0 rounded-full border-2 border-merged\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<span class=\"mt-1 size-3.5 shrink-0 rounded-full border-2 border-faint\"></span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/register.templ +25 −22
package templates
import "gitgud/internal/domain"
templ Register(user *domain.User, username, email, errMsg string) {
@Layout("Register · gitgud", user) {
- <div class="max-w-sm mx-auto">
- <h1 class="text-2xl mb-4">Register</h1>
- if errMsg != "" {
- <p class="text-red-600 mb-3">{ errMsg }</p>
- }
- <form method="post" action="/register" class="flex flex-col gap-3">
- @csrfField()
- <label class="flex flex-col gap-1">
- <span>Username</span>
- <input class="border px-2 py-1" type="text" name="username" value={ username } autofocus/>
- </label>
- <label class="flex flex-col gap-1">
- <span>Email</span>
- <input class="border px-2 py-1" type="email" name="email" value={ email }/>
- </label>
- <label class="flex flex-col gap-1">
- <span>Password</span>
- <input class="border px-2 py-1" type="password" name="password"/>
- </label>
- <button class="border px-3 py-1" type="submit">Create account</button>
- </form>
- <p class="mt-3 text-sm">Already have an account? <a href="/login">Log in</a></p>
+ <div class="mx-auto max-w-sm py-10">
+ <h1 class="mb-1 text-center text-2xl font-semibold tracking-tight">Create your account</h1>
+ <p class="mb-6 text-center text-sm text-muted">Start hosting repositories on gitgud</p>
+ <div class="card p-6">
+ if errMsg != "" {
+ <div class="mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed">{ errMsg }</div>
+ }
+ <form method="post" action="/register" class="flex flex-col gap-4">
+ @csrfField()
+ <label class="flex flex-col gap-1.5">
+ <span class="text-xs font-medium text-muted">Username</span>
+ <input class="input" type="text" name="username" value={ username } autofocus/>
+ </label>
+ <label class="flex flex-col gap-1.5">
+ <span class="text-xs font-medium text-muted">Email</span>
+ <input class="input" type="email" name="email" value={ email }/>
+ </label>
+ <label class="flex flex-col gap-1.5">
+ <span class="text-xs font-medium text-muted">Password</span>
+ <input class="input" type="password" name="password"/>
+ </label>
+ <button class="btn btn-primary mt-1 justify-center" type="submit">Create account</button>
+ </form>
+ </div>
+ <p class="mt-4 text-center text-sm text-muted">Already have an account? <a class="text-accent hover:underline" href="/login">Sign in</a></p>
</div>
}
}
internal/interface/web/templates/register_templ.go +10 −10
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Register(user *domain.User, username, email, errMsg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-sm mx-auto\"><h1 class=\"text-2xl mb-4\">Register</h1>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mx-auto max-w-sm py-10\"><h1 class=\"mb-1 text-center text-2xl font-semibold tracking-tight\">Create your account</h1><p class=\"mb-6 text-center text-sm text-muted\">Start hosting repositories on gitgud</p><div class=\"card p-6\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if errMsg != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"text-red-600 mb-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"mb-4 rounded-md border border-closed/30 bg-closed/10 px-3 py-2 text-sm text-closed\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/register.templ`, Line: 10, Col: 41}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/register.templ`, Line: 12, Col: 109}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<form method=\"post\" action=\"/register\" class=\"flex flex-col gap-3\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<form method=\"post\" action=\"/register\" class=\"flex flex-col gap-4\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<label class=\"flex flex-col gap-1\"><span>Username</span> <input class=\"border px-2 py-1\" type=\"text\" name=\"username\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<label class=\"flex flex-col gap-1.5\"><span class=\"text-xs font-medium text-muted\">Username</span> <input class=\"input\" type=\"text\" name=\"username\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(username)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/register.templ`, Line: 16, Col: 81}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/register.templ`, Line: 18, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" autofocus></label> <label class=\"flex flex-col gap-1\"><span>Email</span> <input class=\"border px-2 py-1\" type=\"email\" name=\"email\" value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" autofocus></label> <label class=\"flex flex-col gap-1.5\"><span class=\"text-xs font-medium text-muted\">Email</span> <input class=\"input\" type=\"email\" name=\"email\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(email)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/register.templ`, Line: 20, Col: 76}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/register.templ`, Line: 22, Col: 66}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\"></label> <label class=\"flex flex-col gap-1\"><span>Password</span> <input class=\"border px-2 py-1\" type=\"password\" name=\"password\"></label> <button class=\"border px-3 py-1\" type=\"submit\">Create account</button></form><p class=\"mt-3 text-sm\">Already have an account? <a href=\"/login\">Log in</a></p></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\"></label> <label class=\"flex flex-col gap-1.5\"><span class=\"text-xs font-medium text-muted\">Password</span> <input class=\"input\" type=\"password\" name=\"password\"></label> <button class=\"btn btn-primary mt-1 justify-center\" type=\"submit\">Create account</button></form></div><p class=\"mt-4 text-center text-sm text-muted\">Already have an account? <a class=\"text-accent hover:underline\" href=\"/login\">Sign in</a></p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout("Register · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/repo_header.templ +25 −19
package templates
import "gitgud/internal/domain"
templ repoHeader(repo *domain.Repository, active string) {
- <div class="border-b mb-4 pb-2">
- <div class="flex items-center gap-2 mb-2">
- <h1 class="text-xl">
- <a href={ templ.SafeURL("/" + repo.OwnerName) }>{ repo.OwnerName }</a>
- <span>/</span>
- <a class="font-semibold" href={ templ.SafeURL(repoPath(repo, "")) }>{ repo.Name }</a>
+ <div class="mb-6">
+ <div class="mb-4 flex items-center gap-3">
+ <span class="text-accent">@gitLogo("size-5")</span>
+ <h1 class="flex items-center gap-1.5 font-mono text-[15px]">
+ <a class="text-accent hover:underline" href={ templ.SafeURL("/" + repo.OwnerName) }>{ repo.OwnerName }</a>
+ <span class="text-faint">/</span>
+ <a class="font-semibold text-ink hover:text-accent" href={ templ.SafeURL(repoPath(repo, "")) }>{ repo.Name }</a>
</h1>
if repo.IsPrivate {
- <span class="text-xs border px-1">private</span>
+ <span class="badge"><span class="size-1.5 rounded-full bg-warn"></span> private</span>
+ } else {
+ <span class="badge">public</span>
}
</div>
- <nav class="flex gap-4 text-sm">
+ <nav class="flex gap-1 border-b border-line">
@repoTab(repoPath(repo, ""), "Code", active == "code")
@repoTab(repoPath(repo, "/issues"), "Issues", active == "issues")
- @repoTab(repoPath(repo, "/pulls"), "Pulls", active == "pulls")
+ @repoTab(repoPath(repo, "/pulls"), "Pull requests", active == "pulls")
</nav>
</div>
}
templ repoTab(href, label string, current bool) {
if current {
- <a class="font-bold border-b-2 border-black pb-1" href={ templ.SafeURL(href) }>{ label }</a>
+ <a class="tab tab-active px-3" href={ templ.SafeURL(href) }>{ label }</a>
} else {
- <a class="pb-1 text-gray-600" href={ templ.SafeURL(href) }>{ label }</a>
+ <a class="tab px-3" href={ templ.SafeURL(href) }>{ label }</a>
}
}
templ branchSwitcher(repo *domain.Repository, ref string, branches []string) {
- <select class="border px-2 py-1 text-sm" onchange="location.href=this.value">
- for _, b := range branches {
- if b == ref {
- <option value={ repoPath(repo, "/tree/" + b) } selected>{ b }</option>
- } else {
- <option value={ repoPath(repo, "/tree/" + b) }>{ b }</option>
+ <div class="relative inline-flex">
+ <select class="select w-auto cursor-pointer appearance-none py-1.5 pr-9 pl-3 font-mono text-xs" onchange="location.href=this.value">
+ for _, b := range branches {
+ if b == ref {
+ <option value={ repoPath(repo, "/tree/" + b) } selected>{ b }</option>
+ } else {
+ <option value={ repoPath(repo, "/tree/" + b) }>{ b }</option>
+ }
}
- }
- </select>
+ </select>
+ <span class="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-faint">▾</span>
+ </div>
}
internal/interface/web/templates/repo_header_templ.go +44 −31
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func repoHeader(repo *domain.Repository, active string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"border-b mb-4 pb-2\"><div class=\"flex items-center gap-2 mb-2\"><h1 class=\"text-xl\"><a href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mb-6\"><div class=\"mb-4 flex items-center gap-3\"><span class=\"text-accent\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = gitLogo("size-5").Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span><h1 class=\"flex items-center gap-1.5 font-mono text-[15px]\"><a class=\"text-accent hover:underline\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 templ.SafeURL = templ.SafeURL("/" + repo.OwnerName)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(repo.OwnerName)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 9, Col: 68}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 10, Col: 104}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</a> <span>/</span> <a class=\"font-semibold\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</a> <span class=\"text-faint\">/</span> <a class=\"font-semibold text-ink hover:text-accent\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 templ.SafeURL = templ.SafeURL(repoPath(repo, ""))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 11, Col: 83}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 12, Col: 110}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</a></h1>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a></h1>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if repo.IsPrivate {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<span class=\"text-xs border px-1\">private</span>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<span class=\"badge\"><span class=\"size-1.5 rounded-full bg-warn\"></span> private</span>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<span class=\"badge\">public</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div><nav class=\"flex gap-4 text-sm\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div><nav class=\"flex gap-1 border-b border-line\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = repoTab(repoPath(repo, ""), "Code", active == "code").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = repoTab(repoPath(repo, "/issues"), "Issues", active == "issues").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = repoTab(repoPath(repo, "/pulls"), "Pulls", active == "pulls").Render(ctx, templ_7745c5c3_Buffer)
+ templ_7745c5c3_Err = repoTab(repoPath(repo, "/pulls"), "Pull requests", active == "pulls").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</nav></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</nav></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func repoTab(href, label string, current bool) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
if templ_7745c5c3_Var6 == nil {
templ_7745c5c3_Var6 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
if current {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a class=\"font-bold border-b-2 border-black pb-1\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<a class=\"tab tab-active px-3\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(href)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(label)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 27, Col: 88}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 30, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</a>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<a class=\"pb-1 text-gray-600\" href=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<a class=\"tab px-3\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 templ.SafeURL = templ.SafeURL(href)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(label)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 29, Col: 68}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 32, Col: 58}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</a>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
return nil
})
}
func branchSwitcher(repo *domain.Repository, ref string, branches []string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
if templ_7745c5c3_Var11 == nil {
templ_7745c5c3_Var11 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<select class=\"border px-2 py-1 text-sm\" onchange=\"location.href=this.value\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<div class=\"relative inline-flex\"><select class=\"select w-auto cursor-pointer appearance-none py-1.5 pr-9 pl-3 font-mono text-xs\" onchange=\"location.href=this.value\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, b := range branches {
if b == ref {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<option value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<option value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(repoPath(repo, "/tree/"+b))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 37, Col: 48}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 41, Col: 49}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" selected>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" selected>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(b)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 37, Col: 63}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 41, Col: 64}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</option>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</option>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<option value=\"")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<option value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(repoPath(repo, "/tree/"+b))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 39, Col: 48}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 43, Col: 49}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(b)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 39, Col: 54}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_header.templ`, Line: 43, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</option>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</option>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</select>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</select> <span class=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-faint\">▾</span></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/repo_home.templ +10 −14
package templates
import "gitgud/internal/domain"
templ RepoHome(user *domain.User, repo *domain.Repository) {
@Layout(repo.OwnerName+"/"+repo.Name+" · gitgud", user) {
- <div class="max-w-2xl mx-auto">
- <div class="flex items-center gap-2 mb-4">
- <h1 class="text-2xl">
- <a href={ templ.SafeURL("/" + repo.OwnerName) }>{ repo.OwnerName }</a> / { repo.Name }
- </h1>
- if repo.IsPrivate {
- <span class="text-xs border px-1">private</span>
- }
+ @repoHeader(repo, "code")
+ if repo.Description != "" {
+ <p class="mb-6 text-sm text-muted">{ repo.Description }</p>
+ }
+ <div class="card overflow-hidden">
+ <div class="border-b border-line px-5 py-3">
+ <h2 class="font-semibold text-ink">Quick setup</h2>
+ <p class="meta mt-0.5">This repository is empty. Push your first commit to get started.</p>
</div>
- if repo.Description != "" {
- <p class="mb-4 text-gray-600">{ repo.Description }</p>
- }
- <div class="border p-4">
- <h2 class="mb-2">Quick setup — create a repo on the command line</h2>
- <pre class="bg-gray-100 p-3 text-sm overflow-x-auto">{ cloneInstructions(repo) }</pre>
+ <div class="bg-panel2 p-5">
+ <pre class="overflow-x-auto font-mono text-xs leading-relaxed text-muted">{ cloneInstructions(repo) }</pre>
</div>
</div>
}
}
internal/interface/web/templates/repo_home_templ.go +14 −55
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func RepoHome(user *domain.User, repo *domain.Repository) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"max-w-2xl mx-auto\"><div class=\"flex items-center gap-2 mb-4\"><h1 class=\"text-2xl\"><a href=\"")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL("/" + repo.OwnerName)
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">")
+ templ_7745c5c3_Err = repoHeader(repo, "code").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(repo.OwnerName)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_home.templ`, Line: 10, Col: 69}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</a> / ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var5 string
- templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Name)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_home.templ`, Line: 10, Col: 89}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</h1>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if repo.IsPrivate {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<span class=\"text-xs border px-1\">private</span>")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if repo.Description != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<p class=\"mb-4 text-gray-600\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<p class=\"mb-6 text-sm text-muted\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var6 string
- templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Description)
+ var templ_7745c5c3_Var3 string
+ templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(repo.Description)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_home.templ`, Line: 17, Col: 52}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_home.templ`, Line: 9, Col: 56}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</p>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<div class=\"border p-4\"><h2 class=\"mb-2\">Quick setup — create a repo on the command line</h2><pre class=\"bg-gray-100 p-3 text-sm overflow-x-auto\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " <div class=\"card overflow-hidden\"><div class=\"border-b border-line px-5 py-3\"><h2 class=\"font-semibold text-ink\">Quick setup</h2><p class=\"meta mt-0.5\">This repository is empty. Push your first commit to get started.</p></div><div class=\"bg-panel2 p-5\"><pre class=\"overflow-x-auto font-mono text-xs leading-relaxed text-muted\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var7 string
- templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(cloneInstructions(repo))
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(cloneInstructions(repo))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_home.templ`, Line: 21, Col: 82}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/repo_home.templ`, Line: 17, Col: 103}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</pre></div></div>")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</pre></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(repo.OwnerName+"/"+repo.Name+" · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate