forked from tangled.org/core
this repo has no description

switch to SSR lucide-icons

+36
appview/pages/funcmap.go
···
"fmt"
"html"
"html/template"
"reflect"
"strings"
···
"list": func(args ...any) []any {
return args
},
}
}
···
"fmt"
"html"
"html/template"
+
"log"
+
"path/filepath"
"reflect"
"strings"
···
"list": func(args ...any) []any {
return args
},
+
"i": func(name string, classes ...string) template.HTML {
+
data, err := icon(name, classes)
+
if err != nil {
+
log.Printf("icon %s does not exist", name)
+
data, _ = icon("airplay", classes)
+
}
+
return template.HTML(data)
+
},
}
}
+
+
func icon(name string, classes []string) (template.HTML, error) {
+
iconPath := filepath.Join("static", "icons", name)
+
+
if filepath.Ext(name) == "" {
+
iconPath += ".svg"
+
}
+
+
data, err := Files.ReadFile(iconPath)
+
if err != nil {
+
return "", fmt.Errorf("icon %s not found: %w", name, err)
+
}
+
+
// Convert SVG data to string
+
svgStr := string(data)
+
+
svgTagEnd := strings.Index(svgStr, ">")
+
if svgTagEnd == -1 {
+
return "", fmt.Errorf("invalid SVG format for icon %s", name)
+
}
+
+
classTag := ` class="` + strings.Join(classes, " ") + `"`
+
+
modifiedSVG := svgStr[:svgTagEnd] + classTag + svgStr[svgTagEnd:]
+
return template.HTML(modifiedSVG), nil
+
}
+6 -6
appview/pages/pages.go
···
"github.com/sotangled/tangled/types"
)
-
//go:embed templates/* static/*
-
var files embed.FS
type Pages struct {
t map[string]*template.Template
···
templates := make(map[string]*template.Template)
// Walk through embedded templates directory and parse all .html files
-
err := fs.WalkDir(files, "templates", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
···
if strings.HasPrefix(path, "templates/fragments/") {
tmpl, err := template.New(name).
Funcs(funcMap()).
-
ParseFS(files, path)
if err != nil {
return fmt.Errorf("setting up fragment: %w", err)
}
···
// Add the page template on top of the base
tmpl, err := template.New(name).
Funcs(funcMap()).
-
ParseFS(files, "templates/layouts/*.html", "templates/fragments/*.html", path)
if err != nil {
return fmt.Errorf("setting up template: %w", err)
}
···
}
func (p *Pages) Static() http.Handler {
-
sub, err := fs.Sub(files, "static")
if err != nil {
log.Fatalf("no static dir found? that's crazy: %v", err)
}
···
"github.com/sotangled/tangled/types"
)
+
//go:embed templates/* static
+
var Files embed.FS
type Pages struct {
t map[string]*template.Template
···
templates := make(map[string]*template.Template)
// Walk through embedded templates directory and parse all .html files
+
err := fs.WalkDir(Files, "templates", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
···
if strings.HasPrefix(path, "templates/fragments/") {
tmpl, err := template.New(name).
Funcs(funcMap()).
+
ParseFS(Files, path)
if err != nil {
return fmt.Errorf("setting up fragment: %w", err)
}
···
// Add the page template on top of the base
tmpl, err := template.New(name).
Funcs(funcMap()).
+
ParseFS(Files, "templates/layouts/*.html", "templates/fragments/*.html", path)
if err != nil {
return fmt.Errorf("setting up template: %w", err)
}
···
}
func (p *Pages) Static() http.Handler {
+
sub, err := fs.Sub(Files, "static")
if err != nil {
log.Fatalf("no static dir found? that's crazy: %v", err)
}
appview/pages/static/.gitkeep

This is a binary file and will not be displayed.

+4 -4
appview/pages/templates/fragments/diff.html
···
<a {{if $parent}}href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}"{{end}}>
{{ .Name.Old }}
</a>
-
<i class="w-4 h-4" data-lucide="arrow-right"></i>
<a {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
{{ .Name.New }}
</a>
···
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 rounded" }}
<div id="right-side-items" class="p-2 flex items-center">
-
<a title="top of file" href="#file-{{ .Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-up-to-line"></i></a>
{{ if gt $idx 0 }}
{{ $prev := index $diff (sub $idx 1) }}
-
<a title="previous file" href="#file-{{ $prev.Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-up"></i></a>
{{ end }}
{{ if lt $idx $last }}
{{ $next := index $diff (add $idx 1) }}
-
<a title="next file" href="#file-{{ $next.Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-down"></i></a>
{{ end }}
</div>
···
<a {{if $parent}}href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}"{{end}}>
{{ .Name.Old }}
</a>
+
{{ i "arrow-right" "w-4 h-4" }}
<a {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
{{ .Name.New }}
</a>
···
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 rounded" }}
<div id="right-side-items" class="p-2 flex items-center">
+
<a title="top of file" href="#file-{{ .Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-up-to-line" "w-4 h-4" }}</a>
{{ if gt $idx 0 }}
{{ $prev := index $diff (sub $idx 1) }}
+
<a title="previous file" href="#file-{{ $prev.Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-up" "w-4 h-4" }}</a>
{{ end }}
{{ if lt $idx $last }}
{{ $next := index $diff (add $idx 1) }}
+
<a title="next file" href="#file-{{ $next.Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-down" "w-4 h-4" }}</a>
{{ end }}
</div>
+6 -6
appview/pages/templates/fragments/editRepoDescription.html
···
{{ define "fragments/editRepoDescription" }}
-
<form hx-put="/{{ .RepoInfo.FullName }}/description" hx-target="this" hx-swap="outerHTML">
-
<input type="text" name="description" value="{{ .RepoInfo.Description }}">
-
<button type="submit" class="bg-green-100 text-green-700 rounded p-1 mr-1 hover:bg-green-200 font-mono uppercase text-sm">
-
save
</button>
-
<button type="button" class="bg-red-100 text-red-700 rounded p-1 hover:bg-red-200 font-mono uppercase text-sm" hx-get="/{{ .RepoInfo.FullName }}/description" >
-
cancel
</button>
</form>
{{ end }}
···
{{ define "fragments/editRepoDescription" }}
+
<form hx-put="/{{ .RepoInfo.FullName }}/description" hx-target="this" hx-swap="outerHTML" class="flex flex-wrap gap-2">
+
<input type="text" class="p-1" name="description" value="{{ .RepoInfo.Description }}">
+
<button type="submit" class="btn p-2 flex items-center gap-2 no-underline text-sm">
+
save {{ i "check" "w-3 h-3" }}
</button>
+
<button type="button" class="btn p-2 flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description" >
+
cancel {{ i "x" "w-3 h-3" }}
</button>
</form>
{{ end }}
+3 -2
appview/pages/templates/fragments/repoDescription.html
···
{{ define "fragments/repoDescription" }}
-
<span id="repo-description" hx-target="this" hx-swap="outerHTML">
{{ if .RepoInfo.Description }}
{{ .RepoInfo.Description }}
{{ else }}
···
{{ end }}
{{ if .RepoInfo.Roles.IsOwner }}
-
<button class="bg-gray-200 uppercase rounded p-1 ml-1 hover:bg-gray-400 font-mono text-sm" hx-get="/{{ .RepoInfo.FullName }}/description/edit">
edit
</button>
{{ end }}
</span>
···
{{ define "fragments/repoDescription" }}
+
<span id="repo-description" class="flex flex-wrap items-center gap-2" hx-target="this" hx-swap="outerHTML">
{{ if .RepoInfo.Description }}
{{ .RepoInfo.Description }}
{{ else }}
···
{{ end }}
{{ if .RepoInfo.Roles.IsOwner }}
+
<button class="btn p-2 flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description/edit">
edit
+
{{ i "pencil" "w-3 h-3" }}
</button>
{{ end }}
</span>
+2 -7
appview/pages/templates/fragments/star.html
···
>
<div class="flex gap-2 items-center">
{{ if .IsStarred }}
-
<span class="w-3 h-3 fill-current" data-lucide="star"></span>
{{ else }}
-
<span class="w-3 h-3" data-lucide="star"></span>
{{ end }}
<span>
{{ .Stats.StarCount }}
</span>
</div>
</button>
-
<script>
-
document.body.addEventListener('htmx:afterRequest', function (evt) {
-
lucide.createIcons();
-
});
-
</script>
{{ end }}
···
>
<div class="flex gap-2 items-center">
{{ if .IsStarred }}
+
{{ i "star" "w-3 h-3 fill-current" }}
{{ else }}
+
{{ i "star" "w-3 h-3" }}
{{ end }}
<span>
{{ .Stats.StarCount }}
</span>
</div>
</button>
{{ end }}
-4
appview/pages/templates/layouts/base.html
···
{{ template "layouts/footer" . }}
{{ end }}
</footer>
-
<script src="/static/lucide.min.js"></script>
-
<script>
-
lucide.createIcons();
-
</script>
</div>
</body>
</html>
···
{{ template "layouts/footer" . }}
{{ end }}
</footer>
</div>
</body>
</html>
+1 -1
appview/pages/templates/layouts/topbar.html
···
<div id="right-items" class="flex gap-2">
{{ with .LoggedInUser }}
<a href="/repo/new" hx-boost="true">
-
<i class="w-6 h-6" data-lucide="plus"></i>
</a>
{{ block "dropDown" . }} {{ end }}
{{ else }}
···
<div id="right-items" class="flex gap-2">
{{ with .LoggedInUser }}
<a href="/repo/new" hx-boost="true">
+
{{ i "plus" "w-6 h-6" }}
</a>
{{ block "dropDown" . }} {{ end }}
{{ else }}
+1 -1
appview/pages/templates/repo/commit.html
···
<p class="flex items-center text-sm text-gray-500">
<a href="/{{ $repo }}/commit/{{ $commit.This }}" class="no-underline hover:underline text-gray-500">{{ slice $commit.This 0 8 }}</a>
{{ if $commit.Parent }}
-
<i class="w-3 h-3 mx-1" data-lucide="arrow-left"></i>
<a href="/{{ $repo }}/commit/{{ $commit.Parent }}" class="no-underline hover:underline text-gray-500">{{ slice $commit.Parent 0 8 }}</a>
{{ end }}
</p>
···
<p class="flex items-center text-sm text-gray-500">
<a href="/{{ $repo }}/commit/{{ $commit.This }}" class="no-underline hover:underline text-gray-500">{{ slice $commit.This 0 8 }}</a>
{{ if $commit.Parent }}
+
{{ i "arrow-left" "w-3 h-3 mx-1" }}
<a href="/{{ $repo }}/commit/{{ $commit.Parent }}" class="no-underline hover:underline text-gray-500">{{ slice $commit.Parent 0 8 }}</a>
{{ end }}
</p>
+6 -16
appview/pages/templates/repo/index.html
···
href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}"
class="ml-2 no-underline flex items-center gap-2 text-sm uppercase font-bold"
>
-
<i class="w-4 h-4" data-lucide="logs"></i>
{{ .TotalCommits }}
{{ if eq .TotalCommits 1 }}commit{{ else }}commits{{ end }}
</a>
···
class="{{ $linkstyle }}"
>
<div class="flex items-center gap-2">
-
<i
-
class="w-3 h-3 fill-current"
-
data-lucide="folder"
-
></i
-
>{{ .Name }}
</div>
</a>
···
class="{{ $linkstyle }}"
>
<div class="flex items-center gap-2">
-
<i
-
class="w-3 h-3"
-
data-lucide="file"
-
></i
-
>{{ .Name }}
</div>
</a>
···
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded"
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')"
>
-
<i
-
class="w-3 h-3"
-
data-lucide="ellipsis"
-
></i>
</button>
{{ end }}
</div>
···
></div>
{{ end }}
{{ range $tagsForCommit }}
-
<span class="text-xs rounded bg-gray-100 font-mono px-2 mx-1/2 inline-flex items-center">
{{ . }}
</span>
{{ end }}
···
href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}"
class="ml-2 no-underline flex items-center gap-2 text-sm uppercase font-bold"
>
+
{{ i "logs" "w-4 h-4" }}
{{ .TotalCommits }}
{{ if eq .TotalCommits 1 }}commit{{ else }}commits{{ end }}
</a>
···
class="{{ $linkstyle }}"
>
<div class="flex items-center gap-2">
+
{{ i "folder" "w-3 h-3 fill-current" }}
+
{{ .Name }}
</div>
</a>
···
class="{{ $linkstyle }}"
>
<div class="flex items-center gap-2">
+
{{ i "file" "w-3 h-3" }}{{ .Name }}
</div>
</a>
···
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded"
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')"
>
+
{{ i "ellipsis" "w-3 h-3" }}
</button>
{{ end }}
</div>
···
></div>
{{ end }}
{{ range $tagsForCommit }}
+
<span class="text-xs rounded bg-gray-100 text-black font-mono px-2 mx-1/2 inline-flex items-center">
{{ . }}
</span>
{{ end }}
+2 -5
appview/pages/templates/repo/issues/issue.html
···
<div class="inline-flex items-center gap-2">
<div id="state"
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }} text-sm">
-
<i data-lucide="{{ $icon }}" class="w-4 h-4 mr-1.5 text-white" ></i>
<span class="text-white">{{ .State }}</span>
</div>
<span class="text-gray-500 text-sm">
···
class="mt-8"
>
<button type="submit" class="btn hover:bg-{{ $hoverColor }}-300">
-
<i
-
data-lucide="{{ $icon }}"
-
class="w-4 h-4 mr-2 text-{{ $hoverColor }}-400"
-
></i>
<span class="text-black">{{ $action }}</span>
</button>
<div id="issue-action" class="error"></div>
···
<div class="inline-flex items-center gap-2">
<div id="state"
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }} text-sm">
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
<span class="text-white">{{ .State }}</span>
</div>
<span class="text-gray-500 text-sm">
···
class="mt-8"
>
<button type="submit" class="btn hover:bg-{{ $hoverColor }}-300">
+
{{ i $icon "w-4 h-4 mr-2" }}
<span class="text-black">{{ $action }}</span>
</button>
<div id="issue-action" class="error"></div>
+2 -2
appview/pages/templates/repo/issues/issues.html
···
<a
href="/{{ .RepoInfo.FullName }}/issues/new"
class="btn text-sm flex items-center gap-2 no-underline hover:no-underline">
-
<i data-lucide="plus" class="w-5 h-5"></i>
<span>new issue</span>
</a>
</div>
···
{{ end }}
<span class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
-
<i data-lucide="{{ $icon }}" class="w-3 h-3 mr-1.5 text-white"></i>
<span class="text-white">{{ $state }}</span>
</span>
···
<a
href="/{{ .RepoInfo.FullName }}/issues/new"
class="btn text-sm flex items-center gap-2 no-underline hover:no-underline">
+
{{ i "plus" "w-4 h-4" }}
<span>new issue</span>
</a>
</div>
···
{{ end }}
<span class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
+
{{ i $icon "w-3 h-3 mr-1.5 text-white" }}
<span class="text-white">{{ $state }}</span>
</span>
+3 -6
appview/pages/templates/repo/log.html
···
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded"
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')"
>
-
<i
-
class="w-3 h-3"
-
data-lucide="ellipsis"
-
></i>
</button>
{{ end }}
</div>
···
hx-boost="true"
onclick="window.location.href = window.location.pathname + '?page={{ sub .Page 1 }}'"
>
-
<i data-lucide="chevron-left" class="w-4 h-4"></i>
previous
</a>
{{ else }}
···
onclick="window.location.href = window.location.pathname + '?page={{ add .Page 1 }}'"
>
next
-
<i data-lucide="chevron-right" class="w-4 h-4"></i>
</a>
{{ end }}
</div>
···
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded"
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')"
>
+
{{ i "ellipsis" "w-3 h-3" }}
</button>
{{ end }}
</div>
···
hx-boost="true"
onclick="window.location.href = window.location.pathname + '?page={{ sub .Page 1 }}'"
>
+
{{ i "chevron-left" "w-4 h-4" }}
previous
</a>
{{ else }}
···
onclick="window.location.href = window.location.pathname + '?page={{ add .Page 1 }}'"
>
next
+
{{ i "chevron-right" "w-4 h-4" }}
</a>
{{ end }}
</div>
+2 -5
appview/pages/templates/repo/pulls/patch.html
···
<header class="pb-2">
<div class="flex gap-3 items-center mb-3">
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/" class="flex items-center gap-2 font-medium">
-
<i data-lucide="arrow-left" class="w-5 h-5"></i>
back
</a>
<span class="select-none before:content-['\00B7']"></span>
···
id="state"
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
>
-
<i
-
data-lucide="{{ $icon }}"
-
class="w-4 h-4 mr-1.5 text-white"
-
></i>
<span class="text-white">{{ .Pull.State.String }}</span>
</div>
<span class="text-gray-500 text-sm">
···
<header class="pb-2">
<div class="flex gap-3 items-center mb-3">
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/" class="flex items-center gap-2 font-medium">
+
{{ i "arrow-left" "w-5 h-5" }}
back
</a>
<span class="select-none before:content-['\00B7']"></span>
···
id="state"
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
>
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
<span class="text-white">{{ .Pull.State.String }}</span>
</div>
<span class="text-gray-500 text-sm">
+24 -20
appview/pages/templates/repo/pulls/pull.html
···
id="state"
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
>
-
<i
-
data-lucide="{{ $icon }}"
-
class="w-4 h-4 mr-1.5 text-white"
-
></i>
<span class="text-white">{{ .Pull.State.String }}</span>
</div>
<span class="text-gray-500 text-sm">
···
<div class="bg-purple-50 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex items-center gap-2 text-purple-500">
-
<i data-lucide="git-merge" class="w-4 h-4"></i>
<span class="font-medium">pull request successfully merged</span
>
</div>
···
<div class="bg-red-50 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex items-center gap-2 text-red-500">
-
<i data-lucide="alert-triangle" class="w-4 h-4"></i>
<span class="font-medium">merge conflicts detected</span>
<ul class="text-sm space-y-1">
{{ range .MergeCheck.Conflicts }}
{{ if .Filename }}
<li class="flex items-center">
-
<i
-
data-lucide="file-warning"
-
class="w-3 h-3 mr-1.5 text-red-500"
-
></i>
<span class="font-mono">{{ slice .Filename 0 (sub (len .Filename) 2) }}</span>
</li>
{{ end }}
···
<div class="bg-green-50 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex items-center gap-2 text-green-500">
-
<i data-lucide="check-circle" class="w-4 h-4"></i>
<span class="font-medium">no conflicts, ready to merge</span>
</div>
</div>
···
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex flex-wrap gap-2">
<button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline">
-
<i data-lucide="message-square-plus" class="w-4 h-4"></i>
<span>comment</span>
</button>
{{ if and $isPushAllowed $isOpen }}
···
{{ if $isConflicted }}
{{ $disabled = "disabled" }}
{{ end }}
-
<button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline" {{ $disabled }}>
-
<i data-lucide="git-merge" class="w-4 h-4"></i>
<span>merge</span>
</button>
{{ end }}
{{ if and $isPullAuthor $isOpen }}
<button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline">
-
<i data-lucide="rotate-ccw" class="w-4 h-4"></i>
<span>resubmit</span>
</button>
{{ end }}
{{ if and $isPullAuthor $isPushAllowed $isOpen }}
-
<button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline">
-
<i data-lucide="ban" class="w-4 h-4"></i>
<span>close</span>
</button>
{{ end }}
{{ if and $isPullAuthor $isPushAllowed $isClosed }}
-
<button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline">
-
<i data-lucide="circle-dot" class="w-4 h-4"></i>
<span>reopen</span>
</button>
{{ end }}
···
class="rounded relative bg-purple-50 border border-purple-200 p-4">
<div class="flex items-center gap-2 text-purple-500">
-
<i data-lucide="git-merge" class="w-4 h-4"></i>
<span class="font-medium"
>pull request successfully merged</span
>
···
id="state"
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
>
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
<span class="text-white">{{ .Pull.State.String }}</span>
</div>
<span class="text-gray-500 text-sm">
···
<div class="bg-purple-50 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex items-center gap-2 text-purple-500">
+
{{ i "git-merge" "w-4 h-4" }}
<span class="font-medium">pull request successfully merged</span
>
</div>
···
<div class="bg-red-50 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex items-center gap-2 text-red-500">
+
{{ i "triangle-alert" "w-4 h-4" }}
<span class="font-medium">merge conflicts detected</span>
<ul class="text-sm space-y-1">
{{ range .MergeCheck.Conflicts }}
{{ if .Filename }}
<li class="flex items-center">
+
{{ i "file-warning" "w-3 h-3 mr-1.5 text-red-500" }}
<span class="font-mono">{{ slice .Filename 0 (sub (len .Filename) 2) }}</span>
</li>
{{ end }}
···
<div class="bg-green-50 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex items-center gap-2 text-green-500">
+
{{ i "circle-check-big" "w-4 h-4" }}
<span class="font-medium">no conflicts, ready to merge</span>
</div>
</div>
···
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300"></div>
<div class="flex flex-wrap gap-2">
<button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline">
+
{{ i "message-square-plus" "w-4 h-4" }}
<span>comment</span>
</button>
{{ if and $isPushAllowed $isOpen }}
···
{{ if $isConflicted }}
{{ $disabled = "disabled" }}
{{ end }}
+
<button
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge"
+
hx-swap="none"
+
hx-confirm="Are you sure you want to merge this pull request?"
+
class="btn p-2 flex items-center gap-2" {{ $disabled }}>
+
{{ i "git-merge" "w-4 h-4" }}
<span>merge</span>
</button>
{{ end }}
{{ if and $isPullAuthor $isOpen }}
<button href="#" class="btn p-2 flex items-center gap-2 no-underline hover:no-underline">
+
{{ i "rotate-ccw" "w-4 h-4" }}
<span>resubmit</span>
</button>
{{ end }}
{{ if and $isPullAuthor $isPushAllowed $isOpen }}
+
<button
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/close"
+
hx-swap="none"
+
class="btn p-2 flex items-center gap-2">
+
{{ i "ban" "w-4 h-4" }}
<span>close</span>
</button>
{{ end }}
{{ if and $isPullAuthor $isPushAllowed $isClosed }}
+
<button
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/reopen"
+
hx-swap="none"
+
class="btn p-2 flex items-center gap-2">
+
{{ i "circle-dot" "w-4 h-4" }}
<span>reopen</span>
</button>
{{ end }}
···
class="rounded relative bg-purple-50 border border-purple-200 p-4">
<div class="flex items-center gap-2 text-purple-500">
+
{{ i "git-merge" "w-4 h-4" }}
<span class="font-medium"
>pull request successfully merged</span
>
+2 -5
appview/pages/templates/repo/pulls/pulls.html
···
href="/{{ .RepoInfo.FullName }}/pulls/new"
class="btn text-sm flex items-center gap-2 no-underline hover:no-underline"
>
-
<i data-lucide="git-pull-request" class="w-5 h-5"></i>
<span>new pull request</span>
</a>
</div>
···
<span
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm"
>
-
<i
-
data-lucide="{{ $icon }}"
-
class="w-3 h-3 mr-1.5 text-white"
-
></i>
<span class="text-white">{{ .State.String }}</span>
</span>
···
href="/{{ .RepoInfo.FullName }}/pulls/new"
class="btn text-sm flex items-center gap-2 no-underline hover:no-underline"
>
+
{{ i "git-pull-request" "w-4 h-4" }}
<span>new pull request</span>
</a>
</div>
···
<span
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm"
>
+
{{ i $icon "w-3 h-3 mr-1.5 text-white" }}
<span class="text-white">{{ .State.String }}</span>
</span>
+2 -2
appview/pages/templates/repo/tree.html
···
<div class="flex justify-between items-center">
<a href="/{{ $.BaseTreeLink }}/{{ .Name }}" class="{{ $linkstyle }}">
<div class="flex items-center gap-2">
-
<i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }}
</div>
</a>
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time>
···
<div class="flex justify-between items-center">
<a href="/{{ $.BaseBlobLink }}/{{ .Name }}" class="{{ $linkstyle }}">
<div class="flex items-center gap-2">
-
<i class="w-3 h-3" data-lucide="file"></i>{{ .Name }}
</div>
</a>
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time>
···
<div class="flex justify-between items-center">
<a href="/{{ $.BaseTreeLink }}/{{ .Name }}" class="{{ $linkstyle }}">
<div class="flex items-center gap-2">
+
{{ i "folder" "w-3 h-3 fill-current" }}{{ .Name }}
</div>
</a>
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time>
···
<div class="flex justify-between items-center">
<a href="/{{ $.BaseBlobLink }}/{{ .Name }}" class="{{ $linkstyle }}">
<div class="flex items-center gap-2">
+
{{ i "file" "w-3 h-3" }}{{ .Name }}
</div>
</a>
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time>
+6 -6
appview/pages/templates/settings.html
···
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
<div class="flex flex-col gap-1">
<div class="inline-flex items-center gap-4">
-
<i class="w-3 h-3" data-lucide="key"></i>
<p class="font-bold">{{ .Name }}</p>
</div>
<p class="text-sm text-gray-500">added {{ .Created | timeFmt }}</p>
···
class="btn text-red-500 hover:text-red-700"
title="Delete key"
hx-delete="/settings/keys?name={{urlquery .Name}}&rkey={{urlquery .Rkey}}&key={{urlquery .Key}}"
-
hx-confirm="Are you sure you wish to delete the key '{{ .Name }}'?">
-
<i class="w-5 h-5" data-lucide="trash-2"></i>
<span class="hidden md:inline">delete</span>
</button>
</div>
···
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
<div class="flex flex-col gap-2">
<div class="inline-flex items-center gap-4">
-
<i class="w-3 h-3" data-lucide="mail"></i>
<p class="font-bold">{{ .Address }}</p>
<div class="inline-flex items-center gap-1">
{{ if .Verified }}
···
hx-swap="none"
href="#"
hx-vals='{"email": "{{ .Address }}"}'>
-
<i class="w-5 h-5" data-lucide="rotate-cw"></i>
<span class="hidden md:inline">resend</span>
</button>
{{ end }}
···
class="btn text-red-500 hover:text-red-700"
title="Delete email"
type="submit">
-
<i class="w-5 h-5" data-lucide="trash-2"></i>
<span class="hidden md:inline">delete</span>
</button>
</form>
···
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
<div class="flex flex-col gap-1">
<div class="inline-flex items-center gap-4">
+
{{ i "key" "w-3 h-3" }}
<p class="font-bold">{{ .Name }}</p>
</div>
<p class="text-sm text-gray-500">added {{ .Created | timeFmt }}</p>
···
class="btn text-red-500 hover:text-red-700"
title="Delete key"
hx-delete="/settings/keys?name={{urlquery .Name}}&rkey={{urlquery .Rkey}}&key={{urlquery .Key}}"
+
hx-confirm="Are you sure you want to delete the key '{{ .Name }}'?">
+
{{ i "trash-2" "w-5 h-5" }}
<span class="hidden md:inline">delete</span>
</button>
</div>
···
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
<div class="flex flex-col gap-2">
<div class="inline-flex items-center gap-4">
+
{{ i "mail" "w-3 h-3" }}
<p class="font-bold">{{ .Address }}</p>
<div class="inline-flex items-center gap-1">
{{ if .Verified }}
···
hx-swap="none"
href="#"
hx-vals='{"email": "{{ .Address }}"}'>
+
{{ i "rotate-cw" "w-5 h-5" }}
<span class="hidden md:inline">resend</span>
</button>
{{ end }}
···
class="btn text-red-500 hover:text-red-700"
title="Delete email"
type="submit">
+
{{ i "trash-2" "w-5 h-5" }}
<span class="hidden md:inline">delete</span>
</button>
</form>
+1 -1
appview/pages/templates/timeline.html
···
tangled
</div>
<div class="italic text-lg">
-
tightly-knit social coding, <a href="/login" class="underline inline-flex gap-1 items-center">join now <i data-lucide="arrow-right" class="w-4 h-4"></i></a>
<p class="pt-5 px-10 text-sm text-gray-500">Join our IRC channel: <a href="https://web.libera.chat/#tangled"><code>#tangled</code> on Libera Chat</a>.
Read an introduction to Tangled <a href="https://blog.tangled.sh/intro">here</a>.</p>
</div>
···
tangled
</div>
<div class="italic text-lg">
+
tightly-knit social coding, <a href="/login" class="underline inline-flex gap-1 items-center">join now {{ i "arrow-right" "w-4 h-4" }}</a>
<p class="pt-5 px-10 text-sm text-gray-500">Join our IRC channel: <a href="https://web.libera.chat/#tangled"><code>#tangled</code> on Libera Chat</a>.
Read an introduction to Tangled <a href="https://blog.tangled.sh/intro">here</a>.</p>
</div>
+2 -8
appview/pages/templates/user/profile.html
···
{{ if .RepoStats.StarCount }}
<div class="flex gap-1 items-center text-sm">
-
<span
-
class="w-3 h-3 fill-current"
-
data-lucide="star"
-
></span>
<span>{{ .RepoStats.StarCount }}</span>
</div>
{{ end }}
···
{{ if .RepoStats.StarCount }}
<div class="flex gap-1 items-center text-sm">
-
<span
-
class="w-3 h-3 fill-current"
-
data-lucide="star"
-
></span>
<span>{{ .RepoStats.StarCount }}</span>
</div>
{{ end }}
···
{{ if .RepoStats.StarCount }}
<div class="flex gap-1 items-center text-sm">
+
{{ i "star" "w-3 h-3 fill-current" }}
<span>{{ .RepoStats.StarCount }}</span>
</div>
{{ end }}
···
{{ if .RepoStats.StarCount }}
<div class="flex gap-1 items-center text-sm">
+
{{ i "star" "w-3 h-3 fill-current" }}
<span>{{ .RepoStats.StarCount }}</span>
</div>
{{ end }}
-2
appview/state/pull.go
···
}
}
-
log.Println(mergeCheckResponse)
-
s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(s, user),
···
}
}
s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(s, user),
+6 -5
flake.lock
···
"lucide-src": {
"flake": false,
"locked": {
-
"narHash": "sha256-5ipNSxTlQ7627lGgsyZxk7vS1sr9RkrlR8/QMj2Zg6s=",
-
"type": "file",
-
"url": "https://unpkg.com/lucide@0.482.0"
},
"original": {
-
"type": "file",
-
"url": "https://unpkg.com/lucide@0.482.0"
}
},
"nixpkgs": {
···
"lucide-src": {
"flake": false,
"locked": {
+
"lastModified": 1742302029,
+
"narHash": "sha256-OyPVtpnC4/AAmPq84Wt1r1Gcs48d9KG+UBCtZK87e9k=",
+
"type": "tarball",
+
"url": "https://github.com/lucide-icons/lucide/releases/download/0.483.0/lucide-icons-0.483.0.zip"
},
"original": {
+
"type": "tarball",
+
"url": "https://github.com/lucide-icons/lucide/releases/download/0.483.0/lucide-icons-0.483.0.zip"
}
},
"nixpkgs": {
+5 -5
flake.nix
···
flake = false;
};
lucide-src = {
-
url = "https://unpkg.com/lucide@0.482.0";
flake = false;
};
ia-fonts-src = {
···
src = gitignoreSource ./.;
postUnpack = ''
pushd source
cp -f ${htmx-src} appview/pages/static/htmx.min.js
-
cp -f ${lucide-src} appview/pages/static/lucide.min.js
-
mkdir -p appview/pages/static/fonts
cp -f ${ia-fonts-src}/"iA Writer Quattro"/Static/*.ttf appview/pages/static/fonts/
cp -f ${ia-fonts-src}/"iA Writer Mono"/Static/*.ttf appview/pages/static/fonts/
${pkgs.tailwindcss}/bin/tailwindcss -i input.css -o appview/pages/static/tw.css
···
pkgs.nixos-shell
];
shellHook = ''
cp -f ${htmx-src} appview/pages/static/htmx.min.js
-
cp -f ${lucide-src} appview/pages/static/lucide.min.js
-
mkdir -p appview/pages/static/fonts/
cp -f ${ia-fonts-src}/"iA Writer Quattro"/Static/*.ttf appview/pages/static/fonts/
cp -f ${ia-fonts-src}/"iA Writer Mono"/Static/*.ttf appview/pages/static/fonts/
'';
···
flake = false;
};
lucide-src = {
+
url = "https://github.com/lucide-icons/lucide/releases/download/0.483.0/lucide-icons-0.483.0.zip";
flake = false;
};
ia-fonts-src = {
···
src = gitignoreSource ./.;
postUnpack = ''
pushd source
+
mkdir -p appview/pages/static/{fonts,icons}
cp -f ${htmx-src} appview/pages/static/htmx.min.js
+
cp -rf ${lucide-src}/*.svg appview/pages/static/icons/
cp -f ${ia-fonts-src}/"iA Writer Quattro"/Static/*.ttf appview/pages/static/fonts/
cp -f ${ia-fonts-src}/"iA Writer Mono"/Static/*.ttf appview/pages/static/fonts/
${pkgs.tailwindcss}/bin/tailwindcss -i input.css -o appview/pages/static/tw.css
···
pkgs.nixos-shell
];
shellHook = ''
+
mkdir -p appview/pages/static/{fonts,icons}
cp -f ${htmx-src} appview/pages/static/htmx.min.js
+
cp -rf ${lucide-src}/*.svg appview/pages/static/icons/
cp -f ${ia-fonts-src}/"iA Writer Quattro"/Static/*.ttf appview/pages/static/fonts/
cp -f ${ia-fonts-src}/"iA Writer Mono"/Static/*.ttf appview/pages/static/fonts/
'';