+4
-2
appview/pages/templates/errors/404.html
+4
-2
appview/pages/templates/errors/404.html
···
1
1
{{ define "title" }}404 · tangled{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<h1>404 — nothing like that here!</h1>
5
-
<p>It seems we couldn't find what you were looking for. Sorry about that!</p>
4
+
<h1>404 — nothing like that here!</h1>
5
+
<p>
6
+
It seems we couldn't find what you were looking for. Sorry about that!
7
+
</p>
6
8
{{ end }}
+2
-2
appview/pages/templates/errors/500.html
+2
-2
appview/pages/templates/errors/500.html
···
1
1
{{ define "title" }}500 · tangled{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<h1>500 — something broke!</h1>
5
-
<p>We're working on getting service back up. Hang tight!</p>
4
+
<h1>500 — something broke!</h1>
5
+
<p>We're working on getting service back up. Hang tight!</p>
6
6
{{ end }}
+5
-4
appview/pages/templates/errors/503.html
+5
-4
appview/pages/templates/errors/503.html
···
1
1
{{ define "title" }}503 · tangled{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<h1>503 — unable to reach knot</h1>
5
-
<p>
6
-
We were unable to reach the knot hosting this repository. Try again later.
7
-
</p>
4
+
<h1>503 — unable to reach knot</h1>
5
+
<p>
6
+
We were unable to reach the knot hosting this repository. Try again
7
+
later.
8
+
</p>
8
9
{{ end }}
+20
-24
appview/pages/templates/favicon.html
+20
-24
appview/pages/templates/favicon.html
···
1
1
{{ define "favicon" }}
2
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
3
-
<style>
2
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
3
+
<style>
4
+
.favicon-text {
5
+
fill: #000000;
6
+
stroke: none;
7
+
}
8
+
9
+
@media (prefers-color-scheme: dark) {
4
10
.favicon-text {
5
-
fill: #000000;
11
+
fill: #ffffff;
6
12
stroke: none;
7
13
}
8
-
9
-
@media (prefers-color-scheme: dark) {
10
-
.favicon-text {
11
-
fill: #ffffff;
12
-
stroke: none;
13
-
}
14
-
}
15
-
</style>
14
+
}
15
+
</style>
16
16
17
-
<g style="display:inline">
18
-
<path
19
-
d="M0-2.117h62.177v25.135H0z"
20
-
style="display:inline;fill:none;fill-opacity:1;stroke-width:.396875"
21
-
transform="translate(11.01 6.9)" />
22
-
<path
23
-
d="M3.64 22.787c-1.697 0-2.943-.45-3.74-1.35-.77-.9-1.156-2.094-1.156-3.585 0-.36.013-.72.038-1.08.052-.385.129-.873.232-1.464L.44 6.826h-5.089l.733-4.394h3.2c.822 0 1.439-.168 1.85-.502.437-.334.72-.938.848-1.812l.771-4.703h5.243L6.84 2.432h7.787l-.733 4.394H6.107L4.257 17.93l.77.27 6.015-4.742 2.775 3.161-2.313 2.005c-.822.694-1.568 1.31-2.236 1.85-.668.515-1.31.952-1.927 1.311a7.406 7.406 0 0 1-1.774.733c-.59.18-1.233.27-1.927.27z"
24
-
aria-label="tangled.sh"
25
-
class="favicon-text"
26
-
style="font-size:16.2278px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono, Normal';display:inline;fill-opacity:1"
27
-
transform="translate(11.01 6.9)" />
28
-
</g>
29
-
</svg>
17
+
<g style="display:inline">
18
+
<path d="M0-2.117h62.177v25.135H0z" style="display:inline;fill:none;fill-opacity:1;stroke-width:.396875" transform="translate(11.01 6.9)"/>
19
+
<path d="M3.64 22.787c-1.697 0-2.943-.45-3.74-1.35-.77-.9-1.156-2.094-1.156-3.585 0-.36.013-.72.038-1.08.052-.385.129-.873.232-1.464L.44 6.826h-5.089l.733-4.394h3.2c.822 0 1.439-.168 1.85-.502.437-.334.72-.938.848-1.812l.771-4.703h5.243L6.84 2.432h7.787l-.733 4.394H6.107L4.257 17.93l.77.27 6.015-4.742 2.775 3.161-2.313 2.005c-.822.694-1.568 1.31-2.236 1.85-.668.515-1.31.952-1.927 1.311a7.406 7.406 0 0 1-1.774.733c-.59.18-1.233.27-1.927.27z"
20
+
aria-label="tangled.sh"
21
+
class="favicon-text"
22
+
style="font-size:16.2278px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono, Normal';display:inline;fill-opacity:1"
23
+
transform="translate(11.01 6.9)"/>
24
+
</g>
25
+
</svg>
30
26
{{ end }}
+5
-12
appview/pages/templates/knots/dashboard.html
+5
-12
appview/pages/templates/knots/dashboard.html
···
14
14
<div id="right-side" class="flex gap-2">
15
15
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }}
16
16
{{ if .Registration.Registered }}
17
-
<span
18
-
class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{ $style }}">
19
-
{{ i "shield-check" "w-4 h-4" }} verified
20
-
</span>
17
+
<span class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{$style}}">{{ i "shield-check" "w-4 h-4" }} verified</span>
21
18
{{ template "knots/fragments/addMemberModal" .Registration }}
22
19
{{ else }}
23
-
<span
24
-
class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{ $style }}">
25
-
{{ i "shield-off" "w-4 h-4" }} pending
26
-
</span>
20
+
<span class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{$style}}">{{ i "shield-off" "w-4 h-4" }} pending</span>
27
21
{{ end }}
28
22
</div>
29
23
</div>
···
31
25
</div>
32
26
33
27
{{ if .Members }}
34
-
<section
35
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
28
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
36
29
<div class="flex flex-col gap-2">
37
-
{{ block "knotMember" . }}{{ end }}
30
+
{{ block "knotMember" . }} {{ end }}
38
31
</div>
39
32
</section>
40
33
{{ end }}
···
46
39
<div class="flex justify-between items-center">
47
40
<div class="flex items-center gap-2">
48
41
{{ template "user/fragments/picHandleLink" . }}
49
-
<span class="ml-2 font-mono text-gray-500">{{ . }}</span>
42
+
<span class="ml-2 font-mono text-gray-500">{{.}}</span>
50
43
</div>
51
44
</div>
52
45
<div class="ml-2 pl-2 pt-2 border-l border-gray-200 dark:border-gray-700">
+40
-39
appview/pages/templates/knots/fragments/addMemberModal.html
+40
-39
appview/pages/templates/knots/fragments/addMemberModal.html
···
3
3
class="btn gap-2 group"
4
4
title="Add member to this spindle"
5
5
popovertarget="add-member-{{ .Id }}"
6
-
popovertargetaction="toggle">
6
+
popovertargetaction="toggle"
7
+
>
7
8
{{ i "user-plus" "w-5 h-5" }}
8
-
<span class="hidden md:inline">add member</span>
9
+
<span class="hidden md:inline">add member</span>
9
10
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
10
11
</button>
11
12
···
13
14
id="add-member-{{ .Id }}"
14
15
popover
15
16
class="bg-white w-full md:w-96 dark:bg-gray-800 p-4 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50">
16
-
{{ block "addKnotMemberPopover" . }}{{ end }}
17
+
{{ block "addKnotMemberPopover" . }} {{ end }}
17
18
</div>
18
19
{{ end }}
19
20
20
21
{{ define "addKnotMemberPopover" }}
21
-
<form
22
-
hx-put="/knots/{{ .Domain }}/member"
23
-
hx-indicator="#spinner"
24
-
hx-swap="none"
25
-
class="flex flex-col gap-2">
26
-
<label for="member-did-{{ .Id }}" class="uppercase p-0">ADD MEMBER</label>
27
-
<p class="text-sm text-gray-500 dark:text-gray-400">
28
-
Members can create repositories on this knot.
29
-
</p>
30
-
<input
31
-
type="text"
32
-
id="member-did-{{ .Id }}"
33
-
name="subject"
34
-
required
35
-
placeholder="@foo.bsky.social" />
36
-
<div class="flex gap-2 pt-2">
37
-
<button
38
-
type="button"
39
-
popovertarget="add-member-{{ .Id }}"
40
-
popovertargetaction="hide"
41
-
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
42
-
{{ i "x" "size-4" }} cancel
43
-
</button>
44
-
<button type="submit" class="btn w-1/2 flex items-center">
45
-
<span class="inline-flex gap-2 items-center">
46
-
{{ i "user-plus" "size-4" }} add
47
-
</span>
48
-
<span id="spinner" class="group">
49
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
50
-
</span>
51
-
</button>
52
-
</div>
53
-
<div
54
-
id="add-member-error-{{ .Id }}"
55
-
class="text-red-500 dark:text-red-400"></div>
56
-
</form>
22
+
<form
23
+
hx-put="/knots/{{ .Domain }}/member"
24
+
hx-indicator="#spinner"
25
+
hx-swap="none"
26
+
class="flex flex-col gap-2"
27
+
>
28
+
<label for="member-did-{{ .Id }}" class="uppercase p-0">
29
+
ADD MEMBER
30
+
</label>
31
+
<p class="text-sm text-gray-500 dark:text-gray-400">Members can create repositories on this knot.</p>
32
+
<input
33
+
type="text"
34
+
id="member-did-{{ .Id }}"
35
+
name="subject"
36
+
required
37
+
placeholder="@foo.bsky.social"
38
+
/>
39
+
<div class="flex gap-2 pt-2">
40
+
<button
41
+
type="button"
42
+
popovertarget="add-member-{{ .Id }}"
43
+
popovertargetaction="hide"
44
+
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
45
+
>
46
+
{{ i "x" "size-4" }} cancel
47
+
</button>
48
+
<button type="submit" class="btn w-1/2 flex items-center">
49
+
<span class="inline-flex gap-2 items-center">{{ i "user-plus" "size-4" }} add</span>
50
+
<span id="spinner" class="group">
51
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
52
+
</span>
53
+
</button>
54
+
</div>
55
+
<div id="add-member-error-{{ .Id }}" class="text-red-500 dark:text-red-400"></div>
56
+
</form>
57
57
{{ end }}
58
+
+10
-14
appview/pages/templates/knots/fragments/knotListing.html
+10
-14
appview/pages/templates/knots/fragments/knotListing.html
···
1
1
{{ define "knots/fragments/knotListing" }}
2
-
<div
3
-
id="knot-{{ .Id }}"
2
+
<div
3
+
id="knot-{{.Id}}"
4
4
hx-swap-oob="true"
5
5
class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
6
-
{{ block "listLeftSide" . }}{{ end }}
7
-
{{ block "listRightSide" . }}{{ end }}
6
+
{{ block "listLeftSide" . }} {{ end }}
7
+
{{ block "listRightSide" . }} {{ end }}
8
8
</div>
9
9
{{ end }}
10
10
···
28
28
<div id="right-side" class="flex gap-2">
29
29
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2 text-sm" }}
30
30
{{ if .Registered }}
31
-
<span
32
-
class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{ $style }}">
33
-
{{ i "shield-check" "w-4 h-4" }} verified
34
-
</span>
31
+
<span class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{$style}}">{{ i "shield-check" "w-4 h-4" }} verified</span>
35
32
{{ template "knots/fragments/addMemberModal" . }}
36
33
{{ else }}
37
-
<span
38
-
class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{ $style }}">
39
-
{{ i "shield-off" "w-4 h-4" }} pending
40
-
</span>
41
-
{{ block "initializeButton" . }}{{ end }}
34
+
<span class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{$style}}">{{ i "shield-off" "w-4 h-4" }} pending</span>
35
+
{{ block "initializeButton" . }} {{ end }}
42
36
{{ end }}
43
37
</div>
44
38
{{ end }}
···
47
41
<button
48
42
class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center group"
49
43
hx-post="/knots/{{ .Domain }}/init"
50
-
hx-swap="none">
44
+
hx-swap="none"
45
+
>
51
46
{{ i "square-play" "w-5 h-5" }}
52
47
<span class="hidden md:inline">initialize</span>
53
48
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
54
49
</button>
55
50
{{ end }}
51
+
+16
-20
appview/pages/templates/knots/fragments/knotListingFull.html
+16
-20
appview/pages/templates/knots/fragments/knotListingFull.html
···
1
1
{{ define "knots/fragments/knotListingFull" }}
2
-
<section
3
-
id="knot-listing-full"
4
-
hx-swap-oob="true"
5
-
class="rounded w-full flex flex-col gap-2">
6
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
7
-
your knots
8
-
</h2>
9
-
<div
10
-
class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
11
-
{{ range $knot := .Registrations }}
12
-
{{ template "knots/fragments/knotListing" . }}
13
-
{{ else }}
14
-
<div
15
-
class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
16
-
no knots registered yet
17
-
</div>
18
-
{{ end }}
19
-
</div>
20
-
<div id="operation-error" class="text-red-500 dark:text-red-400"></div>
21
-
</section>
2
+
<section
3
+
id="knot-listing-full"
4
+
hx-swap-oob="true"
5
+
class="rounded w-full flex flex-col gap-2">
6
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">your knots</h2>
7
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
8
+
{{ range $knot := .Registrations }}
9
+
{{ template "knots/fragments/knotListing" . }}
10
+
{{ else }}
11
+
<div class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
12
+
no knots registered yet
13
+
</div>
14
+
{{ end }}
15
+
</div>
16
+
<div id="operation-error" class="text-red-500 dark:text-red-400"></div>
17
+
</section>
22
18
{{ end }}
+2
-6
appview/pages/templates/knots/fragments/secret.html
+2
-6
appview/pages/templates/knots/fragments/secret.html
···
3
3
id="secret"
4
4
hx-swap-oob="true"
5
5
class="bg-gray-50 dark:bg-gray-700 border border-black dark:border-gray-500 rounded px-6 py-2 w-full lg:w-3xl">
6
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
7
-
generated secret
8
-
</h2>
9
-
<p class="pb-2">
10
-
Configure your knot to use this secret, and then hit initialize.
11
-
</p>
6
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">generated secret</h2>
7
+
<p class="pb-2">Configure your knot to use this secret, and then hit initialize.</p>
12
8
<span class="font-mono overflow-x">{{ .Secret }}</span>
13
9
</div>
14
10
{{ end }}
+22
-27
appview/pages/templates/knots/index.html
+22
-27
appview/pages/templates/knots/index.html
···
1
1
{{ define "title" }}knots{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<div class="px-6 py-4">
5
-
<h1 class="text-xl font-bold dark:text-white">Knots</h1>
4
+
<div class="px-6 py-4">
5
+
<h1 class="text-xl font-bold dark:text-white">Knots</h1>
6
+
</div>
7
+
8
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
9
+
<div class="flex flex-col gap-6">
10
+
{{ block "about" . }} {{ end }}
11
+
{{ template "knots/fragments/knotListingFull" . }}
12
+
{{ block "register" . }} {{ end }}
6
13
</div>
7
-
8
-
<section
9
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
10
-
<div class="flex flex-col gap-6">
11
-
{{ block "about" . }}{{ end }}
12
-
{{ template "knots/fragments/knotListingFull" . }}
13
-
{{ block "register" . }}{{ end }}
14
-
</div>
15
-
</section>
14
+
</section>
16
15
{{ end }}
17
16
18
17
{{ define "about" }}
19
18
<section class="rounded flex flex-col gap-2">
20
19
<p class="dark:text-gray-300">
21
-
Knots are lightweight headless servers that enable users to host Git
22
-
repositories with ease. Knots are designed for either single or
23
-
multi-tenant use which is perfect for self-hosting on a Raspberry Pi at
24
-
home, or larger “community” servers. When creating a repository, you can
25
-
choose a knot to store it on.
26
-
<a
27
-
href="https://tangled.sh/@tangled.sh/core/blob/master/docs/knot-hosting.md">
20
+
Knots are lightweight headless servers that enable users to host Git repositories with ease.
21
+
Knots are designed for either single or multi-tenant use which is perfect for self-hosting on a Raspberry Pi at home, or larger “community” servers.
22
+
When creating a repository, you can choose a knot to store it on.
23
+
<a href="https://tangled.sh/@tangled.sh/core/blob/master/docs/knot-hosting.md">
28
24
Checkout the documentation if you're interested in self-hosting.
29
25
</a>
30
26
</p>
···
33
29
34
30
{{ define "register" }}
35
31
<section class="rounded max-w-2xl flex flex-col gap-2">
36
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
37
-
register a knot
38
-
</h2>
39
-
<p class="mb-2 dark:text-gray-300">
40
-
Enter the hostname of your knot to generate a key.
41
-
</p>
32
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a knot</h2>
33
+
<p class="mb-2 dark:text-gray-300">Enter the hostname of your knot to generate a key.</p>
42
34
<form
43
35
hx-post="/knots/key"
44
36
class="space-y-4"
45
37
hx-indicator="#register-button"
46
-
hx-swap="none">
38
+
hx-swap="none"
39
+
>
47
40
<div class="flex gap-2">
48
41
<input
49
42
type="text"
···
51
44
name="domain"
52
45
placeholder="knot.example.com"
53
46
required
54
-
class="flex-1 w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded" />
47
+
class="flex-1 w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded"
48
+
>
55
49
<button
56
50
type="submit"
57
51
id="register-button"
58
-
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group">
52
+
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group"
53
+
>
59
54
<span class="inline-flex items-center gap-2">
60
55
{{ i "plus" "w-4 h-4" }}
61
56
generate
+52
-56
appview/pages/templates/layouts/base.html
+52
-56
appview/pages/templates/layouts/base.html
···
1
1
{{ define "layouts/base" }}
2
-
<!doctype html>
3
-
<html lang="en" class="dark:bg-gray-900">
4
-
<head>
5
-
<meta charset="UTF-8" />
6
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
-
<meta name="htmx-config" content='{"includeIndicatorStyles": false}' />
8
-
<script src="/static/htmx.min.js"></script>
9
-
<script src="/static/htmx-ext-ws.min.js"></script>
10
-
<link
11
-
rel="stylesheet"
12
-
href="/static/tw.css?{{ cssContentHash }}"
13
-
type="text/css" />
14
-
<title>{{ block "title" . }}{{ end }} · tangled</title>
15
-
{{ block "extrameta" . }}{{ end }}
16
-
</head>
17
-
<body
18
-
class="min-h-screen grid grid-cols-1 grid-rows-[min-content_auto_min-content] md:grid-cols-12 gap-4 bg-slate-100 dark:bg-gray-900 dark:text-white transition-colors duration-200">
19
-
{{ block "topbarLayout" . }}
20
-
<header
21
-
class="px-1 col-span-1 md:col-start-3 md:col-span-8"
22
-
style="z-index: 20;">
23
-
{{ template "layouts/topbar" . }}
24
-
</header>
25
-
{{ end }}
26
-
27
-
{{ block "mainLayout" . }}
28
-
<div
29
-
class="px-1 col-span-1 md:col-start-3 md:col-span-8 flex flex-col gap-4">
30
-
{{ block "contentLayout" . }}
31
-
<div class="col-span-1 md:col-span-2">
32
-
{{ block "contentLeft" . }}{{ end }}
33
-
</div>
34
-
<main class="col-span-1 md:col-span-8">
35
-
{{ block "content" . }}{{ end }}
36
-
</main>
37
-
<div class="col-span-1 md:col-span-2">
38
-
{{ block "contentRight" . }}{{ end }}
39
-
</div>
2
+
<!doctype html>
3
+
<html lang="en" class="dark:bg-gray-900">
4
+
<head>
5
+
<meta charset="UTF-8" />
6
+
<meta
7
+
name="viewport"
8
+
content="width=device-width, initial-scale=1.0"
9
+
/>
10
+
<meta name="htmx-config" content='{"includeIndicatorStyles": false}'>
11
+
<script src="/static/htmx.min.js"></script>
12
+
<script src="/static/htmx-ext-ws.min.js"></script>
13
+
<link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" />
14
+
<title>{{ block "title" . }}{{ end }} · tangled</title>
15
+
{{ block "extrameta" . }}{{ end }}
16
+
</head>
17
+
<body class="min-h-screen grid grid-cols-1 grid-rows-[min-content_auto_min-content] md:grid-cols-12 gap-4 bg-slate-100 dark:bg-gray-900 dark:text-white transition-colors duration-200">
18
+
{{ block "topbarLayout" . }}
19
+
<header class="px-1 col-span-1 md:col-start-3 md:col-span-8" style="z-index: 20;">
20
+
{{ template "layouts/topbar" . }}
21
+
</header>
40
22
{{ end }}
41
23
42
-
{{ block "contentAfterLayout" . }}
43
-
<div class="col-span-1 md:col-span-2">
44
-
{{ block "contentAfterLeft" . }}{{ end }}
45
-
</div>
46
-
<main class="col-span-1 md:col-span-8">
47
-
{{ block "contentAfter" . }}{{ end }}
48
-
</main>
49
-
<div class="col-span-1 md:col-span-2">
50
-
{{ block "contentAfterRight" . }}{{ end }}
24
+
{{ block "mainLayout" . }}
25
+
<div class="px-1 col-span-1 md:col-start-3 md:col-span-8 flex flex-col gap-4">
26
+
{{ block "contentLayout" . }}
27
+
<div class="col-span-1 md:col-span-2">
28
+
{{ block "contentLeft" . }} {{ end }}
29
+
</div>
30
+
<main class="col-span-1 md:col-span-8">
31
+
{{ block "content" . }}{{ end }}
32
+
</main>
33
+
<div class="col-span-1 md:col-span-2">
34
+
{{ block "contentRight" . }} {{ end }}
35
+
</div>
36
+
{{ end }}
37
+
38
+
{{ block "contentAfterLayout" . }}
39
+
<div class="col-span-1 md:col-span-2">
40
+
{{ block "contentAfterLeft" . }} {{ end }}
41
+
</div>
42
+
<main class="col-span-1 md:col-span-8">
43
+
{{ block "contentAfter" . }}{{ end }}
44
+
</main>
45
+
<div class="col-span-1 md:col-span-2">
46
+
{{ block "contentAfterRight" . }} {{ end }}
47
+
</div>
48
+
{{ end }}
51
49
</div>
52
50
{{ end }}
53
-
</div>
54
-
{{ end }}
55
51
56
-
{{ block "footerLayout" . }}
57
-
<footer class="px-1 col-span-1 md:col-start-3 md:col-span-8 mt-12">
58
-
{{ template "layouts/footer" . }}
59
-
</footer>
60
-
{{ end }}
61
-
</body>
62
-
</html>
52
+
{{ block "footerLayout" . }}
53
+
<footer class="px-1 col-span-1 md:col-start-3 md:col-span-8 mt-12">
54
+
{{ template "layouts/footer" . }}
55
+
</footer>
56
+
{{ end }}
57
+
</body>
58
+
</html>
63
59
{{ end }}
+61
-66
appview/pages/templates/layouts/topbar.html
+61
-66
appview/pages/templates/layouts/topbar.html
···
1
1
{{ define "layouts/topbar" }}
2
-
<nav
3
-
class="space-x-4 px-6 py-2 rounded bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm">
4
-
<div class="flex justify-between p-0 items-center">
5
-
<div id="left-items">
6
-
<a href="/" hx-boost="true" class="flex gap-2 font-bold italic">
7
-
tangled
8
-
<sub>alpha</sub>
9
-
</a>
10
-
</div>
2
+
<nav class="space-x-4 px-6 py-2 rounded bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm">
3
+
<div class="flex justify-between p-0 items-center">
4
+
<div id="left-items">
5
+
<a href="/" hx-boost="true" class="flex gap-2 font-bold italic">
6
+
tangled<sub>alpha</sub>
7
+
</a>
8
+
</div>
11
9
12
-
<div id="right-items" class="flex items-center gap-2">
13
-
{{ with .LoggedInUser }}
14
-
{{ block "newButton" . }}{{ end }}
15
-
{{ block "dropDown" . }}{{ end }}
16
-
{{ else }}
17
-
<a href="/login">login</a>
18
-
<span class="text-gray-500 dark:text-gray-400">or</span>
19
-
<a
20
-
href="/signup"
21
-
class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
22
-
join now
23
-
{{ i "arrow-right" "size-4" }}
24
-
</a>
25
-
{{ end }}
26
-
</div>
27
-
</div>
28
-
</nav>
10
+
<div id="right-items" class="flex items-center gap-2">
11
+
{{ with .LoggedInUser }}
12
+
{{ block "newButton" . }} {{ end }}
13
+
{{ block "dropDown" . }} {{ end }}
14
+
{{ else }}
15
+
<a href="/login">login</a>
16
+
<span class="text-gray-500 dark:text-gray-400">or</span>
17
+
<a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
18
+
join now {{ i "arrow-right" "size-4" }}
19
+
</a>
20
+
{{ end }}
21
+
</div>
22
+
</div>
23
+
</nav>
29
24
{{ end }}
30
25
31
26
{{ define "newButton" }}
32
-
<details class="relative inline-block text-left nav-dropdown">
33
-
<summary
34
-
class="btn-create py-0 cursor-pointer list-none flex items-center gap-2">
27
+
<details class="relative inline-block text-left nav-dropdown">
28
+
<summary class="btn-create py-0 cursor-pointer list-none flex items-center gap-2">
35
29
{{ i "plus" "w-4 h-4" }} new
36
30
</summary>
37
-
<div
38
-
class="absolute flex flex-col right-0 mt-4 p-4 rounded w-48 bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700">
39
-
<a href="/repo/new" class="flex items-center gap-2">
40
-
{{ i "book-plus" "w-4 h-4" }}
41
-
new repository
42
-
</a>
43
-
<a href="/strings/new" class="flex items-center gap-2">
44
-
{{ i "line-squiggle" "w-4 h-4" }}
45
-
new string
46
-
</a>
31
+
<div class="absolute flex flex-col right-0 mt-4 p-4 rounded w-48 bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700">
32
+
<a href="/repo/new" class="flex items-center gap-2">
33
+
{{ i "book-plus" "w-4 h-4" }}
34
+
new repository
35
+
</a>
36
+
<a href="/strings/new" class="flex items-center gap-2">
37
+
{{ i "line-squiggle" "w-4 h-4" }}
38
+
new string
39
+
</a>
47
40
</div>
48
-
</details>
41
+
</details>
49
42
{{ end }}
50
43
51
44
{{ define "dropDown" }}
52
-
<details class="relative inline-block text-left nav-dropdown">
53
-
<summary class="cursor-pointer list-none flex items-center">
54
-
{{ $user := didOrHandle .Did .Handle }}
55
-
{{ template "user/fragments/picHandle" $user }}
45
+
<details class="relative inline-block text-left nav-dropdown">
46
+
<summary
47
+
class="cursor-pointer list-none flex items-center"
48
+
>
49
+
{{ $user := didOrHandle .Did .Handle }}
50
+
{{ template "user/fragments/picHandle" $user }}
56
51
</summary>
57
52
<div
58
-
class="absolute flex flex-col right-0 mt-4 p-4 rounded w-48 bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700">
59
-
<a href="/{{ $user }}">profile</a>
60
-
<a href="/{{ $user }}?tab=repos">repositories</a>
61
-
<a href="/strings/{{ $user }}">strings</a>
62
-
<a href="/knots">knots</a>
63
-
<a href="/spindles">spindles</a>
64
-
<a href="/settings">settings</a>
65
-
<a
66
-
href="#"
67
-
hx-post="/logout"
68
-
hx-swap="none"
69
-
class="text-red-400 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
70
-
logout
71
-
</a>
53
+
class="absolute flex flex-col right-0 mt-4 p-4 rounded w-48 bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700"
54
+
>
55
+
<a href="/{{ $user }}">profile</a>
56
+
<a href="/{{ $user }}?tab=repos">repositories</a>
57
+
<a href="/strings/{{ $user }}">strings</a>
58
+
<a href="/knots">knots</a>
59
+
<a href="/spindles">spindles</a>
60
+
<a href="/settings">settings</a>
61
+
<a href="#"
62
+
hx-post="/logout"
63
+
hx-swap="none"
64
+
class="text-red-400 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
65
+
logout
66
+
</a>
72
67
</div>
73
-
</details>
68
+
</details>
74
69
75
-
<script>
76
-
document.addEventListener("click", function (event) {
77
-
const dropdowns = document.querySelectorAll(".nav-dropdown");
78
-
dropdowns.forEach(function (dropdown) {
70
+
<script>
71
+
document.addEventListener('click', function(event) {
72
+
const dropdowns = document.querySelectorAll('.nav-dropdown');
73
+
dropdowns.forEach(function(dropdown) {
79
74
if (!dropdown.contains(event.target)) {
80
-
dropdown.removeAttribute("open");
75
+
dropdown.removeAttribute('open');
81
76
}
82
-
});
83
77
});
84
-
</script>
78
+
});
79
+
</script>
85
80
{{ end }}
+65
-155
appview/pages/templates/legal/privacy.html
+65
-155
appview/pages/templates/legal/privacy.html
···
1
-
{{ define "title" }}privacy policy{{ end }}
1
+
{{ define "title" }} privacy policy {{ end }}
2
2
{{ define "content" }}
3
-
<div class="max-w-4xl mx-auto px-4 py-8">
3
+
<div class="max-w-4xl mx-auto px-4 py-8">
4
4
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-8">
5
-
<div class="prose prose-gray dark:prose-invert max-w-none">
5
+
<div class="prose prose-gray dark:prose-invert max-w-none">
6
6
<h1>Privacy Policy</h1>
7
7
8
-
<p>
9
-
<strong>Last updated:</strong>
10
-
{{ now.Format "January 2, 2006" }}
11
-
</p>
8
+
<p><strong>Last updated:</strong> {{ now.Format "January 2, 2006" }}</p>
12
9
13
-
<p>
14
-
This Privacy Policy describes how Tangled ("we," "us," or "our")
15
-
collects, uses, and shares your personal information when you use our
16
-
platform and services (the "Service").
17
-
</p>
10
+
<p>This Privacy Policy describes how Tangled ("we," "us," or "our") collects, uses, and shares your personal information when you use our platform and services (the "Service").</p>
18
11
19
12
<h2>1. Information We Collect</h2>
20
13
21
14
<h3>Account Information</h3>
22
15
<p>When you create an account, we collect:</p>
23
16
<ul>
24
-
<li>Your chosen username</li>
25
-
<li>Email address</li>
26
-
<li>Profile information you choose to provide</li>
27
-
<li>Authentication data</li>
17
+
<li>Your chosen username</li>
18
+
<li>Email address</li>
19
+
<li>Profile information you choose to provide</li>
20
+
<li>Authentication data</li>
28
21
</ul>
29
22
30
23
<h3>Content and Activity</h3>
31
24
<p>We store:</p>
32
25
<ul>
33
-
<li>Code repositories and associated metadata</li>
34
-
<li>Issues, pull requests, and comments</li>
35
-
<li>Activity logs and usage patterns</li>
36
-
<li>Public keys for authentication</li>
26
+
<li>Code repositories and associated metadata</li>
27
+
<li>Issues, pull requests, and comments</li>
28
+
<li>Activity logs and usage patterns</li>
29
+
<li>Public keys for authentication</li>
37
30
</ul>
38
31
39
32
<h2>2. Data Location and Hosting</h2>
40
-
<div
41
-
class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 my-6">
42
-
<h3 class="text-blue-800 dark:text-blue-200 font-semibold mb-2">
43
-
EU Data Hosting
44
-
</h3>
45
-
<p class="text-blue-700 dark:text-blue-300">
46
-
<strong>
47
-
All Tangled service data is hosted within the European Union.
48
-
</strong>
49
-
Specifically:
50
-
</p>
51
-
<ul class="text-blue-700 dark:text-blue-300 mt-2">
52
-
<li>
53
-
<strong>Personal Data Servers (PDS):</strong>
54
-
Accounts hosted on Tangled PDS (*.tngl.sh) are located in Finland
55
-
</li>
56
-
<li>
57
-
<strong>Application Data:</strong>
58
-
All other service data is stored on EU-based servers
59
-
</li>
60
-
<li>
61
-
<strong>Data Processing:</strong>
62
-
All data processing occurs within EU jurisdiction
63
-
</li>
64
-
</ul>
33
+
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 my-6">
34
+
<h3 class="text-blue-800 dark:text-blue-200 font-semibold mb-2">EU Data Hosting</h3>
35
+
<p class="text-blue-700 dark:text-blue-300">
36
+
<strong>All Tangled service data is hosted within the European Union.</strong> Specifically:
37
+
</p>
38
+
<ul class="text-blue-700 dark:text-blue-300 mt-2">
39
+
<li><strong>Personal Data Servers (PDS):</strong> Accounts hosted on Tangled PDS (*.tngl.sh) are located in Finland</li>
40
+
<li><strong>Application Data:</strong> All other service data is stored on EU-based servers</li>
41
+
<li><strong>Data Processing:</strong> All data processing occurs within EU jurisdiction</li>
42
+
</ul>
65
43
</div>
66
44
67
-
<div
68
-
class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4 my-6">
69
-
<h3 class="text-yellow-800 dark:text-yellow-200 font-semibold mb-2">
70
-
External PDS Notice
71
-
</h3>
72
-
<p class="text-yellow-700 dark:text-yellow-300">
73
-
<strong>Important:</strong>
74
-
If your account is hosted on Bluesky's PDS or other self-hosted
75
-
Personal Data Servers (not *.tngl.sh), we do not control that data.
76
-
The data protection, storage location, and privacy practices for
77
-
such accounts are governed by the respective PDS provider's
78
-
policies, not this Privacy Policy. We only control data processing
79
-
within our own services and infrastructure.
80
-
</p>
45
+
<div class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4 my-6">
46
+
<h3 class="text-yellow-800 dark:text-yellow-200 font-semibold mb-2">External PDS Notice</h3>
47
+
<p class="text-yellow-700 dark:text-yellow-300">
48
+
<strong>Important:</strong> If your account is hosted on Bluesky's PDS or other self-hosted Personal Data Servers (not *.tngl.sh), we do not control that data. The data protection, storage location, and privacy practices for such accounts are governed by the respective PDS provider's policies, not this Privacy Policy. We only control data processing within our own services and infrastructure.
49
+
</p>
81
50
</div>
82
51
83
52
<h2>3. Third-Party Data Processors</h2>
84
-
<p>
85
-
We only share your data with the following third-party processors:
86
-
</p>
53
+
<p>We only share your data with the following third-party processors:</p>
87
54
88
55
<h3>Resend (Email Services)</h3>
89
56
<ul>
90
-
<li>
91
-
<strong>Purpose:</strong>
92
-
Sending transactional emails (account verification, notifications)
93
-
</li>
94
-
<li>
95
-
<strong>Data Shared:</strong>
96
-
Email address and necessary message content
97
-
</li>
98
-
<li>
99
-
<strong>Location:</strong>
100
-
EU-compliant email delivery service
101
-
</li>
57
+
<li><strong>Purpose:</strong> Sending transactional emails (account verification, notifications)</li>
58
+
<li><strong>Data Shared:</strong> Email address and necessary message content</li>
59
+
<li><strong>Location:</strong> EU-compliant email delivery service</li>
102
60
</ul>
103
61
104
62
<h3>Cloudflare (Image Caching)</h3>
105
63
<ul>
106
-
<li>
107
-
<strong>Purpose:</strong>
108
-
Caching and optimizing image delivery
109
-
</li>
110
-
<li>
111
-
<strong>Data Shared:</strong>
112
-
Public images and associated metadata for caching purposes
113
-
</li>
114
-
<li>
115
-
<strong>Location:</strong>
116
-
Global CDN with EU data protection compliance
117
-
</li>
64
+
<li><strong>Purpose:</strong> Caching and optimizing image delivery</li>
65
+
<li><strong>Data Shared:</strong> Public images and associated metadata for caching purposes</li>
66
+
<li><strong>Location:</strong> Global CDN with EU data protection compliance</li>
118
67
</ul>
119
68
120
69
<h2>4. How We Use Your Information</h2>
121
70
<p>We use your information to:</p>
122
71
<ul>
123
-
<li>Provide and maintain the Service</li>
124
-
<li>Process your transactions and requests</li>
125
-
<li>Send you technical notices and support messages</li>
126
-
<li>Improve and develop new features</li>
127
-
<li>Ensure security and prevent fraud</li>
128
-
<li>Comply with legal obligations</li>
72
+
<li>Provide and maintain the Service</li>
73
+
<li>Process your transactions and requests</li>
74
+
<li>Send you technical notices and support messages</li>
75
+
<li>Improve and develop new features</li>
76
+
<li>Ensure security and prevent fraud</li>
77
+
<li>Comply with legal obligations</li>
129
78
</ul>
130
79
131
80
<h2>5. Data Sharing and Disclosure</h2>
132
-
<p>
133
-
We do not sell, trade, or rent your personal information. We may share
134
-
your information only in the following circumstances:
135
-
</p>
81
+
<p>We do not sell, trade, or rent your personal information. We may share your information only in the following circumstances:</p>
136
82
<ul>
137
-
<li>With the third-party processors listed above</li>
138
-
<li>When required by law or legal process</li>
139
-
<li>
140
-
To protect our rights, property, or safety, or that of our users
141
-
</li>
142
-
<li>
143
-
In connection with a merger, acquisition, or sale of assets (with
144
-
appropriate protections)
145
-
</li>
83
+
<li>With the third-party processors listed above</li>
84
+
<li>When required by law or legal process</li>
85
+
<li>To protect our rights, property, or safety, or that of our users</li>
86
+
<li>In connection with a merger, acquisition, or sale of assets (with appropriate protections)</li>
146
87
</ul>
147
88
148
89
<h2>6. Data Security</h2>
149
-
<p>
150
-
We implement appropriate technical and organizational measures to
151
-
protect your personal information against unauthorized access,
152
-
alteration, disclosure, or destruction. However, no method of
153
-
transmission over the Internet is 100% secure.
154
-
</p>
90
+
<p>We implement appropriate technical and organizational measures to protect your personal information against unauthorized access, alteration, disclosure, or destruction. However, no method of transmission over the Internet is 100% secure.</p>
155
91
156
92
<h2>7. Data Retention</h2>
157
-
<p>
158
-
We retain your personal information for as long as necessary to
159
-
provide the Service and fulfill the purposes outlined in this Privacy
160
-
Policy, unless a longer retention period is required by law.
161
-
</p>
93
+
<p>We retain your personal information for as long as necessary to provide the Service and fulfill the purposes outlined in this Privacy Policy, unless a longer retention period is required by law.</p>
162
94
163
95
<h2>8. Your Rights</h2>
164
96
<p>Under applicable data protection laws, you have the right to:</p>
165
97
<ul>
166
-
<li>Access your personal information</li>
167
-
<li>Correct inaccurate information</li>
168
-
<li>Request deletion of your information</li>
169
-
<li>Object to processing of your information</li>
170
-
<li>Data portability</li>
171
-
<li>Withdraw consent (where applicable)</li>
98
+
<li>Access your personal information</li>
99
+
<li>Correct inaccurate information</li>
100
+
<li>Request deletion of your information</li>
101
+
<li>Object to processing of your information</li>
102
+
<li>Data portability</li>
103
+
<li>Withdraw consent (where applicable)</li>
172
104
</ul>
173
105
174
106
<h2>9. Cookies and Tracking</h2>
175
107
<p>We use cookies and similar technologies to:</p>
176
108
<ul>
177
-
<li>Maintain your login session</li>
178
-
<li>Remember your preferences</li>
179
-
<li>Analyze usage patterns to improve the Service</li>
109
+
<li>Maintain your login session</li>
110
+
<li>Remember your preferences</li>
111
+
<li>Analyze usage patterns to improve the Service</li>
180
112
</ul>
181
113
<p>You can control cookie settings through your browser preferences.</p>
182
114
183
115
<h2>10. Children's Privacy</h2>
184
-
<p>
185
-
The Service is not intended for children under 16 years of age. We do
186
-
not knowingly collect personal information from children under 16. If
187
-
we become aware that we have collected such information, we will take
188
-
steps to delete it.
189
-
</p>
116
+
<p>The Service is not intended for children under 16 years of age. We do not knowingly collect personal information from children under 16. If we become aware that we have collected such information, we will take steps to delete it.</p>
190
117
191
118
<h2>11. International Data Transfers</h2>
192
-
<p>
193
-
While all our primary data processing occurs within the EU, some of
194
-
our third-party processors may process data outside the EU. When this
195
-
occurs, we ensure appropriate safeguards are in place, such as
196
-
Standard Contractual Clauses or adequacy decisions.
197
-
</p>
119
+
<p>While all our primary data processing occurs within the EU, some of our third-party processors may process data outside the EU. When this occurs, we ensure appropriate safeguards are in place, such as Standard Contractual Clauses or adequacy decisions.</p>
198
120
199
121
<h2>12. Changes to This Privacy Policy</h2>
200
-
<p>
201
-
We may update this Privacy Policy from time to time. We will notify
202
-
you of any changes by posting the new Privacy Policy on this page and
203
-
updating the "Last updated" date.
204
-
</p>
122
+
<p>We may update this Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on this page and updating the "Last updated" date.</p>
205
123
206
124
<h2>13. Contact Information</h2>
207
-
<p>
208
-
If you have any questions about this Privacy Policy or wish to
209
-
exercise your rights, please contact us through our platform or via
210
-
email.
211
-
</p>
125
+
<p>If you have any questions about this Privacy Policy or wish to exercise your rights, please contact us through our platform or via email.</p>
212
126
213
-
<div
214
-
class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
215
-
<p>
216
-
This Privacy Policy complies with the EU General Data Protection
217
-
Regulation (GDPR) and other applicable data protection laws.
218
-
</p>
127
+
<div class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
128
+
<p>This Privacy Policy complies with the EU General Data Protection Regulation (GDPR) and other applicable data protection laws.</p>
129
+
</div>
219
130
</div>
220
-
</div>
221
131
</div>
222
-
</div>
132
+
</div>
223
133
{{ end }}
+32
-118
appview/pages/templates/legal/terms.html
+32
-118
appview/pages/templates/legal/terms.html
···
1
1
{{ define "title" }}terms of service{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<div class="max-w-4xl mx-auto px-4 py-8">
4
+
<div class="max-w-4xl mx-auto px-4 py-8">
5
5
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-8">
6
-
<div class="prose prose-gray dark:prose-invert max-w-none">
6
+
<div class="prose prose-gray dark:prose-invert max-w-none">
7
7
<h1>Terms of Service</h1>
8
8
9
-
<p>
10
-
<strong>Last updated:</strong>
11
-
{{ now.Format "January 2, 2006" }}
12
-
</p>
9
+
<p><strong>Last updated:</strong> {{ now.Format "January 2, 2006" }}</p>
13
10
14
-
<p>
15
-
Welcome to Tangled. These Terms of Service ("Terms") govern your
16
-
access to and use of the Tangled platform and services (the "Service")
17
-
operated by us ("Tangled," "we," "us," or "our").
18
-
</p>
11
+
<p>Welcome to Tangled. These Terms of Service ("Terms") govern your access to and use of the Tangled platform and services (the "Service") operated by us ("Tangled," "we," "us," or "our").</p>
19
12
20
13
<h2>1. Acceptance of Terms</h2>
21
-
<p>
22
-
By accessing or using our Service, you agree to be bound by these
23
-
Terms. If you disagree with any part of these terms, then you may not
24
-
access the Service.
25
-
</p>
14
+
<p>By accessing or using our Service, you agree to be bound by these Terms. If you disagree with any part of these terms, then you may not access the Service.</p>
26
15
27
16
<h2>2. Account Registration</h2>
28
-
<p>
29
-
To use certain features of the Service, you must register for an
30
-
account. You agree to provide accurate, current, and complete
31
-
information during the registration process and to update such
32
-
information to keep it accurate, current, and complete.
33
-
</p>
17
+
<p>To use certain features of the Service, you must register for an account. You agree to provide accurate, current, and complete information during the registration process and to update such information to keep it accurate, current, and complete.</p>
34
18
35
19
<h2>3. Account Termination</h2>
36
-
<div
37
-
class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 my-6">
38
-
<h3 class="text-red-800 dark:text-red-200 font-semibold mb-2">
39
-
Important Notice
40
-
</h3>
41
-
<p class="text-red-700 dark:text-red-300">
42
-
<strong>
43
-
We reserve the right to terminate, suspend, or restrict access to
44
-
your account at any time, for any reason, or for no reason at all,
45
-
at our sole discretion.
46
-
</strong>
47
-
This includes, but is not limited to, termination for violation of
48
-
these Terms, inappropriate conduct, spam, abuse, or any other
49
-
behavior we deem harmful to the Service or other users.
50
-
</p>
51
-
<p class="text-red-700 dark:text-red-300 mt-2">
52
-
Account termination may result in the loss of access to your
53
-
repositories, data, and other content associated with your account.
54
-
We are not obligated to provide advance notice of termination,
55
-
though we may do so in our discretion.
56
-
</p>
20
+
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 my-6">
21
+
<h3 class="text-red-800 dark:text-red-200 font-semibold mb-2">Important Notice</h3>
22
+
<p class="text-red-700 dark:text-red-300">
23
+
<strong>We reserve the right to terminate, suspend, or restrict access to your account at any time, for any reason, or for no reason at all, at our sole discretion.</strong> This includes, but is not limited to, termination for violation of these Terms, inappropriate conduct, spam, abuse, or any other behavior we deem harmful to the Service or other users.
24
+
</p>
25
+
<p class="text-red-700 dark:text-red-300 mt-2">
26
+
Account termination may result in the loss of access to your repositories, data, and other content associated with your account. We are not obligated to provide advance notice of termination, though we may do so in our discretion.
27
+
</p>
57
28
</div>
58
29
59
30
<h2>4. Acceptable Use</h2>
60
31
<p>You agree not to use the Service to:</p>
61
32
<ul>
62
-
<li>Violate any applicable laws or regulations</li>
63
-
<li>Infringe upon the rights of others</li>
64
-
<li>
65
-
Upload, store, or share content that is illegal, harmful,
66
-
threatening, abusive, harassing, defamatory, vulgar, obscene, or
67
-
otherwise objectionable
68
-
</li>
69
-
<li>Engage in spam, phishing, or other deceptive practices</li>
70
-
<li>
71
-
Attempt to gain unauthorized access to the Service or other users'
72
-
accounts
73
-
</li>
74
-
<li>
75
-
Interfere with or disrupt the Service or servers connected to the
76
-
Service
77
-
</li>
33
+
<li>Violate any applicable laws or regulations</li>
34
+
<li>Infringe upon the rights of others</li>
35
+
<li>Upload, store, or share content that is illegal, harmful, threatening, abusive, harassing, defamatory, vulgar, obscene, or otherwise objectionable</li>
36
+
<li>Engage in spam, phishing, or other deceptive practices</li>
37
+
<li>Attempt to gain unauthorized access to the Service or other users' accounts</li>
38
+
<li>Interfere with or disrupt the Service or servers connected to the Service</li>
78
39
</ul>
79
40
80
41
<h2>5. Content and Intellectual Property</h2>
81
-
<p>
82
-
You retain ownership of the content you upload to the Service. By
83
-
uploading content, you grant us a non-exclusive, worldwide,
84
-
royalty-free license to use, reproduce, modify, and distribute your
85
-
content as necessary to provide the Service.
86
-
</p>
42
+
<p>You retain ownership of the content you upload to the Service. By uploading content, you grant us a non-exclusive, worldwide, royalty-free license to use, reproduce, modify, and distribute your content as necessary to provide the Service.</p>
87
43
88
44
<h2>6. Privacy</h2>
89
-
<p>
90
-
Your privacy is important to us. Please review our
91
-
<a
92
-
href="/privacy"
93
-
class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">
94
-
Privacy Policy
95
-
</a>
96
-
, which also governs your use of the Service.
97
-
</p>
45
+
<p>Your privacy is important to us. Please review our <a href="/privacy" class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">Privacy Policy</a>, which also governs your use of the Service.</p>
98
46
99
47
<h2>7. Disclaimers</h2>
100
-
<p>
101
-
The Service is provided on an "AS IS" and "AS AVAILABLE" basis. We
102
-
make no warranties, expressed or implied, and hereby disclaim and
103
-
negate all other warranties including without limitation, implied
104
-
warranties or conditions of merchantability, fitness for a particular
105
-
purpose, or non-infringement of intellectual property or other
106
-
violation of rights.
107
-
</p>
48
+
<p>The Service is provided on an "AS IS" and "AS AVAILABLE" basis. We make no warranties, expressed or implied, and hereby disclaim and negate all other warranties including without limitation, implied warranties or conditions of merchantability, fitness for a particular purpose, or non-infringement of intellectual property or other violation of rights.</p>
108
49
109
50
<h2>8. Limitation of Liability</h2>
110
-
<p>
111
-
In no event shall Tangled, nor its directors, employees, partners,
112
-
agents, suppliers, or affiliates, be liable for any indirect,
113
-
incidental, special, consequential, or punitive damages, including
114
-
without limitation, loss of profits, data, use, goodwill, or other
115
-
intangible losses, resulting from your use of the Service.
116
-
</p>
51
+
<p>In no event shall Tangled, nor its directors, employees, partners, agents, suppliers, or affiliates, be liable for any indirect, incidental, special, consequential, or punitive damages, including without limitation, loss of profits, data, use, goodwill, or other intangible losses, resulting from your use of the Service.</p>
117
52
118
53
<h2>9. Indemnification</h2>
119
-
<p>
120
-
You agree to defend, indemnify, and hold harmless Tangled and its
121
-
affiliates, officers, directors, employees, and agents from and
122
-
against any and all claims, damages, obligations, losses, liabilities,
123
-
costs, or debt, and expenses (including attorney's fees).
124
-
</p>
54
+
<p>You agree to defend, indemnify, and hold harmless Tangled and its affiliates, officers, directors, employees, and agents from and against any and all claims, damages, obligations, losses, liabilities, costs, or debt, and expenses (including attorney's fees).</p>
125
55
126
56
<h2>10. Governing Law</h2>
127
-
<p>
128
-
These Terms shall be interpreted and governed by the laws of Finland,
129
-
without regard to its conflict of law provisions.
130
-
</p>
57
+
<p>These Terms shall be interpreted and governed by the laws of Finland, without regard to its conflict of law provisions.</p>
131
58
132
59
<h2>11. Changes to Terms</h2>
133
-
<p>
134
-
We reserve the right to modify or replace these Terms at any time. If
135
-
a revision is material, we will try to provide at least 30 days notice
136
-
prior to any new terms taking effect.
137
-
</p>
60
+
<p>We reserve the right to modify or replace these Terms at any time. If a revision is material, we will try to provide at least 30 days notice prior to any new terms taking effect.</p>
138
61
139
62
<h2>12. Contact Information</h2>
140
-
<p>
141
-
If you have any questions about these Terms of Service, please contact
142
-
us through our platform or via email.
143
-
</p>
63
+
<p>If you have any questions about these Terms of Service, please contact us through our platform or via email.</p>
144
64
145
-
<div
146
-
class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
147
-
<p>
148
-
These terms are effective as of the last updated date shown above
149
-
and will remain in effect except with respect to any changes in
150
-
their provisions in the future, which will be in effect immediately
151
-
after being posted on this page.
152
-
</p>
65
+
<div class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
66
+
<p>These terms are effective as of the last updated date shown above and will remain in effect except with respect to any changes in their provisions in the future, which will be in effect immediately after being posted on this page.</p>
67
+
</div>
153
68
</div>
154
-
</div>
155
69
</div>
156
-
</div>
70
+
</div>
157
71
{{ end }}
+70
-93
appview/pages/templates/repo/blob.html
+70
-93
appview/pages/templates/repo/blob.html
···
1
-
{{ define "title" }}
2
-
{{ .Path }} at {{ .Ref }} ·
3
-
{{ .RepoInfo.FullName }}
4
-
{{ end }}
1
+
{{ define "title" }}{{ .Path }} at {{ .Ref }} · {{ .RepoInfo.FullName }}{{ end }}
5
2
6
3
{{ define "extrameta" }}
7
-
{{ template "repo/fragments/meta" . }}
4
+
{{ template "repo/fragments/meta" . }}
5
+
6
+
{{ $title := printf "%s at %s · %s" .Path .Ref .RepoInfo.FullName }}
7
+
{{ $url := printf "https://tangled.sh/%s/blob/%s/%s" .RepoInfo.FullName .Ref .Path }}
8
8
9
-
{{ $title := printf "%s at %s · %s" .Path .Ref .RepoInfo.FullName }}
10
-
{{ $url := printf "https://tangled.sh/%s/blob/%s/%s" .RepoInfo.FullName .Ref .Path }}
9
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
11
10
12
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
13
11
{{ end }}
14
12
15
13
{{ define "repoContent" }}
16
-
{{ $lines := split .Contents }}
17
-
{{ $tot_lines := len $lines }}
18
-
{{ $tot_chars := len (printf "%d" $tot_lines) }}
19
-
{{ $code_number_style := "text-gray-400 dark:text-gray-500 left-0 bg-white dark:bg-gray-800 text-right mr-6 select-none inline-block w-12" }}
20
-
{{ $linkstyle := "no-underline hover:underline" }}
21
-
<div
22
-
class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
23
-
<div class="flex flex-col md:flex-row md:justify-between gap-2">
24
-
<div
25
-
id="breadcrumbs"
26
-
class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
27
-
{{ range $idx, $value := .BreadCrumbs }}
28
-
{{ if ne $idx (sub (len $.BreadCrumbs) 1) }}
29
-
<a
30
-
href="{{ index . 1 }}"
31
-
class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}">
32
-
{{ pathUnescape (index . 0) }}
33
-
</a>
34
-
/
35
-
{{ else }}
36
-
<span class="text-bold text-black dark:text-white">
37
-
{{ pathUnescape (index . 0) }}
38
-
</span>
39
-
{{ end }}
40
-
{{ end }}
41
-
</div>
42
-
<div
43
-
id="file-info"
44
-
class="text-gray-500 dark:text-gray-400 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0">
45
-
<span>
46
-
at
47
-
<a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a>
48
-
</span>
49
-
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
50
-
<span>{{ .Lines }} lines</span>
51
-
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
52
-
<span>{{ byteFmt .SizeHint }}</span>
53
-
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
54
-
<a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">
55
-
view raw
56
-
</a>
57
-
{{ if .RenderToggle }}
58
-
<span
59
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
60
-
<a
61
-
href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}"
62
-
hx-boost="true">
63
-
view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}
64
-
</a>
65
-
{{ end }}
66
-
</div>
14
+
{{ $lines := split .Contents }}
15
+
{{ $tot_lines := len $lines }}
16
+
{{ $tot_chars := len (printf "%d" $tot_lines) }}
17
+
{{ $code_number_style := "text-gray-400 dark:text-gray-500 left-0 bg-white dark:bg-gray-800 text-right mr-6 select-none inline-block w-12" }}
18
+
{{ $linkstyle := "no-underline hover:underline" }}
19
+
<div class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
20
+
<div class="flex flex-col md:flex-row md:justify-between gap-2">
21
+
<div id="breadcrumbs" class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
22
+
{{ range $idx, $value := .BreadCrumbs }}
23
+
{{ if ne $idx (sub (len $.BreadCrumbs) 1) }}
24
+
<a
25
+
href="{{ index . 1 }}"
26
+
class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}"
27
+
>{{ pathUnescape (index . 0) }}</a
28
+
>
29
+
/
30
+
{{ else }}
31
+
<span class="text-bold text-black dark:text-white"
32
+
>{{ pathUnescape (index . 0) }}</span
33
+
>
34
+
{{ end }}
35
+
{{ end }}
36
+
</div>
37
+
<div id="file-info" class="text-gray-500 dark:text-gray-400 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0">
38
+
<span>at <a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a></span>
39
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
40
+
<span>{{ .Lines }} lines</span>
41
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
42
+
<span>{{ byteFmt .SizeHint }}</span>
43
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
44
+
<a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">view raw</a>
45
+
{{ if .RenderToggle }}
46
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
47
+
<a
48
+
href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}"
49
+
hx-boost="true"
50
+
>view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}</a>
51
+
{{ end }}
52
+
</div>
53
+
</div>
67
54
</div>
68
-
</div>
69
-
{{ if and .IsBinary .Unsupported }}
70
-
<p class="text-center text-gray-400 dark:text-gray-500">
71
-
Previews are not supported for this file type.
72
-
</p>
73
-
{{ else if .IsBinary }}
74
-
<div class="text-center">
75
-
{{ if .IsImage }}
76
-
<img
77
-
src="{{ .ContentSrc }}"
78
-
alt="{{ .Path }}"
79
-
class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" />
80
-
{{ else if .IsVideo }}
81
-
<video
82
-
controls
83
-
class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded">
84
-
<source src="{{ .ContentSrc }}" />
85
-
Your browser does not support the video tag.
86
-
</video>
87
-
{{ end }}
88
-
</div>
89
-
{{ else }}
55
+
{{ if and .IsBinary .Unsupported }}
56
+
<p class="text-center text-gray-400 dark:text-gray-500">
57
+
Previews are not supported for this file type.
58
+
</p>
59
+
{{ else if .IsBinary }}
60
+
<div class="text-center">
61
+
{{ if .IsImage }}
62
+
<img src="{{ .ContentSrc }}"
63
+
alt="{{ .Path }}"
64
+
class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" />
65
+
{{ else if .IsVideo }}
66
+
<video controls class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded">
67
+
<source src="{{ .ContentSrc }}">
68
+
Your browser does not support the video tag.
69
+
</video>
70
+
{{ end }}
71
+
</div>
72
+
{{ else }}
90
73
<div class="overflow-auto relative">
91
-
{{ if .ShowRendered }}
92
-
<div id="blob-contents" class="prose dark:prose-invert">
93
-
{{ .RenderedContents }}
94
-
</div>
95
-
{{ else }}
96
-
<div
97
-
id="blob-contents"
98
-
class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">
99
-
{{ $.Contents | escapeHtml }}
100
-
</div>
101
-
{{ end }}
74
+
{{ if .ShowRendered }}
75
+
<div id="blob-contents" class="prose dark:prose-invert">{{ .RenderedContents }}</div>
76
+
{{ else }}
77
+
<div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ $.Contents | escapeHtml }}</div>
78
+
{{ end }}
102
79
</div>
103
-
{{ end }}
80
+
{{ end }}
104
81
{{ end }}
+83
-116
appview/pages/templates/repo/branches.html
+83
-116
appview/pages/templates/repo/branches.html
···
1
1
{{ define "title" }}
2
-
branches ·
3
-
{{ .RepoInfo.FullName }}
2
+
branches · {{ .RepoInfo.FullName }}
4
3
{{ end }}
5
4
6
5
{{ define "extrameta" }}
7
-
{{ $title := printf "branches · %s" .RepoInfo.FullName }}
8
-
{{ $url := printf "https://tangled.sh/%s/branches" .RepoInfo.FullName }}
9
-
10
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
6
+
{{ $title := printf "branches · %s" .RepoInfo.FullName }}
7
+
{{ $url := printf "https://tangled.sh/%s/branches" .RepoInfo.FullName }}
8
+
9
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
11
10
{{ end }}
12
11
13
12
{{ define "repoContent" }}
14
-
<section id="branches-table" class="overflow-x-auto">
15
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">Branches</h2>
13
+
<section id="branches-table" class="overflow-x-auto">
14
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
15
+
Branches
16
+
</h2>
16
17
17
-
<!-- desktop view (hidden on small screens) -->
18
-
<table class="w-full border-collapse hidden md:table">
19
-
<thead>
20
-
<tr>
21
-
<th
22
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
23
-
Name
24
-
</th>
25
-
<th
26
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
27
-
Commit
28
-
</th>
29
-
<th
30
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
31
-
Message
32
-
</th>
33
-
<th
34
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
35
-
Date
36
-
</th>
37
-
</tr>
38
-
</thead>
39
-
<tbody>
40
-
{{ range $index, $branch := .Branches }}
41
-
<tr
42
-
class="{{ if ne $index (sub (len $.Branches) 1) }}
43
-
border-b border-gray-200 dark:border-gray-700
44
-
{{ end }}">
45
-
<td class="py-3 whitespace-nowrap">
46
-
<a
47
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}"
48
-
class="no-underline hover:underline flex items-center gap-2">
49
-
<span class="dark:text-white">
50
-
{{ .Name }}
51
-
</span>
52
-
{{ if .IsDefault }}
53
-
<span
54
-
class="
18
+
<!-- desktop view (hidden on small screens) -->
19
+
<table class="w-full border-collapse hidden md:table">
20
+
<thead>
21
+
<tr>
22
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Name</th>
23
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Commit</th>
24
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Message</th>
25
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Date</th>
26
+
</tr>
27
+
</thead>
28
+
<tbody>
29
+
{{ range $index, $branch := .Branches }}
30
+
<tr class="{{ if ne $index (sub (len $.Branches) 1) }}border-b border-gray-200 dark:border-gray-700{{ end }}">
31
+
<td class="py-3 whitespace-nowrap">
32
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}" class="no-underline hover:underline flex items-center gap-2">
33
+
<span class="dark:text-white">
34
+
{{ .Name }}
35
+
</span>
36
+
{{ if .IsDefault }}
37
+
<span class="
55
38
text-sm rounded
56
39
bg-gray-100 dark:bg-gray-700 text-black dark:text-white
57
40
font-mono
58
41
px-2 mx-1/2
59
42
inline-flex items-center
60
43
">
61
-
default
62
-
</span>
63
-
{{ end }}
64
-
</a>
65
-
</td>
66
-
<td class="py-3 whitespace-nowrap">
67
-
{{ if .Commit }}
68
-
<a
69
-
href="/{{ $.RepoInfo.FullName }}/commits/{{ .Name | urlquery }}"
70
-
class="font-mono text-gray-700 dark:text-gray-300 no-underline hover:underline">
71
-
{{ slice .Commit.Hash.String 0 8 }}
72
-
</a>
73
-
{{ end }}
74
-
</td>
75
-
<td class="py-3 whitespace-nowrap">
76
-
{{ if .Commit }}
77
-
{{ $messageParts := splitN .Commit.Message "\n\n" 2 }}
78
-
<span class="text-gray-700 dark:text-gray-300">
79
-
{{ index $messageParts 0 }}
80
-
</span>
81
-
{{ end }}
82
-
</td>
83
-
<td class="py-3 whitespace-nowrap text-gray-500 dark:text-gray-400">
84
-
{{ if .Commit }}
85
-
{{ template "repo/fragments/time" .Commit.Committer.When }}
86
-
{{ end }}
87
-
</td>
88
-
</tr>
89
-
{{ end }}
90
-
</tbody>
91
-
</table>
44
+
default
45
+
</span>
46
+
{{ end }}
47
+
</a>
48
+
</td>
49
+
<td class="py-3 whitespace-nowrap">
50
+
{{ if .Commit }}
51
+
<a href="/{{ $.RepoInfo.FullName }}/commits/{{ .Name | urlquery }}" class="font-mono text-gray-700 dark:text-gray-300 no-underline hover:underline">{{ slice .Commit.Hash.String 0 8 }}</a>
52
+
{{ end }}
53
+
</td>
54
+
<td class="py-3 whitespace-nowrap">
55
+
{{ if .Commit }}
56
+
{{ $messageParts := splitN .Commit.Message "\n\n" 2 }}
57
+
<span class="text-gray-700 dark:text-gray-300">{{ index $messageParts 0 }}</span>
58
+
{{ end }}
59
+
</td>
60
+
<td class="py-3 whitespace-nowrap text-gray-500 dark:text-gray-400">
61
+
{{ if .Commit }}
62
+
{{ template "repo/fragments/time" .Commit.Committer.When }}
63
+
{{ end }}
64
+
</td>
65
+
</tr>
66
+
{{ end }}
67
+
</tbody>
68
+
</table>
92
69
93
-
<!-- mobile view (visible only on small screens) -->
94
-
<div class="md:hidden">
95
-
{{ range $index, $branch := .Branches }}
96
-
<div
97
-
class="relative p-2 {{ if ne $index (sub (len $.Branches) 1) }}
98
-
border-b border-gray-200 dark:border-gray-700
99
-
{{ end }}">
100
-
<div class="flex items-center justify-between">
101
-
<a
102
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}"
103
-
class="no-underline hover:underline flex items-center gap-2">
104
-
<span class="dark:text-white font-medium">
105
-
{{ .Name }}
106
-
</span>
107
-
{{ if .IsDefault }}
108
-
<span
109
-
class="
70
+
<!-- mobile view (visible only on small screens) -->
71
+
<div class="md:hidden">
72
+
{{ range $index, $branch := .Branches }}
73
+
<div class="relative p-2 {{ if ne $index (sub (len $.Branches) 1) }}border-b border-gray-200 dark:border-gray-700{{ end }}">
74
+
<div class="flex items-center justify-between">
75
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}" class="no-underline hover:underline flex items-center gap-2">
76
+
<span class="dark:text-white font-medium">
77
+
{{ .Name }}
78
+
</span>
79
+
{{ if .IsDefault }}
80
+
<span class="
110
81
text-xs rounded
111
82
bg-gray-100 dark:bg-gray-700 text-black dark:text-white
112
83
font-mono
113
84
px-2
114
85
inline-flex items-center
115
86
">
116
-
default
117
-
</span>
118
-
{{ end }}
119
-
</a>
120
-
</div>
87
+
default
88
+
</span>
89
+
{{ end }}
90
+
</a>
91
+
</div>
121
92
122
-
{{ if .Commit }}
123
-
<div
124
-
class="text-xs text-gray-500 dark:text-gray-400 mt-1 flex items-center">
125
-
<span class="font-mono">
126
-
<a
127
-
href="/{{ $.RepoInfo.FullName }}/commits/{{ .Name | urlquery }}"
128
-
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
129
-
{{ slice .Commit.Hash.String 0 8 }}
130
-
</a>
131
-
</span>
132
-
<div
133
-
class="inline-block px-1 select-none after:content-['·']"></div>
134
-
{{ template "repo/fragments/time" .Commit.Committer.When }}
135
-
</div>
136
-
{{ end }}
137
-
</div>
93
+
{{ if .Commit }}
94
+
<div class="text-xs text-gray-500 dark:text-gray-400 mt-1 flex items-center">
95
+
<span class="font-mono">
96
+
<a href="/{{ $.RepoInfo.FullName }}/commits/{{ .Name | urlquery }}" class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
97
+
{{ slice .Commit.Hash.String 0 8 }}
98
+
</a>
99
+
</span>
100
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
101
+
{{ template "repo/fragments/time" .Commit.Committer.When }}
102
+
</div>
138
103
{{ end }}
139
104
</div>
140
-
</section>
105
+
{{ end }}
106
+
</div>
107
+
</section>
141
108
{{ end }}
+59
-92
appview/pages/templates/repo/commit.html
+59
-92
appview/pages/templates/repo/commit.html
···
1
-
{{ define "title" }}
2
-
commit {{ .Diff.Commit.This }} ·
3
-
{{ .RepoInfo.FullName }}
4
-
{{ end }}
1
+
{{ define "title" }} commit {{ .Diff.Commit.This }} · {{ .RepoInfo.FullName }} {{ end }}
5
2
6
3
{{ define "extrameta" }}
7
-
{{ $title := printf "commit %s · %s" .Diff.Commit.This .RepoInfo.FullName }}
8
-
{{ $url := printf "https://tangled.sh/%s/commit/%s" .RepoInfo.FullName .Diff.Commit.This }}
4
+
{{ $title := printf "commit %s · %s" .Diff.Commit.This .RepoInfo.FullName }}
5
+
{{ $url := printf "https://tangled.sh/%s/commit/%s" .RepoInfo.FullName .Diff.Commit.This }}
9
6
10
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
7
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
11
8
{{ end }}
9
+
12
10
13
11
{{ define "repoContent" }}
14
12
15
-
{{ $repo := .RepoInfo.FullName }}
16
-
{{ $commit := .Diff.Commit }}
13
+
{{ $repo := .RepoInfo.FullName }}
14
+
{{ $commit := .Diff.Commit }}
17
15
18
-
19
-
<section class="commit dark:text-white">
20
-
<div id="commit-message">
21
-
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
22
-
<div>
23
-
<p class="pb-2">{{ index $messageParts 0 }}</p>
24
-
{{ if gt (len $messageParts) 1 }}
25
-
<p class="mt-1 cursor-text pb-2 text-sm">
26
-
{{ nl2br (index $messageParts 1) }}
27
-
</p>
28
-
{{ end }}
29
-
</div>
16
+
<section class="commit dark:text-white">
17
+
<div id="commit-message">
18
+
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
19
+
<div>
20
+
<p class="pb-2">{{ index $messageParts 0 }}</p>
21
+
{{ if gt (len $messageParts) 1 }}
22
+
<p class="mt-1 cursor-text pb-2 text-sm">{{ nl2br (index $messageParts 1) }}</p>
23
+
{{ end }}
30
24
</div>
25
+
</div>
31
26
32
-
<div class="flex items-center space-x-2">
27
+
<div class="flex items-center space-x-2">
33
28
<p class="text-sm text-gray-500 dark:text-gray-300">
34
-
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
29
+
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
35
30
36
-
{{ if $didOrHandle }}
37
-
<a
38
-
href="/{{ $didOrHandle }}"
39
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
40
-
{{ $didOrHandle }}
41
-
</a>
42
-
{{ else }}
43
-
<a
44
-
href="mailto:{{ $commit.Author.Email }}"
45
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
46
-
{{ $commit.Author.Name }}
47
-
</a>
48
-
{{ end }}
49
-
<span class="px-1 select-none before:content-['\00B7']"></span>
50
-
{{ template "repo/fragments/time" $commit.Author.When }}
51
-
<span class="px-1 select-none before:content-['\00B7']"></span>
31
+
{{ if $didOrHandle }}
32
+
<a href="/{{ $didOrHandle }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ $didOrHandle }}</a>
33
+
{{ else }}
34
+
<a href="mailto:{{ $commit.Author.Email }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ $commit.Author.Name }}</a>
35
+
{{ end }}
36
+
<span class="px-1 select-none before:content-['\00B7']"></span>
37
+
{{ template "repo/fragments/time" $commit.Author.When }}
38
+
<span class="px-1 select-none before:content-['\00B7']"></span>
52
39
</p>
53
40
54
41
<p class="flex items-center text-sm text-gray-500 dark:text-gray-300">
55
-
<a
56
-
href="/{{ $repo }}/commit/{{ $commit.This }}"
57
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
58
-
{{ slice $commit.This 0 8 }}
59
-
</a>
60
-
{{ if $commit.Parent }}
42
+
<a href="/{{ $repo }}/commit/{{ $commit.This }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ slice $commit.This 0 8 }}</a>
43
+
{{ if $commit.Parent }}
61
44
{{ i "arrow-left" "w-3 h-3 mx-1" }}
62
-
<a
63
-
href="/{{ $repo }}/commit/{{ $commit.Parent }}"
64
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
65
-
{{ slice $commit.Parent 0 8 }}
66
-
</a>
67
-
{{ end }}
45
+
<a href="/{{ $repo }}/commit/{{ $commit.Parent }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ slice $commit.Parent 0 8 }}</a>
46
+
{{ end }}
68
47
</p>
69
48
70
49
{{ if .VerifiedCommit.IsVerified $commit.This }}
71
-
<div class="group relative inline-block text-sm">
72
-
<div
73
-
class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 rounded cursor-pointer">
74
-
<div class="flex items-center gap-2">
75
-
{{ i "shield-check" "w-4 h-4" }}
76
-
verified
77
-
</div>
50
+
<div class="group relative inline-block text-sm">
51
+
<div class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 rounded cursor-pointer">
52
+
<div class="flex items-center gap-2">
53
+
{{ i "shield-check" "w-4 h-4" }}
54
+
verified
55
+
</div>
78
56
</div>
79
-
<div
80
-
class="absolute z-[9999] hidden group-hover:block bg-white dark:bg-gray-900 text-sm text-black dark:text-white rounded-md shadow-md p-4 w-80 top-full mt-2">
81
-
<div class="mb-1">
82
-
This commit was signed with the committer's
83
-
<span class="text-green-600 font-semibold">known signature</span>
84
-
.
85
-
</div>
86
-
<div class="flex items-center gap-2 my-2">
87
-
{{ i "user" "w-4 h-4" }}
88
-
{{ $committerDidOrHandle := index $.EmailToDidOrHandle $commit.Committer.Email }}
89
-
<a href="/{{ $committerDidOrHandle }}">
90
-
{{ template "user/fragments/picHandleLink" $committerDidOrHandle }}
91
-
</a>
92
-
</div>
93
-
<div class="my-1 pt-2 text-xs border-t">
94
-
<div class="text-gray-600 dark:text-gray-300">
95
-
SSH Key Fingerprint:
57
+
<div class="absolute z-[9999] hidden group-hover:block bg-white dark:bg-gray-900 text-sm text-black dark:text-white rounded-md shadow-md p-4 w-80 top-full mt-2">
58
+
<div class="mb-1">This commit was signed with the committer's <span class="text-green-600 font-semibold">known signature</span>.</div>
59
+
<div class="flex items-center gap-2 my-2">
60
+
{{ i "user" "w-4 h-4" }}
61
+
{{ $committerDidOrHandle := index $.EmailToDidOrHandle $commit.Committer.Email }}
62
+
<a href="/{{ $committerDidOrHandle }}">{{ template "user/fragments/picHandleLink" $committerDidOrHandle }}</a>
96
63
</div>
97
-
<div class="break-all">
98
-
{{ .VerifiedCommit.Fingerprint $commit.This }}
64
+
<div class="my-1 pt-2 text-xs border-t">
65
+
<div class="text-gray-600 dark:text-gray-300">SSH Key Fingerprint:</div>
66
+
<div class="break-all">{{ .VerifiedCommit.Fingerprint $commit.This }}</div>
99
67
</div>
100
-
</div>
101
68
</div>
102
-
</div>
69
+
</div>
103
70
{{ end }}
104
-
105
71
106
72
<div class="text-sm">
107
73
{{ if $.Pipeline }}
108
74
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $.Pipeline "RepoInfo" $.RepoInfo) }}
109
75
{{ end }}
110
76
</div>
111
-
</div>
112
-
</section>
113
-
{{ end }}
77
+
</div>
78
+
79
+
</section>
80
+
{{end}}
114
81
115
82
{{ define "topbarLayout" }}
116
83
<header class="px-1 col-span-full" style="z-index: 20;">
···
125
92
{{ end }}
126
93
127
94
{{ block "contentAfterLayout" . }}
128
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
129
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
130
-
{{ block "contentAfterLeft" . }}{{ end }}
131
-
</div>
132
-
<main class="col-span-1 md:col-span-10">
133
-
{{ block "contentAfter" . }}{{ end }}
134
-
</main>
95
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
96
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
97
+
{{ block "contentAfterLeft" . }} {{ end }}
135
98
</div>
99
+
<main class="col-span-1 md:col-span-10">
100
+
{{ block "contentAfter" . }}{{ end }}
101
+
</main>
102
+
</div>
136
103
{{ end }}
137
104
</div>
138
105
{{ end }}
···
145
112
146
113
{{ define "contentAfter" }}
147
114
{{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }}
148
-
{{ end }}
115
+
{{end}}
149
116
150
117
{{ define "contentAfterLeft" }}
151
118
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
154
121
<div class="sticky top-0 flex-grow max-h-screen">
155
122
{{ template "repo/fragments/diffChangedFiles" .Diff }}
156
123
</div>
157
-
{{ end }}
124
+
{{end}}
+10
-11
appview/pages/templates/repo/compare/compare.html
+10
-11
appview/pages/templates/repo/compare/compare.html
···
1
1
{{ define "title" }}
2
-
comparing {{ .Base }} and {{ .Head }} on
3
-
{{ .RepoInfo.FullName }}
2
+
comparing {{ .Base }} and {{ .Head }} on {{ .RepoInfo.FullName }}
4
3
{{ end }}
5
4
6
5
{{ define "repoContent" }}
···
24
23
{{ end }}
25
24
26
25
{{ block "contentAfterLayout" . }}
27
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
28
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
29
-
{{ block "contentAfterLeft" . }}{{ end }}
30
-
</div>
31
-
<main class="col-span-1 md:col-span-10">
32
-
{{ block "contentAfter" . }}{{ end }}
33
-
</main>
26
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
27
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
28
+
{{ block "contentAfterLeft" . }} {{ end }}
34
29
</div>
30
+
<main class="col-span-1 md:col-span-10">
31
+
{{ block "contentAfter" . }}{{ end }}
32
+
</main>
33
+
</div>
35
34
{{ end }}
36
35
</div>
37
36
{{ end }}
···
44
43
45
44
{{ define "contentAfter" }}
46
45
{{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }}
47
-
{{ end }}
46
+
{{end}}
48
47
49
48
{{ define "contentAfterLeft" }}
50
49
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
53
52
<div class="sticky top-0 flex-grow max-h-screen">
54
53
{{ template "repo/fragments/diffChangedFiles" .Diff }}
55
54
</div>
56
-
{{ end }}
55
+
{{end}}
+9
-16
appview/pages/templates/repo/compare/new.html
+9
-16
appview/pages/templates/repo/compare/new.html
···
1
1
{{ define "title" }}
2
-
compare refs on
3
-
{{ .RepoInfo.FullName }}
2
+
compare refs on {{ .RepoInfo.FullName }}
4
3
{{ end }}
5
4
6
5
{{ define "repoContent" }}
···
10
9
{{ define "repoAfter" }}
11
10
{{ $brs := take .Branches 5 }}
12
11
{{ if $brs }}
13
-
<section
14
-
class="p-6 mt-4 rounded-br rounded-bl bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm w-full mx-auto">
12
+
<section class="p-6 mt-4 rounded-br rounded-bl bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm w-full mx-auto">
15
13
<div class="flex flex-col items-center">
16
14
<p class="text-center text-black dark:text-white">
17
-
Recently updated branches in this repository:
15
+
Recently updated branches in this repository:
18
16
</p>
19
-
<div
20
-
class="mt-4 grid grid-cols-1 divide-y divide-gray-200 dark:divide-gray-700 rounded border border-gray-200 dark:border-gray-700 w-full md:w-1/2">
21
-
{{ range $br := $brs }}
22
-
<a
23
-
href="/{{ $.RepoInfo.FullName }}/compare?head={{ $br.Name | urlquery }}"
24
-
class="no-underline hover:no-underline">
17
+
<div class="mt-4 grid grid-cols-1 divide-y divide-gray-200 dark:divide-gray-700 rounded border border-gray-200 dark:border-gray-700 w-full md:w-1/2">
18
+
{{ range $br := $brs }}
19
+
<a href="/{{ $.RepoInfo.FullName }}/compare?head={{ $br.Name | urlquery }}" class="no-underline hover:no-underline">
25
20
<div class="flex items-center justify-between p-2">
26
21
{{ $br.Name }}
27
-
<span class="text-gray-500 dark:text-gray-400">
28
-
{{ template "repo/fragments/time" $br.Commit.Committer.When }}
29
-
</span>
22
+
<span class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" $br.Commit.Committer.When }}</span>
30
23
</div>
31
24
</a>
32
-
{{ end }}
33
-
</div>
25
+
{{ end }}
26
+
</div>
34
27
</div>
35
28
</section>
36
29
{{ end }}
+17
-48
appview/pages/templates/repo/empty.html
+17
-48
appview/pages/templates/repo/empty.html
···
1
1
{{ define "title" }}{{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
{{ template "repo/fragments/meta" . }}
5
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
4
+
{{ template "repo/fragments/meta" . }}
5
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
6
6
{{ end }}
7
7
8
8
{{ define "repoContent" }}
···
10
10
{{ if gt (len .BranchesTrunc) 0 }}
11
11
<div class="flex flex-col items-center">
12
12
<p class="text-center pt-5 text-gray-400 dark:text-gray-500">
13
-
This branch is empty. Other branches in this repository are populated:
13
+
This branch is empty. Other branches in this repository are populated:
14
14
</p>
15
-
<div
16
-
class="mt-4 grid grid-cols-1 divide-y divide-gray-200 dark:divide-gray-700 rounded border border-gray-200 dark:border-gray-700 w-full md:w-1/2">
15
+
<div class="mt-4 grid grid-cols-1 divide-y divide-gray-200 dark:divide-gray-700 rounded border border-gray-200 dark:border-gray-700 w-full md:w-1/2">
17
16
{{ range $br := .BranchesTrunc }}
18
-
<a
19
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ $br.Name | urlquery }}"
20
-
class="no-underline hover:no-underline">
21
-
<div class="flex items-center justify-between p-2">
22
-
{{ $br.Name }}
23
-
<span class="text-gray-500 dark:text-gray-400">
24
-
{{ template "repo/fragments/time" $br.Commit.Committer.When }}
25
-
</span>
26
-
</div>
27
-
</a>
17
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{$br.Name | urlquery }}" class="no-underline hover:no-underline">
18
+
<div class="flex items-center justify-between p-2">
19
+
{{ $br.Name }}
20
+
<span class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" $br.Commit.Committer.When }}</span>
21
+
</div>
22
+
</a>
28
23
{{ end }}
29
24
</div>
30
25
</div>
31
26
{{ else if (and .LoggedInUser (eq .LoggedInUser.Did .RepoInfo.OwnerDid)) }}
32
27
{{ $knot := .RepoInfo.Knot }}
33
28
{{ if eq $knot "knot1.tangled.sh" }}
34
-
{{ $knot = "tangled.sh" }}
29
+
{{ $knot = "tangled.sh" }}
35
30
{{ end }}
36
31
<div class="w-full flex place-content-center">
37
32
<div class="py-6 w-fit flex flex-col gap-4">
38
33
<p>This is an empty repository. To get started:</p>
39
34
{{ $bullet := "mx-2 text-xs bg-gray-200 dark:bg-gray-600 rounded-full size-5 flex items-center justify-center font-mono inline-flex align-middle" }}
40
35
41
-
42
-
<p>
43
-
<span class="{{ $bullet }}">1</span>
44
-
First, generate a new
45
-
<a
46
-
href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key"
47
-
class="underline">
48
-
SSH key pair
49
-
</a>
50
-
.
51
-
</p>
52
-
<p>
53
-
<span class="{{ $bullet }}">2</span>
54
-
Then add the public key to your account from the
55
-
<a href="/settings" class="underline">settings</a>
56
-
page.
57
-
</p>
58
-
<p>
59
-
<span class="{{ $bullet }}">3</span>
60
-
Configure your remote to
61
-
<code>
62
-
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}
63
-
</code>
64
-
</p>
65
-
<p>
66
-
<span class="{{ $bullet }}">4</span>
67
-
Push!
68
-
</p>
36
+
<p><span class="{{$bullet}}">1</span>First, generate a new <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key" class="underline">SSH key pair</a>.</p>
37
+
<p><span class="{{$bullet}}">2</span>Then add the public key to your account from the <a href="/settings" class="underline">settings</a> page.</p>
38
+
<p><span class="{{$bullet}}">3</span>Configure your remote to <code>git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code></p>
39
+
<p><span class="{{$bullet}}">4</span>Push!</p>
69
40
</div>
70
41
</div>
71
42
{{ else }}
72
-
<p class="text-gray-400 dark:text-gray-500 py-6 text-center">
73
-
This is an empty repository.
74
-
</p>
43
+
<p class="text-gray-400 dark:text-gray-500 py-6 text-center">This is an empty repository.</p>
75
44
{{ end }}
76
45
</main>
77
46
{{ end }}
78
47
79
48
{{ define "repoAfter" }}
80
-
{{ template "repo/fragments/cloneInstructions" . }}
49
+
{{ template "repo/fragments/cloneInstructions" . }}
81
50
{{ end }}
+31
-41
appview/pages/templates/repo/fork.html
+31
-41
appview/pages/templates/repo/fork.html
···
1
1
{{ define "title" }}fork · {{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<div class="p-6">
5
-
<p class="text-xl font-bold dark:text-white">
6
-
Fork
7
-
{{ .RepoInfo.FullName }}
8
-
</p>
9
-
</div>
10
-
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
11
-
<form
12
-
hx-post="/{{ .RepoInfo.FullName }}/fork"
13
-
class="space-y-12"
14
-
hx-swap="none">
15
-
<fieldset class="space-y-3">
16
-
<legend class="dark:text-white">Select a knot to fork into</legend>
17
-
<div class="space-y-2">
18
-
<div class="flex flex-col">
19
-
{{ range .Knots }}
20
-
<div class="flex items-center">
21
-
<input
22
-
type="radio"
23
-
name="knot"
24
-
value="{{ . }}"
25
-
class="mr-2"
26
-
id="domain-{{ . }}" />
27
-
<span class="dark:text-white">{{ . }}</span>
28
-
</div>
29
-
{{ else }}
30
-
<p class="dark:text-white">No knots available.</p>
31
-
{{ end }}
4
+
<div class="p-6">
5
+
<p class="text-xl font-bold dark:text-white">Fork {{ .RepoInfo.FullName }}</p>
6
+
</div>
7
+
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
8
+
<form hx-post="/{{ .RepoInfo.FullName }}/fork" class="space-y-12" hx-swap="none">
9
+
<fieldset class="space-y-3">
10
+
<legend class="dark:text-white">Select a knot to fork into</legend>
11
+
<div class="space-y-2">
12
+
<div class="flex flex-col">
13
+
{{ range .Knots }}
14
+
<div class="flex items-center">
15
+
<input
16
+
type="radio"
17
+
name="knot"
18
+
value="{{ . }}"
19
+
class="mr-2"
20
+
id="domain-{{ . }}"
21
+
/>
22
+
<span class="dark:text-white">{{ . }}</span>
32
23
</div>
24
+
{{ else }}
25
+
<p class="dark:text-white">No knots available.</p>
26
+
{{ end }}
33
27
</div>
34
-
<p class="text-sm text-gray-500 dark:text-gray-400">
35
-
A knot hosts repository data.
36
-
<a href="/knots" class="underline">
37
-
Learn how to register your own knot.
38
-
</a>
39
-
</p>
40
-
</fieldset>
41
-
42
-
<div class="space-y-2">
43
-
<button type="submit" class="btn">fork repo</button>
44
-
<div id="repo" class="error"></div>
45
28
</div>
46
-
</form>
47
-
</div>
29
+
<p class="text-sm text-gray-500 dark:text-gray-400">A knot hosts repository data. <a href="/knots" class="underline">Learn how to register your own knot.</a></p>
30
+
</fieldset>
31
+
32
+
<div class="space-y-2">
33
+
<button type="submit" class="btn">fork repo</button>
34
+
<div id="repo" class="error"></div>
35
+
</div>
36
+
</form>
37
+
</div>
48
38
{{ end }}
+13
-27
appview/pages/templates/repo/fragments/artifact.html
+13
-27
appview/pages/templates/repo/fragments/artifact.html
···
1
1
{{ define "repo/fragments/artifact" }}
2
-
{{ $unique := .Artifact.BlobCid.String }}
3
-
<div
4
-
id="artifact-{{ $unique }}"
5
-
class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
6
-
<div id="left-side" class="flex items-center gap-2 min-w-0 max-w-[60%]">
7
-
{{ i "box" "w-4 h-4" }}
8
-
<a
9
-
href="/{{ .RepoInfo.FullName }}/tags/{{ .Artifact.Tag.String }}/download/{{ .Artifact.Name | urlquery }}"
10
-
class="no-underline hover:no-underline">
11
-
{{ .Artifact.Name }}
12
-
</a>
13
-
<span class="text-gray-500 dark:text-gray-400 pl-2 text-sm">
14
-
{{ byteFmt .Artifact.Size }}
15
-
</span>
16
-
</div>
2
+
{{ $unique := .Artifact.BlobCid.String }}
3
+
<div id="artifact-{{ $unique }}" class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
4
+
<div id="left-side" class="flex items-center gap-2 min-w-0 max-w-[60%]">
5
+
{{ i "box" "w-4 h-4" }}
6
+
<a href="/{{ .RepoInfo.FullName }}/tags/{{ .Artifact.Tag.String }}/download/{{ .Artifact.Name | urlquery }}" class="no-underline hover:no-underline">
7
+
{{ .Artifact.Name }}
8
+
</a>
9
+
<span class="text-gray-500 dark:text-gray-400 pl-2 text-sm">{{ byteFmt .Artifact.Size }}</span>
10
+
</div>
17
11
18
-
<div
19
-
id="right-side"
20
-
class="text-gray-500 dark:text-gray-400 flex items-center flex-shrink-0 gap-2 text-sm">
21
-
<span class="hidden md:inline">
22
-
{{ template "repo/fragments/time" .Artifact.CreatedAt }}
23
-
</span>
24
-
<span class=" md:hidden">
25
-
{{ template "repo/fragments/shortTime" .Artifact.CreatedAt }}
26
-
</span>
12
+
<div id="right-side" class="text-gray-500 dark:text-gray-400 flex items-center flex-shrink-0 gap-2 text-sm">
13
+
<span class="hidden md:inline">{{ template "repo/fragments/time" .Artifact.CreatedAt }}</span>
14
+
<span class=" md:hidden">{{ template "repo/fragments/shortTime" .Artifact.CreatedAt }}</span>
27
15
28
16
<span class="select-none after:content-['·'] hidden md:inline"></span>
29
-
<span class="truncate max-w-[100px] hidden md:inline">
30
-
{{ .Artifact.MimeType }}
31
-
</span>
17
+
<span class="truncate max-w-[100px] hidden md:inline">{{ .Artifact.MimeType }}</span>
32
18
33
19
{{ if and .LoggedInUser (eq .LoggedInUser.Did .Artifact.Did) }}
34
20
<button
+49
-48
appview/pages/templates/repo/fragments/cloneInstructions.html
+49
-48
appview/pages/templates/repo/fragments/cloneInstructions.html
···
1
1
{{ define "repo/fragments/cloneInstructions" }}
2
-
{{ $knot := .RepoInfo.Knot }}
3
-
{{ if eq $knot "knot1.tangled.sh" }}
4
-
{{ $knot = "tangled.sh" }}
5
-
{{ end }}
6
-
<section
7
-
class="mt-4 p-6 rounded drop-shadow-sm bg-white dark:bg-gray-800 dark:text-white w-full mx-auto overflow-auto flex flex-col gap-4">
8
-
<div class="flex flex-col gap-2">
9
-
<strong>push</strong>
10
-
<div class="md:pl-4 overflow-x-auto whitespace-nowrap">
11
-
<code class="dark:text-gray-100">
12
-
git remote add origin
13
-
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}
14
-
</code>
15
-
</div>
16
-
</div>
2
+
{{ $knot := .RepoInfo.Knot }}
3
+
{{ if eq $knot "knot1.tangled.sh" }}
4
+
{{ $knot = "tangled.sh" }}
5
+
{{ end }}
6
+
<section
7
+
class="mt-4 p-6 rounded drop-shadow-sm bg-white dark:bg-gray-800 dark:text-white w-full mx-auto overflow-auto flex flex-col gap-4"
8
+
>
9
+
<div class="flex flex-col gap-2">
10
+
<strong>push</strong>
11
+
<div class="md:pl-4 overflow-x-auto whitespace-nowrap">
12
+
<code class="dark:text-gray-100"
13
+
>git remote add origin
14
+
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code
15
+
>
16
+
</div>
17
+
</div>
17
18
18
-
<div class="flex flex-col gap-2">
19
-
<strong>clone</strong>
20
-
<div class="md:pl-4 flex flex-col gap-2">
21
-
<div class="flex items-center gap-3">
22
-
<span
23
-
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white">
24
-
HTTP
25
-
</span>
26
-
<div class="overflow-x-auto whitespace-nowrap flex-1">
27
-
<code class="dark:text-gray-100">
28
-
git clone
29
-
https://tangled.sh/{{ .RepoInfo.OwnerWithAt }}/{{ .RepoInfo.Name }}
30
-
</code>
31
-
</div>
32
-
</div>
19
+
<div class="flex flex-col gap-2">
20
+
<strong>clone</strong>
21
+
<div class="md:pl-4 flex flex-col gap-2">
22
+
<div class="flex items-center gap-3">
23
+
<span
24
+
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white"
25
+
>HTTP</span
26
+
>
27
+
<div class="overflow-x-auto whitespace-nowrap flex-1">
28
+
<code class="dark:text-gray-100"
29
+
>git clone
30
+
https://tangled.sh/{{ .RepoInfo.OwnerWithAt }}/{{ .RepoInfo.Name }}</code
31
+
>
32
+
</div>
33
+
</div>
33
34
34
-
<div class="flex items-center gap-3">
35
-
<span
36
-
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white">
37
-
SSH
38
-
</span>
39
-
<div class="overflow-x-auto whitespace-nowrap flex-1">
40
-
<code class="dark:text-gray-100">
41
-
git clone
42
-
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}
43
-
</code>
44
-
</div>
35
+
<div class="flex items-center gap-3">
36
+
<span
37
+
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white"
38
+
>SSH</span
39
+
>
40
+
<div class="overflow-x-auto whitespace-nowrap flex-1">
41
+
<code class="dark:text-gray-100"
42
+
>git clone
43
+
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code
44
+
>
45
+
</div>
46
+
</div>
47
+
</div>
45
48
</div>
46
-
</div>
47
-
</div>
48
49
49
-
<p class="py-2 text-gray-500 dark:text-gray-400">
50
-
Note that for self-hosted knots, clone URLs may be different based on your
51
-
setup.
52
-
</p>
53
-
</section>
50
+
<p class="py-2 text-gray-500 dark:text-gray-400">
51
+
Note that for self-hosted knots, clone URLs may be different based
52
+
on your setup.
53
+
</p>
54
+
</section>
54
55
{{ end }}
+22
-20
appview/pages/templates/repo/fragments/compareAllowPull.html
+22
-20
appview/pages/templates/repo/fragments/compareAllowPull.html
···
1
1
{{ define "repo/fragments/compareAllowPull" }}
2
-
<div
3
-
class="flex items-baseline justify-normal gap-4"
4
-
id="allow-pull"
5
-
hx-oob-swap="true">
6
-
<p>
7
-
This comparison can be turned into a pull request to be reviewed and
8
-
discussed.
9
-
</p>
2
+
<div
3
+
class="flex items-baseline justify-normal gap-4"
4
+
id="allow-pull"
5
+
hx-oob-swap="true"
6
+
>
7
+
<p>
8
+
This comparison can be turned into a pull request to be reviewed and
9
+
discussed.
10
+
</p>
10
11
11
-
{{ $newPullUrl := printf "/%s/pulls/new?strategy=branch&targetBranch=%s&sourceBranch=%s" .RepoInfo.FullName .Base .Head }}
12
+
{{ $newPullUrl := printf "/%s/pulls/new?strategy=branch&targetBranch=%s&sourceBranch=%s" .RepoInfo.FullName .Base .Head }}
12
13
13
14
14
-
<div class="flex justify-start items-center gap-2 mt-2">
15
-
<a
16
-
href="{{ $newPullUrl }}"
17
-
class="btn flex items-center gap-2 no-underline hover:no-underline">
18
-
{{ i "git-pull-request-create" "w-4 h-4" }}
19
-
create pull
20
-
<span id="create-pull-spinner" class="group">
21
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
22
-
</span>
23
-
</a>
15
+
<div class="flex justify-start items-center gap-2 mt-2">
16
+
<a
17
+
href="{{ $newPullUrl }}"
18
+
class="btn flex items-center gap-2 no-underline hover:no-underline"
19
+
>
20
+
{{ i "git-pull-request-create" "w-4 h-4" }}
21
+
create pull
22
+
<span id="create-pull-spinner" class="group">
23
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
24
+
</span>
25
+
</a>
26
+
</div>
24
27
</div>
25
-
</div>
26
28
{{ end }}
+54
-63
appview/pages/templates/repo/fragments/compareForm.html
+54
-63
appview/pages/templates/repo/fragments/compareForm.html
···
1
1
{{ define "repo/fragments/compareForm" }}
2
-
<div id="compare-select">
3
-
<h2 class="font-bold text-sm mb-2 uppercase dark:text-white">
4
-
Compare changes
5
-
</h2>
6
-
<p>Choose any two refs to compare.</p>
2
+
<div id="compare-select">
3
+
<h2 class="font-bold text-sm mb-2 uppercase dark:text-white">
4
+
Compare changes
5
+
</h2>
6
+
<p>Choose any two refs to compare.</p>
7
7
8
-
<form id="compare-form" class="flex items-center gap-2 py-4">
9
-
<div>
10
-
<span class="hidden md:inline">base:</span>
11
-
{{ block "dropdown" (list $ "base" $.Base) }}{{ end }}
12
-
</div>
13
-
<span class="flex-shrink-0">
14
-
{{ i "arrow-left" "w-4 h-4" }}
15
-
</span>
16
-
<div>
17
-
<span class="hidden md:inline">compare:</span>
18
-
{{ block "dropdown" (list $ "head" $.Head) }}{{ end }}
19
-
</div>
20
-
<button
21
-
id="compare-button"
22
-
class="btn disabled:opacity-50 disabled:cursor-not-allowed"
23
-
type="button"
24
-
hx-boost="true"
25
-
onclick="
8
+
<form id="compare-form" class="flex items-center gap-2 py-4">
9
+
<div>
10
+
<span class="hidden md:inline">base:</span>
11
+
{{ block "dropdown" (list $ "base" $.Base) }} {{ end }}
12
+
</div>
13
+
<span class="flex-shrink-0">
14
+
{{ i "arrow-left" "w-4 h-4" }}
15
+
</span>
16
+
<div>
17
+
<span class="hidden md:inline">compare:</span>
18
+
{{ block "dropdown" (list $ "head" $.Head) }} {{ end }}
19
+
</div>
20
+
<button
21
+
id="compare-button"
22
+
class="btn disabled:opacity-50 disabled:cursor-not-allowed"
23
+
type="button"
24
+
hx-boost="true"
25
+
onclick="
26
26
const base = document.getElementById('base-select').value;
27
27
const head = document.getElementById('head-select').value;
28
-
window.location.href = `/{{ $.RepoInfo.FullName }}/compare/${encodeURIComponent(base)}...${encodeURIComponent(head)}`;
28
+
window.location.href = `/{{$.RepoInfo.FullName}}/compare/${encodeURIComponent(base)}...${encodeURIComponent(head)}`;
29
29
">
30
-
go
31
-
</button>
32
-
</form>
33
-
</div>
34
-
<script>
35
-
const baseSelect = document.getElementById("base-select");
36
-
const headSelect = document.getElementById("head-select");
37
-
const compareButton = document.getElementById("compare-button");
30
+
go
31
+
</button>
32
+
</form>
33
+
</div>
34
+
<script>
35
+
const baseSelect = document.getElementById('base-select');
36
+
const headSelect = document.getElementById('head-select');
37
+
const compareButton = document.getElementById('compare-button');
38
38
39
-
function toggleButtonState() {
40
-
compareButton.disabled = baseSelect.value === headSelect.value;
41
-
}
39
+
function toggleButtonState() {
40
+
compareButton.disabled = baseSelect.value === headSelect.value;
41
+
}
42
42
43
-
baseSelect.addEventListener("change", toggleButtonState);
44
-
headSelect.addEventListener("change", toggleButtonState);
43
+
baseSelect.addEventListener('change', toggleButtonState);
44
+
headSelect.addEventListener('change', toggleButtonState);
45
45
46
-
// Run once on page load
47
-
toggleButtonState();
48
-
</script>
46
+
// Run once on page load
47
+
toggleButtonState();
48
+
</script>
49
49
{{ end }}
50
50
51
51
{{ define "dropdown" }}
52
-
{{ $root := index . 0 }}
53
-
{{ $name := index . 1 }}
54
-
{{ $default := index . 2 }}
55
-
<select
56
-
name="{{ $name }}"
57
-
id="{{ $name }}-select"
58
-
class="p-1 border max-w-32 md:max-w-64 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
52
+
{{ $root := index . 0 }}
53
+
{{ $name := index . 1 }}
54
+
{{ $default := index . 2 }}
55
+
<select name="{{$name}}" id="{{$name}}-select" class="p-1 border max-w-32 md:max-w-64 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
59
56
<optgroup label="branches ({{ len $root.Branches }})" class="bold text-sm">
60
57
{{ range $root.Branches }}
61
-
<option
62
-
value="{{ .Reference.Name }}"
63
-
class="py-1"
64
-
{{ if eq .Reference.Name $default }}selected{{ end }}>
58
+
<option value="{{ .Reference.Name }}" class="py-1" {{if eq .Reference.Name $default}}selected{{end}}>
65
59
{{ .Reference.Name }}
66
60
</option>
67
61
{{ end }}
68
62
</optgroup>
69
-
<optgroup label="tags ({{ len $root.Tags }})" class="bold text-sm">
70
-
{{ range $root.Tags }}
71
-
<option
72
-
value="{{ .Reference.Name }}"
73
-
class="py-1"
74
-
{{ if eq .Reference.Name $default }}selected{{ end }}>
75
-
{{ .Reference.Name }}
76
-
</option>
77
-
{{ else }}
78
-
<option class="py-1" disabled>no tags found</option>
79
-
{{ end }}
80
-
</optgroup>
63
+
<optgroup label="tags ({{ len $root.Tags }})" class="bold text-sm">
64
+
{{ range $root.Tags }}
65
+
<option value="{{ .Reference.Name }}" class="py-1" {{if eq .Reference.Name $default}}selected{{end}}>
66
+
{{ .Reference.Name }}
67
+
</option>
68
+
{{ else }}
69
+
<option class="py-1" disabled>no tags found</option>
70
+
{{ end }}
71
+
</optgroup>
81
72
</select>
82
73
{{ end }}
+78
-127
appview/pages/templates/repo/fragments/diff.html
+78
-127
appview/pages/templates/repo/fragments/diff.html
···
10
10
{{ $parent := $commit.Parent }}
11
11
{{ $last := sub (len $diff) 1 }}
12
12
13
-
14
13
<div class="flex flex-col gap-4">
15
14
{{ range $idx, $hunk := $diff }}
16
15
{{ with $hunk }}
17
-
<section
18
-
class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
19
-
<div id="file-{{ .Name.New }}">
20
-
<div id="diff-file">
21
-
<details open>
22
-
<summary class="list-none cursor-pointer sticky top-0">
23
-
<div
24
-
id="diff-file-header"
25
-
class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
26
-
<div
27
-
id="left-side-items"
28
-
class="p-2 flex gap-2 items-center overflow-x-auto">
29
-
<div class="flex gap-1 items-center">
30
-
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
31
-
{{ if .IsNew }}
32
-
<span
33
-
class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">
34
-
ADDED
35
-
</span>
36
-
{{ else if .IsDelete }}
37
-
<span
38
-
class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">
39
-
DELETED
40
-
</span>
41
-
{{ else if .IsCopy }}
42
-
<span
43
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
44
-
COPIED
45
-
</span>
46
-
{{ else if .IsRename }}
47
-
<span
48
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
49
-
RENAMED
50
-
</span>
51
-
{{ else }}
52
-
<span
53
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
54
-
MODIFIED
55
-
</span>
56
-
{{ end }}
16
+
<section class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
17
+
<div id="file-{{ .Name.New }}">
18
+
<div id="diff-file">
19
+
<details open>
20
+
<summary class="list-none cursor-pointer sticky top-0">
21
+
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
22
+
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
23
+
<div class="flex gap-1 items-center">
24
+
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
25
+
{{ if .IsNew }}
26
+
<span class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">ADDED</span>
27
+
{{ else if .IsDelete }}
28
+
<span class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">DELETED</span>
29
+
{{ else if .IsCopy }}
30
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">COPIED</span>
31
+
{{ else if .IsRename }}
32
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">RENAMED</span>
33
+
{{ else }}
34
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">MODIFIED</span>
35
+
{{ end }}
57
36
58
-
{{ template "repo/fragments/diffStatPill" .Stats }}
59
-
</div>
60
-
61
-
<div class="flex gap-2 items-center overflow-x-auto">
62
-
{{ if .IsDelete }}
63
-
<a
64
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
65
-
{{ if $this }}
66
-
href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"
67
-
{{ end }}>
68
-
{{ .Name.Old }}
69
-
</a>
70
-
{{ else if (or .IsCopy .IsRename) }}
71
-
<a
72
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
73
-
{{ if $parent }}
74
-
href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}"
75
-
{{ end }}>
76
-
{{ .Name.Old }}
77
-
</a>
78
-
{{ i "arrow-right" "w-4 h-4" }}
79
-
<a
80
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
81
-
{{ if $this }}
82
-
href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"
83
-
{{ end }}>
84
-
{{ .Name.New }}
85
-
</a>
86
-
{{ else }}
87
-
<a
88
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
89
-
{{ if $this }}
90
-
href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"
91
-
{{ end }}>
92
-
{{ .Name.New }}
93
-
</a>
94
-
{{ end }}
95
-
</div>
37
+
{{ template "repo/fragments/diffStatPill" .Stats }}
96
38
</div>
97
39
98
-
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
99
-
<div id="right-side-items" class="p-2 flex items-center">
100
-
<a
101
-
title="top of file"
102
-
href="#file-{{ .Name.New }}"
103
-
class="{{ $iconstyle }}">
104
-
{{ i "arrow-up-to-line" "w-4 h-4" }}
40
+
<div class="flex gap-2 items-center overflow-x-auto">
41
+
{{ if .IsDelete }}
42
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}>
43
+
{{ .Name.Old }}
105
44
</a>
106
-
{{ if gt $idx 0 }}
107
-
{{ $prev := index $diff (sub $idx 1) }}
108
-
<a
109
-
title="previous file"
110
-
href="#file-{{ $prev.Name.New }}"
111
-
class="{{ $iconstyle }}">
112
-
{{ i "arrow-up" "w-4 h-4" }}
113
-
</a>
114
-
{{ end }}
115
-
116
-
{{ if lt $idx $last }}
117
-
{{ $next := index $diff (add $idx 1) }}
118
-
<a
119
-
title="next file"
120
-
href="#file-{{ $next.Name.New }}"
121
-
class="{{ $iconstyle }}">
122
-
{{ i "arrow-down" "w-4 h-4" }}
123
-
</a>
45
+
{{ else if (or .IsCopy .IsRename) }}
46
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $parent}}href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}"{{end}}>
47
+
{{ .Name.Old }}
48
+
</a>
49
+
{{ i "arrow-right" "w-4 h-4" }}
50
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
51
+
{{ .Name.New }}
52
+
</a>
53
+
{{ else }}
54
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
55
+
{{ .Name.New }}
56
+
</a>
124
57
{{ end }}
125
58
</div>
126
59
</div>
127
-
</summary>
128
60
129
-
<div class="transition-all duration-700 ease-in-out">
130
-
{{ if .IsDelete }}
131
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
132
-
This file has been deleted.
133
-
</p>
134
-
{{ else if .IsCopy }}
135
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
136
-
This file has been copied.
137
-
</p>
138
-
{{ else if .IsBinary }}
139
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
140
-
This is a binary file and will not be displayed.
141
-
</p>
142
-
{{ else }}
143
-
{{ if $isSplit }}
144
-
{{- template "repo/fragments/splitDiff" .Split -}}
145
-
{{ else }}
146
-
{{- template "repo/fragments/unifiedDiff" . -}}
61
+
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
62
+
<div id="right-side-items" class="p-2 flex items-center">
63
+
<a title="top of file" href="#file-{{ .Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-up-to-line" "w-4 h-4" }}</a>
64
+
{{ if gt $idx 0 }}
65
+
{{ $prev := index $diff (sub $idx 1) }}
66
+
<a title="previous file" href="#file-{{ $prev.Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-up" "w-4 h-4" }}</a>
147
67
{{ end }}
148
-
{{- end -}}
68
+
69
+
{{ if lt $idx $last }}
70
+
{{ $next := index $diff (add $idx 1) }}
71
+
<a title="next file" href="#file-{{ $next.Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-down" "w-4 h-4" }}</a>
72
+
{{ end }}
73
+
</div>
74
+
149
75
</div>
150
-
</details>
151
-
</div>
76
+
</summary>
77
+
78
+
<div class="transition-all duration-700 ease-in-out">
79
+
{{ if .IsDelete }}
80
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
81
+
This file has been deleted.
82
+
</p>
83
+
{{ else if .IsCopy }}
84
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
85
+
This file has been copied.
86
+
</p>
87
+
{{ else if .IsBinary }}
88
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
89
+
This is a binary file and will not be displayed.
90
+
</p>
91
+
{{ else }}
92
+
{{ if $isSplit }}
93
+
{{- template "repo/fragments/splitDiff" .Split -}}
94
+
{{ else }}
95
+
{{- template "repo/fragments/unifiedDiff" . -}}
96
+
{{ end }}
97
+
{{- end -}}
98
+
</div>
99
+
100
+
</details>
101
+
152
102
</div>
153
-
</section>
103
+
</div>
104
+
</section>
154
105
{{ end }}
155
106
{{ end }}
156
107
</div>
+2
-5
appview/pages/templates/repo/fragments/diffChangedFiles.html
+2
-5
appview/pages/templates/repo/fragments/diffChangedFiles.html
···
1
1
{{ define "repo/fragments/diffChangedFiles" }}
2
2
{{ $stat := .Stat }}
3
3
{{ $fileTree := fileTree .ChangedFiles }}
4
-
<section
5
-
class="overflow-x-auto text-sm px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto min-h-full rounded bg-white dark:bg-gray-800 drop-shadow-sm">
4
+
<section class="overflow-x-auto text-sm px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto min-h-full rounded bg-white dark:bg-gray-800 drop-shadow-sm">
6
5
<div class="diff-stat">
7
6
<div class="flex gap-2 items-center">
8
-
<strong class="text-sm uppercase dark:text-gray-200">
9
-
Changed files
10
-
</strong>
7
+
<strong class="text-sm uppercase dark:text-gray-200">Changed files</strong>
11
8
{{ template "repo/fragments/diffStatPill" $stat }}
12
9
</div>
13
10
{{ template "repo/fragments/fileTree" $fileTree }}
+6
-14
appview/pages/templates/repo/fragments/diffOpts.html
+6
-14
appview/pages/templates/repo/fragments/diffOpts.html
···
1
1
{{ define "repo/fragments/diffOpts" }}
2
-
<section
3
-
class="flex flex-col gap-2 overflow-x-auto text-sm px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
2
+
<section class="flex flex-col gap-2 overflow-x-auto text-sm px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
4
3
<strong class="text-sm uppercase dark:text-gray-200">options</strong>
5
4
{{ $active := "unified" }}
6
5
{{ if .Split }}
7
6
{{ $active = "split" }}
8
7
{{ end }}
9
8
{{ $values := list "unified" "split" }}
10
-
{{ block "tabSelector" (dict "Name" "diff" "Values" $values "Active" $active) }}
11
-
{{ end }}
9
+
{{ block "tabSelector" (dict "Name" "diff" "Values" $values "Active" $active) }} {{ end }}
12
10
</section>
13
11
{{ end }}
14
12
···
16
14
{{ $name := .Name }}
17
15
{{ $all := .Values }}
18
16
{{ $active := .Active }}
19
-
<div
20
-
class="flex justify-between divide-x divide-gray-200 dark:divide-gray-700 rounded border border-gray-200 dark:border-gray-700 overflow-hidden">
17
+
<div class="flex justify-between divide-x divide-gray-200 dark:divide-gray-700 rounded border border-gray-200 dark:border-gray-700 overflow-hidden">
21
18
{{ $activeTab := "bg-white dark:bg-gray-700 shadow-sm" }}
22
19
{{ $inactiveTab := "bg-gray-100 dark:bg-gray-800 shadow-inner" }}
23
20
{{ range $index, $value := $all }}
24
21
{{ $isActive := eq $value $active }}
25
-
<a
26
-
href="?{{ $name }}={{ $value }}"
27
-
class="py-2 text-sm w-full block hover:no-underline text-center {{ if $isActive }}
28
-
{{ $activeTab }}
29
-
{{ else }}
30
-
{{ $inactiveTab }}
31
-
{{ end }}">
32
-
{{ $value }}
22
+
<a href="?{{ $name }}={{ $value }}"
23
+
class="py-2 text-sm w-full block hover:no-underline text-center {{ if $isActive }} {{$activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}">
24
+
{{ $value }}
33
25
</a>
34
26
{{ end }}
35
27
</div>
+5
-16
appview/pages/templates/repo/fragments/diffStatPill.html
+5
-16
appview/pages/templates/repo/fragments/diffStatPill.html
···
1
1
{{ define "repo/fragments/diffStatPill" }}
2
2
<div class="flex items-center font-mono text-sm">
3
3
{{ if and .Insertions .Deletions }}
4
-
<span
5
-
class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">
6
-
+{{ .Insertions }}
7
-
</span>
8
-
<span
9
-
class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">
10
-
-{{ .Deletions }}
11
-
</span>
4
+
<span class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span>
5
+
<span class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span>
12
6
{{ else if .Insertions }}
13
-
<span
14
-
class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">
15
-
+{{ .Insertions }}
16
-
</span>
7
+
<span class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span>
17
8
{{ else if .Deletions }}
18
-
<span
19
-
class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">
20
-
-{{ .Deletions }}
21
-
</span>
9
+
<span class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span>
22
10
{{ end }}
23
11
</div>
24
12
{{ end }}
13
+
+7
-20
appview/pages/templates/repo/fragments/editRepoDescription.html
+7
-20
appview/pages/templates/repo/fragments/editRepoDescription.html
···
1
1
{{ define "repo/fragments/editRepoDescription" }}
2
-
<form
3
-
hx-put="/{{ .RepoInfo.FullName }}/description"
4
-
hx-target="this"
5
-
hx-swap="outerHTML"
6
-
class="flex flex-wrap gap-2">
7
-
<input
8
-
type="text"
9
-
class="p-1"
10
-
name="description"
11
-
value="{{ .RepoInfo.Description }}" />
12
-
<button
13
-
type="submit"
14
-
class="btn p-1 flex items-center gap-2 no-underline text-sm">
15
-
{{ i "check" "w-3 h-3" }} save
2
+
<form hx-put="/{{ .RepoInfo.FullName }}/description" hx-target="this" hx-swap="outerHTML" class="flex flex-wrap gap-2">
3
+
<input type="text" class="p-1" name="description" value="{{ .RepoInfo.Description }}">
4
+
<button type="submit" class="btn p-1 flex items-center gap-2 no-underline text-sm">
5
+
{{ i "check" "w-3 h-3" }} save
16
6
</button>
17
-
<button
18
-
type="button"
19
-
class="btn p-1 flex items-center gap-2 no-underline text-sm"
20
-
hx-get="/{{ .RepoInfo.FullName }}/description">
21
-
{{ i "x" "w-3 h-3" }} cancel
7
+
<button type="button" class="btn p-1 flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description" >
8
+
{{ i "x" "w-3 h-3" }} cancel
22
9
</button>
23
-
</form>
10
+
</form>
24
11
{{ end }}
+3
-8
appview/pages/templates/repo/fragments/fileTree.html
+3
-8
appview/pages/templates/repo/fragments/fileTree.html
···
4
4
<summary class="cursor-pointer list-none pt-1">
5
5
<span class="tree-directory inline-flex items-center gap-2 ">
6
6
{{ i "folder" "flex-shrink-0 size-4 fill-current" }}
7
-
<span class="filename truncate text-black dark:text-white">
8
-
{{ .Name }}
9
-
</span>
7
+
<span class="filename truncate text-black dark:text-white">{{ .Name }}</span>
10
8
</span>
11
9
</summary>
12
10
<div class="ml-1 pl-2 border-l border-gray-200 dark:border-gray-700">
···
18
16
{{ else if .Name }}
19
17
<div class="tree-file flex items-center gap-2 pt-1">
20
18
{{ i "file" "flex-shrink-0 size-4" }}
21
-
<a
22
-
href="#file-{{ .Path }}"
23
-
class="filename truncate text-black dark:text-white no-underline hover:underline">
24
-
{{ .Name }}
25
-
</a>
19
+
<a href="#file-{{ .Path }}" class="filename truncate text-black dark:text-white no-underline hover:underline">{{ .Name }}</a>
26
20
</div>
27
21
{{ else }}
28
22
{{ range $child := .Children }}
···
30
24
{{ end }}
31
25
{{ end }}
32
26
{{ end }}
27
+
+82
-124
appview/pages/templates/repo/fragments/interdiff.html
+82
-124
appview/pages/templates/repo/fragments/interdiff.html
···
1
1
{{ define "repo/fragments/interdiff" }}
2
-
{{ $repo := index . 0 }}
3
-
{{ $x := index . 1 }}
4
-
{{ $opts := index . 2 }}
5
-
{{ $fileTree := fileTree $x.AffectedFiles }}
6
-
{{ $diff := $x.Files }}
7
-
{{ $last := sub (len $diff) 1 }}
8
-
{{ $isSplit := $opts.Split }}
2
+
{{ $repo := index . 0 }}
3
+
{{ $x := index . 1 }}
4
+
{{ $opts := index . 2 }}
5
+
{{ $fileTree := fileTree $x.AffectedFiles }}
6
+
{{ $diff := $x.Files }}
7
+
{{ $last := sub (len $diff) 1 }}
8
+
{{ $isSplit := $opts.Split }}
9
9
10
+
<div class="flex flex-col gap-4">
11
+
{{ range $idx, $hunk := $diff }}
12
+
{{ with $hunk }}
13
+
<section class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
14
+
<div id="file-{{ .Name }}">
15
+
<div id="diff-file">
16
+
<details {{ if not (.Status.IsOnlyInOne) }}open{{end}}>
17
+
<summary class="list-none cursor-pointer sticky top-0">
18
+
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
19
+
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
20
+
<div class="flex gap-1 items-center" style="direction: ltr;">
21
+
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
22
+
{{ if .Status.IsOk }}
23
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">CHANGED</span>
24
+
{{ else if .Status.IsUnchanged }}
25
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">UNCHANGED</span>
26
+
{{ else if .Status.IsOnlyInOne }}
27
+
<span class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">REVERTED</span>
28
+
{{ else if .Status.IsOnlyInTwo }}
29
+
<span class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">NEW</span>
30
+
{{ else if .Status.IsRebased }}
31
+
<span class="bg-amber-100 text-amber-700 dark:bg-amber-800/50 dark:text-amber-400 {{ $markerstyle }}">REBASED</span>
32
+
{{ else }}
33
+
<span class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">ERROR</span>
34
+
{{ end }}
35
+
</div>
10
36
11
-
<div class="flex flex-col gap-4">
12
-
{{ range $idx, $hunk := $diff }}
13
-
{{ with $hunk }}
14
-
<section
15
-
class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
16
-
<div id="file-{{ .Name }}">
17
-
<div id="diff-file">
18
-
<details {{ if not (.Status.IsOnlyInOne) }}open{{ end }}>
19
-
<summary class="list-none cursor-pointer sticky top-0">
20
-
<div
21
-
id="diff-file-header"
22
-
class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
23
-
<div
24
-
id="left-side-items"
25
-
class="p-2 flex gap-2 items-center overflow-x-auto">
26
-
<div
27
-
class="flex gap-1 items-center"
28
-
style="direction: ltr;">
29
-
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
30
-
{{ if .Status.IsOk }}
31
-
<span
32
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
33
-
CHANGED
34
-
</span>
35
-
{{ else if .Status.IsUnchanged }}
36
-
<span
37
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
38
-
UNCHANGED
39
-
</span>
40
-
{{ else if .Status.IsOnlyInOne }}
41
-
<span
42
-
class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">
43
-
REVERTED
44
-
</span>
45
-
{{ else if .Status.IsOnlyInTwo }}
46
-
<span
47
-
class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">
48
-
NEW
49
-
</span>
50
-
{{ else if .Status.IsRebased }}
51
-
<span
52
-
class="bg-amber-100 text-amber-700 dark:bg-amber-800/50 dark:text-amber-400 {{ $markerstyle }}">
53
-
REBASED
54
-
</span>
55
-
{{ else }}
56
-
<span
57
-
class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">
58
-
ERROR
59
-
</span>
60
-
{{ end }}
61
-
</div>
37
+
<div class="flex gap-2 items-center overflow-x-auto" style="direction: rtl;">
38
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" href="">
39
+
{{ .Name }}
40
+
</a>
41
+
</div>
42
+
</div>
62
43
63
-
<div
64
-
class="flex gap-2 items-center overflow-x-auto"
65
-
style="direction: rtl;">
66
-
<a
67
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
68
-
href="">
69
-
{{ .Name }}
70
-
</a>
71
-
</div>
72
-
</div>
44
+
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
45
+
<div id="right-side-items" class="p-2 flex items-center">
46
+
<a title="top of file" href="#file-{{ .Name }}" class="{{ $iconstyle }}">{{ i "arrow-up-to-line" "w-4 h-4" }}</a>
47
+
{{ if gt $idx 0 }}
48
+
{{ $prev := index $diff (sub $idx 1) }}
49
+
<a title="previous file" href="#file-{{ $prev.Name }}" class="{{ $iconstyle }}">{{ i "arrow-up" "w-4 h-4" }}</a>
50
+
{{ end }}
73
51
74
-
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
75
-
<div id="right-side-items" class="p-2 flex items-center">
76
-
<a
77
-
title="top of file"
78
-
href="#file-{{ .Name }}"
79
-
class="{{ $iconstyle }}">
80
-
{{ i "arrow-up-to-line" "w-4 h-4" }}
81
-
</a>
82
-
{{ if gt $idx 0 }}
83
-
{{ $prev := index $diff (sub $idx 1) }}
84
-
<a
85
-
title="previous file"
86
-
href="#file-{{ $prev.Name }}"
87
-
class="{{ $iconstyle }}">
88
-
{{ i "arrow-up" "w-4 h-4" }}
89
-
</a>
90
-
{{ end }}
52
+
{{ if lt $idx $last }}
53
+
{{ $next := index $diff (add $idx 1) }}
54
+
<a title="next file" href="#file-{{ $next.Name }}" class="{{ $iconstyle }}">{{ i "arrow-down" "w-4 h-4" }}</a>
55
+
{{ end }}
56
+
</div>
91
57
92
-
{{ if lt $idx $last }}
93
-
{{ $next := index $diff (add $idx 1) }}
94
-
<a
95
-
title="next file"
96
-
href="#file-{{ $next.Name }}"
97
-
class="{{ $iconstyle }}">
98
-
{{ i "arrow-down" "w-4 h-4" }}
99
-
</a>
100
-
{{ end }}
101
-
</div>
102
-
</div>
103
-
</summary>
58
+
</div>
59
+
</summary>
104
60
105
-
<div class="transition-all duration-700 ease-in-out">
106
-
{{ if .Status.IsUnchanged }}
107
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
108
-
This file has not been changed.
109
-
</p>
110
-
{{ else if .Status.IsRebased }}
111
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
112
-
This patch was likely rebased, as context lines do not
113
-
match.
114
-
</p>
115
-
{{ else if .Status.IsError }}
116
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
117
-
Failed to calculate interdiff for this file.
118
-
</p>
119
-
{{ else }}
120
-
{{ if $isSplit }}
121
-
{{- template "repo/fragments/splitDiff" .Split -}}
122
-
{{ else }}
123
-
{{- template "repo/fragments/unifiedDiff" . -}}
124
-
{{ end }}
125
-
{{- end -}}
126
-
</div>
127
-
</details>
61
+
<div class="transition-all duration-700 ease-in-out">
62
+
{{ if .Status.IsUnchanged }}
63
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
64
+
This file has not been changed.
65
+
</p>
66
+
{{ else if .Status.IsRebased }}
67
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
68
+
This patch was likely rebased, as context lines do not match.
69
+
</p>
70
+
{{ else if .Status.IsError }}
71
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
72
+
Failed to calculate interdiff for this file.
73
+
</p>
74
+
{{ else }}
75
+
{{ if $isSplit }}
76
+
{{- template "repo/fragments/splitDiff" .Split -}}
77
+
{{ else }}
78
+
{{- template "repo/fragments/unifiedDiff" . -}}
79
+
{{ end }}
80
+
{{- end -}}
128
81
</div>
129
-
</div>
130
-
</section>
131
-
{{ end }}
82
+
83
+
</details>
84
+
85
+
</div>
86
+
</div>
87
+
</section>
132
88
{{ end }}
133
-
</div>
89
+
{{ end }}
90
+
</div>
134
91
{{ end }}
92
+
+8
-9
appview/pages/templates/repo/fragments/interdiffFiles.html
+8
-9
appview/pages/templates/repo/fragments/interdiffFiles.html
···
1
1
{{ define "repo/fragments/interdiffFiles" }}
2
-
{{ $fileTree := fileTree .AffectedFiles }}
3
-
<section
4
-
class="mt-4 px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm min-h-full text-sm">
5
-
<div class="diff-stat">
6
-
<div class="flex gap-2 items-center">
7
-
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
8
-
</div>
9
-
{{ template "repo/fragments/fileTree" $fileTree }}
2
+
{{ $fileTree := fileTree .AffectedFiles }}
3
+
<section class="mt-4 px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm min-h-full text-sm">
4
+
<div class="diff-stat">
5
+
<div class="flex gap-2 items-center">
6
+
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
10
7
</div>
11
-
</section>
8
+
{{ template "repo/fragments/fileTree" $fileTree }}
9
+
</div>
10
+
</section>
12
11
{{ end }}
+24
-18
appview/pages/templates/repo/fragments/meta.html
+24
-18
appview/pages/templates/repo/fragments/meta.html
···
1
1
{{ define "repo/fragments/meta" }}
2
-
<meta
3
-
name="vcs:clone"
4
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}" />
5
-
<meta
6
-
name="forge:summary"
7
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}" />
8
-
<meta
9
-
name="forge:dir"
10
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}/tree/{ref}/{path}" />
11
-
<meta
12
-
name="forge:file"
13
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}" />
14
-
<meta
15
-
name="forge:line"
16
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}#L{line}" />
17
-
<meta
18
-
name="go-import"
19
-
content="tangled.sh/{{ .RepoInfo.FullNameWithoutAt }} git https://tangled.sh/{{ .RepoInfo.FullName }}" />
2
+
<meta
3
+
name="vcs:clone"
4
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}"
5
+
/>
6
+
<meta
7
+
name="forge:summary"
8
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}"
9
+
/>
10
+
<meta
11
+
name="forge:dir"
12
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}/tree/{ref}/{path}"
13
+
/>
14
+
<meta
15
+
name="forge:file"
16
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}"
17
+
/>
18
+
<meta
19
+
name="forge:line"
20
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}#L{line}"
21
+
/>
22
+
<meta
23
+
name="go-import"
24
+
content="tangled.sh/{{ .RepoInfo.FullNameWithoutAt }} git https://tangled.sh/{{ .RepoInfo.FullName }}"
25
+
/>
20
26
{{ end }}
+7
-7
appview/pages/templates/repo/fragments/og.html
+7
-7
appview/pages/templates/repo/fragments/og.html
···
1
1
{{ define "repo/fragments/og" }}
2
-
{{ $title := or .Title .RepoInfo.FullName }}
3
-
{{ $description := or .Description .RepoInfo.Description }}
4
-
{{ $url := or .Url (printf "https://tangled.sh/%s" .RepoInfo.FullName) }}
2
+
{{ $title := or .Title .RepoInfo.FullName }}
3
+
{{ $description := or .Description .RepoInfo.Description }}
4
+
{{ $url := or .Url (printf "https://tangled.sh/%s" .RepoInfo.FullName) }}
5
5
6
6
7
-
<meta property="og:title" content="{{ unescapeHtml $title }}" />
8
-
<meta property="og:type" content="object" />
9
-
<meta property="og:url" content="{{ $url }}" />
10
-
<meta property="og:description" content="{{ $description }}" />
7
+
<meta property="og:title" content="{{ unescapeHtml $title }}" />
8
+
<meta property="og:type" content="object" />
9
+
<meta property="og:url" content="{{ $url }}" />
10
+
<meta property="og:description" content="{{ $description }}" />
11
11
{{ end }}
+28
-21
appview/pages/templates/repo/fragments/reaction.html
+28
-21
appview/pages/templates/repo/fragments/reaction.html
···
1
1
{{ define "repo/fragments/reaction" }}
2
-
<button
3
-
id="reactIndi-{{ .Kind }}"
4
-
class="flex justify-center items-center min-w-8 min-h-8 rounded border
2
+
<button
3
+
id="reactIndi-{{ .Kind }}"
4
+
class="flex justify-center items-center min-w-8 min-h-8 rounded border
5
5
leading-4 px-3 gap-1
6
6
{{ if eq .Count 0 }}
7
-
hidden
8
-
{{ end }}
7
+
hidden
8
+
{{ end }}
9
9
{{ if .IsReacted }}
10
-
bg-sky-100 border-sky-400 dark:bg-sky-900 dark:border-sky-500
11
-
{{ else }}
12
-
border-gray-200 hover:bg-gray-50 hover:border-gray-300
13
-
dark:border-gray-700 dark:hover:bg-gray-700 dark:hover:border-gray-600
14
-
{{ end }}
10
+
bg-sky-100
11
+
border-sky-400
12
+
dark:bg-sky-900
13
+
dark:border-sky-500
14
+
{{ else }}
15
+
border-gray-200
16
+
hover:bg-gray-50
17
+
hover:border-gray-300
18
+
dark:border-gray-700
19
+
dark:hover:bg-gray-700
20
+
dark:hover:border-gray-600
21
+
{{ end }}
15
22
"
16
-
{{ if .IsReacted }}
17
-
hx-delete="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
18
-
{{ else }}
19
-
hx-post="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
20
-
{{ end }}
21
-
hx-swap="outerHTML"
22
-
hx-trigger="click from:(#reactBtn-{{ .Kind }}, #reactIndi-{{ .Kind }})"
23
-
hx-disabled-elt="this">
24
-
<span>{{ .Kind }}</span>
25
-
<span>{{ .Count }}</span>
26
-
</button>
23
+
{{ if .IsReacted }}
24
+
hx-delete="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
25
+
{{ else }}
26
+
hx-post="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
27
+
{{ end }}
28
+
hx-swap="outerHTML"
29
+
hx-trigger="click from:(#reactBtn-{{ .Kind }}, #reactIndi-{{ .Kind }})"
30
+
hx-disabled-elt="this"
31
+
>
32
+
<span>{{ .Kind }}</span> <span>{{ .Count }}</span>
33
+
</button>
27
34
{{ end }}
+24
-18
appview/pages/templates/repo/fragments/reactionsPopUp.html
+24
-18
appview/pages/templates/repo/fragments/reactionsPopUp.html
···
1
1
{{ define "repo/fragments/reactionsPopUp" }}
2
-
<details id="reactionsPopUp" class="relative inline-block">
3
-
<summary
4
-
class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700
2
+
<details
3
+
id="reactionsPopUp"
4
+
class="relative inline-block"
5
+
>
6
+
<summary
7
+
class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700
5
8
hover:bg-gray-50
6
9
hover:border-gray-300
7
10
dark:hover:bg-gray-700
8
11
dark:hover:border-gray-600
9
-
cursor-pointer list-none">
10
-
{{ i "smile" "size-4" }}
11
-
</summary>
12
-
<div
13
-
class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg">
14
-
{{ range $kind := . }}
15
-
<button
16
-
id="reactBtn-{{ $kind }}"
17
-
class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700"
18
-
hx-on:click="this.parentElement.parentElement.removeAttribute('open')">
19
-
{{ $kind }}
20
-
</button>
21
-
{{ end }}
22
-
</div>
23
-
</details>
12
+
cursor-pointer list-none"
13
+
>
14
+
{{ i "smile" "size-4" }}
15
+
</summary>
16
+
<div
17
+
class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg"
18
+
>
19
+
{{ range $kind := . }}
20
+
<button
21
+
id="reactBtn-{{ $kind }}"
22
+
class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700"
23
+
hx-on:click="this.parentElement.parentElement.removeAttribute('open')"
24
+
>
25
+
{{ $kind }}
26
+
</button>
27
+
{{ end }}
28
+
</div>
29
+
</details>
24
30
{{ end }}
+7
-13
appview/pages/templates/repo/fragments/repoDescription.html
+7
-13
appview/pages/templates/repo/fragments/repoDescription.html
···
1
1
{{ define "repo/fragments/repoDescription" }}
2
-
<span
3
-
id="repo-description"
4
-
class="flex flex-wrap items-center gap-2 text-sm"
5
-
hx-target="this"
6
-
hx-swap="outerHTML">
2
+
<span id="repo-description" class="flex flex-wrap items-center gap-2 text-sm" hx-target="this" hx-swap="outerHTML">
7
3
{{ if .RepoInfo.Description }}
8
-
{{ .RepoInfo.Description }}
4
+
{{ .RepoInfo.Description }}
9
5
{{ else }}
10
-
<span class="italic">this repo has no description</span>
6
+
<span class="italic">this repo has no description</span>
11
7
{{ end }}
12
8
13
9
{{ if .RepoInfo.Roles.IsOwner }}
14
-
<button
15
-
class="flex items-center gap-2 no-underline text-sm"
16
-
hx-get="/{{ .RepoInfo.FullName }}/description/edit">
17
-
{{ i "pencil" "w-3 h-3" }}
18
-
</button>
10
+
<button class="flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description/edit">
11
+
{{ i "pencil" "w-3 h-3" }}
12
+
</button>
19
13
{{ end }}
20
-
</span>
14
+
</span>
21
15
{{ end }}
+23
-22
appview/pages/templates/repo/fragments/repoStar.html
+23
-22
appview/pages/templates/repo/fragments/repoStar.html
···
1
1
{{ define "repo/fragments/repoStar" }}
2
-
<button
3
-
id="starBtn"
4
-
class="btn disabled:opacity-50 disabled:cursor-not-allowed flex gap-2 items-center group"
5
-
{{ if .IsStarred }}
6
-
hx-delete="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
7
-
{{ else }}
8
-
hx-post="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
9
-
{{ end }}
2
+
<button
3
+
id="starBtn"
4
+
class="btn disabled:opacity-50 disabled:cursor-not-allowed flex gap-2 items-center group"
5
+
{{ if .IsStarred }}
6
+
hx-delete="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
7
+
{{ else }}
8
+
hx-post="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
9
+
{{ end }}
10
10
11
-
hx-trigger="click"
12
-
hx-target="this"
13
-
hx-swap="outerHTML"
14
-
hx-disabled-elt="#starBtn">
15
-
{{ if .IsStarred }}
16
-
{{ i "star" "w-4 h-4 fill-current" }}
17
-
{{ else }}
18
-
{{ i "star" "w-4 h-4" }}
19
-
{{ end }}
20
-
<span class="text-sm">
21
-
{{ .Stats.StarCount }}
22
-
</span>
23
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
24
-
</button>
11
+
hx-trigger="click"
12
+
hx-target="this"
13
+
hx-swap="outerHTML"
14
+
hx-disabled-elt="#starBtn"
15
+
>
16
+
{{ if .IsStarred }}
17
+
{{ i "star" "w-4 h-4 fill-current" }}
18
+
{{ else }}
19
+
{{ i "star" "w-4 h-4" }}
20
+
{{ end }}
21
+
<span class="text-sm">
22
+
{{ .Stats.StarCount }}
23
+
</span>
24
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
25
+
</button>
25
26
{{ end }}
+58
-113
appview/pages/templates/repo/fragments/splitDiff.html
+58
-113
appview/pages/templates/repo/fragments/splitDiff.html
···
1
1
{{ define "repo/fragments/splitDiff" }}
2
-
{{ $name := .Id }}
3
-
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}}
4
-
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
5
-
{{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
6
-
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
7
-
{{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}}
8
-
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}}
9
-
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
10
-
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
11
-
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
12
-
<div class="grid grid-cols-2 divide-x divide-gray-200 dark:divide-gray-700">
13
-
<pre
14
-
class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}
15
-
<div
16
-
class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">
17
-
···
18
-
</div>
19
-
{{- range .LeftLines -}}
20
-
{{- if .IsEmpty -}}
21
-
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
22
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
23
-
<span aria-hidden="true" class="invisible">
24
-
{{ .LineNumber }}
25
-
</span>
26
-
</div>
27
-
<div class="{{ $opStyle }}">
28
-
<span aria-hidden="true" class="invisible">{{ .Op.String }}</span>
29
-
</div>
30
-
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
31
-
</div>
32
-
{{- else if eq .Op.String "-" -}}
33
-
<div
34
-
class="{{ $delStyle }} {{ $containerStyle }}"
35
-
id="{{ $name }}-O{{ .LineNumber }}">
36
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
37
-
<a
38
-
class="{{ $linkStyle }}"
39
-
href="#{{ $name }}-O{{ .LineNumber }}">
40
-
{{ .LineNumber }}
41
-
</a>
42
-
</div>
43
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
44
-
<div class="px-2">{{ .Content }}</div>
45
-
</div>
46
-
{{- else if eq .Op.String " " -}}
47
-
<div
48
-
class="{{ $ctxStyle }} {{ $containerStyle }}"
49
-
id="{{ $name }}-O{{ .LineNumber }}">
50
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
51
-
<a
52
-
class="{{ $linkStyle }}"
53
-
href="#{{ $name }}-O{{ .LineNumber }}">
54
-
{{ .LineNumber }}
55
-
</a>
56
-
</div>
57
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
58
-
<div class="px-2">{{ .Content }}</div>
59
-
</div>
60
-
{{- end -}}
61
-
{{- end -}}
62
-
{{- end -}}
63
-
</div></div></pre>
2
+
{{ $name := .Id }}
3
+
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}}
4
+
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
5
+
{{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
6
+
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
7
+
{{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}}
8
+
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}}
9
+
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
10
+
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
11
+
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
12
+
<div class="grid grid-cols-2 divide-x divide-gray-200 dark:divide-gray-700">
13
+
<pre class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">···</div>
14
+
{{- range .LeftLines -}}
15
+
{{- if .IsEmpty -}}
16
+
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
17
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div>
18
+
<div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div>
19
+
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
20
+
</div>
21
+
{{- else if eq .Op.String "-" -}}
22
+
<div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}">
23
+
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div>
24
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
25
+
<div class="px-2">{{ .Content }}</div>
26
+
</div>
27
+
{{- else if eq .Op.String " " -}}
28
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}">
29
+
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div>
30
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
31
+
<div class="px-2">{{ .Content }}</div>
32
+
</div>
33
+
{{- end -}}
34
+
{{- end -}}
35
+
{{- end -}}</div></div></pre>
64
36
65
-
<pre
66
-
class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}
67
-
<div
68
-
class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">
69
-
···
70
-
</div>
71
-
{{- range .RightLines -}}
72
-
{{- if .IsEmpty -}}
73
-
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
74
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
75
-
<span aria-hidden="true" class="invisible">
76
-
{{ .LineNumber }}
77
-
</span>
78
-
</div>
79
-
<div class="{{ $opStyle }}">
80
-
<span aria-hidden="true" class="invisible">{{ .Op.String }}</span>
81
-
</div>
82
-
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
83
-
</div>
84
-
{{- else if eq .Op.String "+" -}}
85
-
<div
86
-
class="{{ $addStyle }} {{ $containerStyle }}"
87
-
id="{{ $name }}-N{{ .LineNumber }}">
88
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
89
-
<a
90
-
class="{{ $linkStyle }}"
91
-
href="#{{ $name }}-N{{ .LineNumber }}">
92
-
{{ .LineNumber }}
93
-
</a>
94
-
</div>
95
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
96
-
<div class="px-2">{{ .Content }}</div>
97
-
</div>
98
-
{{- else if eq .Op.String " " -}}
99
-
<div
100
-
class="{{ $ctxStyle }} {{ $containerStyle }}"
101
-
id="{{ $name }}-N{{ .LineNumber }}">
102
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
103
-
<a
104
-
class="{{ $linkStyle }}"
105
-
href="#{{ $name }}-N{{ .LineNumber }}">
106
-
{{ .LineNumber }}
107
-
</a>
108
-
</div>
109
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
110
-
<div class="px-2">{{ .Content }}</div>
111
-
</div>
112
-
{{- end -}}
113
-
{{- end -}}
114
-
{{- end -}}</div></div></pre>
115
-
</div>
37
+
<pre class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">···</div>
38
+
{{- range .RightLines -}}
39
+
{{- if .IsEmpty -}}
40
+
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
41
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div>
42
+
<div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div>
43
+
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
44
+
</div>
45
+
{{- else if eq .Op.String "+" -}}
46
+
<div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}">
47
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div>
48
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
49
+
<div class="px-2" >{{ .Content }}</div>
50
+
</div>
51
+
{{- else if eq .Op.String " " -}}
52
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}">
53
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div>
54
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
55
+
<div class="px-2">{{ .Content }}</div>
56
+
</div>
57
+
{{- end -}}
58
+
{{- end -}}
59
+
{{- end -}}</div></div></pre>
60
+
</div>
116
61
{{ end }}
+6
-14
appview/pages/templates/repo/fragments/time.html
+6
-14
appview/pages/templates/repo/fragments/time.html
···
1
1
{{ define "repo/fragments/timeWrapper" }}
2
-
<time
3
-
datetime="{{ .Time | iso8601DateTimeFmt }}"
4
-
title="{{ .Time | longTimeFmt }}">
5
-
{{ .Content }}
6
-
</time>
2
+
<time datetime="{{ .Time | iso8601DateTimeFmt }}" title="{{ .Time | longTimeFmt }}">{{ .Content }}</time>
7
3
{{ end }}
8
4
9
5
{{ define "repo/fragments/time" }}
10
-
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | relTimeFmt)) }}
6
+
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | relTimeFmt)) }}
11
7
{{ end }}
12
8
13
9
{{ define "repo/fragments/shortTime" }}
14
-
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | shortRelTimeFmt)) }}
10
+
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | shortRelTimeFmt)) }}
15
11
{{ end }}
16
12
17
13
{{ define "repo/fragments/shortTimeAgo" }}
18
-
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (print (. | shortRelTimeFmt) " ago")) }}
14
+
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (print (. | shortRelTimeFmt) " ago")) }}
19
15
{{ end }}
20
16
21
17
{{ define "repo/fragments/duration" }}
22
-
<time
23
-
datetime="{{ . | iso8601DurationFmt }}"
24
-
title="{{ . | longDurationFmt }}">
25
-
{{ . | durationFmt }}
26
-
</time>
27
-
{{ end }}
18
+
<time datetime="{{ . | iso8601DurationFmt }}" title="{{ . | longDurationFmt }}">{{ . | durationFmt }}</time>
19
+
{{ end }}
+45
-79
appview/pages/templates/repo/fragments/unifiedDiff.html
+45
-79
appview/pages/templates/repo/fragments/unifiedDiff.html
···
1
1
{{ define "repo/fragments/unifiedDiff" }}
2
-
{{ $name := .Id }}
3
-
<pre
4
-
class="overflow-x-auto"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}
5
-
<div
6
-
class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">
7
-
···
8
-
</div>
9
-
{{- $oldStart := .OldPosition -}}
10
-
{{- $newStart := .NewPosition -}}
11
-
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800 target:bg-yellow-200 target:dark:bg-yellow-600" -}}
12
-
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
13
-
{{- $lineNrSepStyle1 := "" -}}
14
-
{{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
15
-
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
16
-
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}}
17
-
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
18
-
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
19
-
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
20
-
{{- range .Lines -}}
21
-
{{- if eq .Op.String "+" -}}
22
-
<div
23
-
class="{{ $addStyle }} {{ $containerStyle }}"
24
-
id="{{ $name }}-N{{ $newStart }}">
25
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle1 }}">
26
-
<span aria-hidden="true" class="invisible">{{ $newStart }}</span>
27
-
</div>
28
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle2 }}">
29
-
<a class="{{ $linkStyle }}" href="#{{ $name }}-N{{ $newStart }}">
30
-
{{ $newStart }}
31
-
</a>
32
-
</div>
33
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
34
-
<div class="px-2">{{ .Line }}</div>
35
-
</div>
36
-
{{- $newStart = add64 $newStart 1 -}}
37
-
{{- end -}}
38
-
{{- if eq .Op.String "-" -}}
39
-
<div
40
-
class="{{ $delStyle }} {{ $containerStyle }}"
41
-
id="{{ $name }}-O{{ $oldStart }}">
42
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle1 }}">
43
-
<a class="{{ $linkStyle }}" href="#{{ $name }}-O{{ $oldStart }}">
44
-
{{ $oldStart }}
45
-
</a>
46
-
</div>
47
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle2 }}">
48
-
<span aria-hidden="true" class="invisible">{{ $oldStart }}</span>
49
-
</div>
50
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
51
-
<div class="px-2">{{ .Line }}</div>
52
-
</div>
53
-
{{- $oldStart = add64 $oldStart 1 -}}
54
-
{{- end -}}
55
-
{{- if eq .Op.String " " -}}
56
-
<div
57
-
class="{{ $ctxStyle }} {{ $containerStyle }}"
58
-
id="{{ $name }}-O{{ $oldStart }}-N{{ $newStart }}">
59
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle1 }}">
60
-
<a
61
-
class="{{ $linkStyle }}"
62
-
href="#{{ $name }}-O{{ $oldStart }}-N{{ $newStart }}">
63
-
{{ $oldStart }}
64
-
</a>
65
-
</div>
66
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle2 }}">
67
-
<a
68
-
class="{{ $linkStyle }}"
69
-
href="#{{ $name }}-O{{ $oldStart }}-N{{ $newStart }}">
70
-
{{ $newStart }}
71
-
</a>
72
-
</div>
73
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
74
-
<div class="px-2">{{ .Line }}</div>
75
-
</div>
76
-
{{- $newStart = add64 $newStart 1 -}}
77
-
{{- $oldStart = add64 $oldStart 1 -}}
78
-
{{- end -}}
79
-
{{- end -}}
80
-
{{- end -}}</div></div></pre>
2
+
{{ $name := .Id }}
3
+
<pre class="overflow-x-auto"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">···</div>
4
+
{{- $oldStart := .OldPosition -}}
5
+
{{- $newStart := .NewPosition -}}
6
+
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800 target:bg-yellow-200 target:dark:bg-yellow-600" -}}
7
+
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
8
+
{{- $lineNrSepStyle1 := "" -}}
9
+
{{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
10
+
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
11
+
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}}
12
+
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
13
+
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
14
+
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
15
+
{{- range .Lines -}}
16
+
{{- if eq .Op.String "+" -}}
17
+
<div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{$newStart}}">
18
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div>
19
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div>
20
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
21
+
<div class="px-2">{{ .Line }}</div>
22
+
</div>
23
+
{{- $newStart = add64 $newStart 1 -}}
24
+
{{- end -}}
25
+
{{- if eq .Op.String "-" -}}
26
+
<div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}">
27
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div>
28
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div>
29
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
30
+
<div class="px-2">{{ .Line }}</div>
31
+
</div>
32
+
{{- $oldStart = add64 $oldStart 1 -}}
33
+
{{- end -}}
34
+
{{- if eq .Op.String " " -}}
35
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}-N{{$newStart}}">
36
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $oldStart }}</a></div>
37
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $newStart }}</a></div>
38
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
39
+
<div class="px-2">{{ .Line }}</div>
40
+
</div>
41
+
{{- $newStart = add64 $newStart 1 -}}
42
+
{{- $oldStart = add64 $oldStart 1 -}}
43
+
{{- end -}}
44
+
{{- end -}}
45
+
{{- end -}}</div></div></pre>
81
46
{{ end }}
47
+
+254
-308
appview/pages/templates/repo/index.html
+254
-308
appview/pages/templates/repo/index.html
···
1
1
{{ define "title" }}{{ .RepoInfo.FullName }} at {{ .Ref }}{{ end }}
2
2
3
+
3
4
{{ define "extrameta" }}
4
-
{{ template "repo/fragments/meta" . }}
5
+
{{ template "repo/fragments/meta" . }}
5
6
6
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
7
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
7
8
{{ end }}
8
9
9
10
{{ define "repoContent" }}
10
-
<main>
11
-
{{ if .Languages }}
12
-
{{ block "repoLanguages" . }}{{ end }}
13
-
{{ end }}
14
-
<div class="flex items-center justify-between pb-5">
15
-
{{ block "branchSelector" . }}{{ end }}
16
-
<div class="flex md:hidden items-center gap-4">
17
-
<a
18
-
href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}"
19
-
class="inline-flex items-center text-sm gap-1">
20
-
{{ i "git-commit-horizontal" "w-4" "h-4" }}
21
-
{{ .TotalCommits }}
22
-
</a>
23
-
<a
24
-
href="/{{ .RepoInfo.FullName }}/branches"
25
-
class="inline-flex items-center text-sm gap-1">
26
-
{{ i "git-branch" "w-4" "h-4" }}
27
-
{{ len .Branches }}
28
-
</a>
29
-
<a
30
-
href="/{{ .RepoInfo.FullName }}/tags"
31
-
class="inline-flex items-center text-sm gap-1">
32
-
{{ i "tags" "w-4" "h-4" }}
33
-
{{ len .Tags }}
34
-
</a>
35
-
</div>
36
-
</div>
37
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
38
-
{{ block "fileTree" . }}{{ end }}
39
-
{{ block "rightInfo" . }}{{ end }}
40
-
</div>
41
-
</main>
11
+
<main>
12
+
{{ if .Languages }}
13
+
{{ block "repoLanguages" . }}{{ end }}
14
+
{{ end }}
15
+
<div class="flex items-center justify-between pb-5">
16
+
{{ block "branchSelector" . }}{{ end }}
17
+
<div class="flex md:hidden items-center gap-4">
18
+
<a href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}" class="inline-flex items-center text-sm gap-1">
19
+
{{ i "git-commit-horizontal" "w-4" "h-4" }} {{ .TotalCommits }}
20
+
</a>
21
+
<a href="/{{ .RepoInfo.FullName }}/branches" class="inline-flex items-center text-sm gap-1">
22
+
{{ i "git-branch" "w-4" "h-4" }} {{ len .Branches }}
23
+
</a>
24
+
<a href="/{{ .RepoInfo.FullName }}/tags" class="inline-flex items-center text-sm gap-1">
25
+
{{ i "tags" "w-4" "h-4" }} {{ len .Tags }}
26
+
</a>
27
+
</div>
28
+
</div>
29
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
30
+
{{ block "fileTree" . }}{{ end }}
31
+
{{ block "rightInfo" . }}{{ end }}
32
+
</div>
33
+
</main>
42
34
{{ end }}
43
35
44
36
{{ define "repoLanguages" }}
45
-
<div class="flex gap-[1px] -m-6 mb-6 overflow-hidden rounded-t">
46
-
{{ range $value := .Languages }}
47
-
<div
48
-
title="{{ or $value.Name "Other" }} {{ printf "%.1f" $value.Percentage }}%"
49
-
class="h-[4px] rounded-full"
50
-
style="background-color: {{ $value.Color }}; width: {{ $value.Percentage }}%"></div>
51
-
{{ end }}
52
-
</div>
37
+
<div class="flex gap-[1px] -m-6 mb-6 overflow-hidden rounded-t">
38
+
{{ range $value := .Languages }}
39
+
<div
40
+
title='{{ or $value.Name "Other" }} {{ printf "%.1f" $value.Percentage }}%'
41
+
class="h-[4px] rounded-full"
42
+
style="background-color: {{ $value.Color }}; width: {{ $value.Percentage }}%"
43
+
></div>
44
+
{{ end }}
45
+
</div>
53
46
{{ end }}
47
+
54
48
55
49
{{ define "branchSelector" }}
56
50
<div class="flex gap-2 items-center items-stretch justify-center">
57
51
<select
58
-
onchange="window.location.href = '/{{ .RepoInfo.FullName }}/tree/' + encodeURIComponent(this.value)"
59
-
class="p-1 border max-w-32 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
60
-
<optgroup label="branches ({{ len .Branches }})" class="bold text-sm">
61
-
{{ range .Branches }}
62
-
<option
63
-
value="{{ .Reference.Name }}"
64
-
class="py-1"
65
-
{{ if eq .Reference.Name $.Ref }}
66
-
selected
67
-
{{ end }}>
68
-
{{ .Reference.Name }}
69
-
</option>
70
-
{{ end }}
71
-
</optgroup>
72
-
<optgroup label="tags ({{ len .Tags }})" class="bold text-sm">
73
-
{{ range .Tags }}
74
-
<option
75
-
value="{{ .Reference.Name }}"
76
-
class="py-1"
77
-
{{ if eq .Reference.Name $.Ref }}
78
-
selected
79
-
{{ end }}>
80
-
{{ .Reference.Name }}
81
-
</option>
82
-
{{ else }}
83
-
<option class="py-1" disabled>no tags found</option>
84
-
{{ end }}
85
-
</optgroup>
52
+
onchange="window.location.href = '/{{ .RepoInfo.FullName }}/tree/' + encodeURIComponent(this.value)"
53
+
class="p-1 border max-w-32 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"
54
+
>
55
+
<optgroup label="branches ({{len .Branches}})" class="bold text-sm">
56
+
{{ range .Branches }}
57
+
<option
58
+
value="{{ .Reference.Name }}"
59
+
class="py-1"
60
+
{{ if eq .Reference.Name $.Ref }}
61
+
selected
62
+
{{ end }}
63
+
>
64
+
{{ .Reference.Name }}
65
+
</option>
66
+
{{ end }}
67
+
</optgroup>
68
+
<optgroup label="tags ({{len .Tags}})" class="bold text-sm">
69
+
{{ range .Tags }}
70
+
<option
71
+
value="{{ .Reference.Name }}"
72
+
class="py-1"
73
+
{{ if eq .Reference.Name $.Ref }}
74
+
selected
75
+
{{ end }}
76
+
>
77
+
{{ .Reference.Name }}
78
+
</option>
79
+
{{ else }}
80
+
<option class="py-1" disabled>no tags found</option>
81
+
{{ end }}
82
+
</optgroup>
86
83
</select>
87
84
<div class="flex items-center gap-2">
88
-
{{ $isOwner := and .LoggedInUser .RepoInfo.Roles.IsOwner }}
89
-
{{ $isCollaborator := and .LoggedInUser .RepoInfo.Roles.IsCollaborator }}
90
-
{{ if and (or $isOwner $isCollaborator) .ForkInfo .ForkInfo.IsFork }}
85
+
{{ $isOwner := and .LoggedInUser .RepoInfo.Roles.IsOwner }}
86
+
{{ $isCollaborator := and .LoggedInUser .RepoInfo.Roles.IsCollaborator }}
87
+
{{ if and (or $isOwner $isCollaborator) .ForkInfo .ForkInfo.IsFork }}
91
88
{{ $disabled := "" }}
92
89
{{ $title := "" }}
93
90
{{ if eq .ForkInfo.Status 0 }}
94
-
{{ $disabled = "disabled" }}
95
-
{{ $title = "This branch is not behind the upstream" }}
91
+
{{ $disabled = "disabled" }}
92
+
{{ $title = "This branch is not behind the upstream" }}
96
93
{{ else if eq .ForkInfo.Status 2 }}
97
-
{{ $disabled = "disabled" }}
98
-
{{ $title = "This branch has conflicts that must be resolved" }}
94
+
{{ $disabled = "disabled" }}
95
+
{{ $title = "This branch has conflicts that must be resolved" }}
99
96
{{ else if eq .ForkInfo.Status 3 }}
100
-
{{ $disabled = "disabled" }}
101
-
{{ $title = "This branch does not exist on the upstream" }}
97
+
{{ $disabled = "disabled" }}
98
+
{{ $title = "This branch does not exist on the upstream" }}
102
99
{{ end }}
103
100
104
-
105
101
<button
106
-
id="syncBtn"
107
-
{{ $disabled }}
108
-
{{ if $title }}title="{{ $title }}"{{ end }}
109
-
class="btn flex gap-2 items-center disabled:opacity-50 disabled:cursor-not-allowed"
110
-
hx-post="/{{ .RepoInfo.FullName }}/fork/sync"
111
-
hx-trigger="click"
112
-
hx-swap="none">
102
+
id="syncBtn"
103
+
{{ $disabled }}
104
+
{{ if $title }}title="{{ $title }}"{{ end }}
105
+
class="btn flex gap-2 items-center disabled:opacity-50 disabled:cursor-not-allowed"
106
+
hx-post="/{{ .RepoInfo.FullName }}/fork/sync"
107
+
hx-trigger="click"
108
+
hx-swap="none"
109
+
>
113
110
{{ if $disabled }}
114
-
{{ i "refresh-cw-off" "w-4 h-4" }}
111
+
{{ i "refresh-cw-off" "w-4 h-4" }}
115
112
{{ else }}
116
-
{{ i "refresh-cw" "w-4 h-4" }}
113
+
{{ i "refresh-cw" "w-4 h-4" }}
117
114
{{ end }}
118
115
<span>sync</span>
119
116
</button>
120
-
{{ end }}
121
-
<a
122
-
href="/{{ .RepoInfo.FullName }}/compare?base={{ $.Ref | urlquery }}"
123
-
class="btn flex items-center gap-2 no-underline hover:no-underline"
124
-
title="Compare branches or tags">
125
-
{{ i "git-compare" "w-4 h-4" }}
126
-
</a>
117
+
{{ end }}
118
+
<a
119
+
href="/{{ .RepoInfo.FullName }}/compare?base={{ $.Ref | urlquery }}"
120
+
class="btn flex items-center gap-2 no-underline hover:no-underline"
121
+
title="Compare branches or tags"
122
+
>
123
+
{{ i "git-compare" "w-4 h-4" }}
124
+
</a>
127
125
</div>
128
-
</div>
126
+
</div>
129
127
{{ end }}
130
128
131
129
{{ define "fileTree" }}
132
-
<div
133
-
id="file-tree"
134
-
class="col-span-1 pr-2 md:border-r md:border-gray-200 dark:md:border-gray-700">
130
+
<div id="file-tree" class="col-span-1 pr-2 md:border-r md:border-gray-200 dark:md:border-gray-700" >
135
131
{{ $linkstyle := "no-underline hover:underline dark:text-white" }}
136
132
137
133
{{ range .Files }}
···
156
152
157
153
<div class="text-xs col-span-1 text-right">
158
154
{{ with .LastCommit }}
159
-
<a
160
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}"
161
-
class="text-gray-500 dark:text-gray-400">
162
-
{{ template "repo/fragments/time" .When }}
163
-
</a>
155
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .When }}</a>
164
156
{{ end }}
165
157
</div>
166
158
</div>
···
169
161
{{ end }}
170
162
171
163
{{ define "rightInfo" }}
172
-
<div id="right-info" class="hidden md:block col-span-1">
173
-
{{ block "commitLog" . }}{{ end }}
174
-
{{ block "branchList" . }}{{ end }}
175
-
{{ block "tagList" . }}{{ end }}
176
-
</div>
164
+
<div id="right-info" class="hidden md:block col-span-1">
165
+
{{ block "commitLog" . }} {{ end }}
166
+
{{ block "branchList" . }} {{ end }}
167
+
{{ block "tagList" . }} {{ end }}
168
+
</div>
177
169
{{ end }}
178
170
179
171
{{ define "commitLog" }}
180
-
<div id="commit-log" class="md:col-span-1 px-2 pb-4">
181
-
<div class="flex justify-between items-center">
182
-
<a
183
-
href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}"
184
-
class="flex items-center gap-2 pb-2 cursor-pointer font-bold hover:text-gray-600 dark:hover:text-gray-300 hover:no-underline">
185
-
{{ i "logs" "w-4 h-4" }} commits
186
-
<span
187
-
class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
188
-
{{ .TotalCommits }}
189
-
</span>
190
-
</a>
191
-
</div>
192
-
<div class="flex flex-col gap-6">
193
-
{{ range .CommitsTrunc }}
194
-
<div>
195
-
<div id="commit-message">
196
-
{{ $messageParts := splitN .Message "\n\n" 2 }}
197
-
<div class="text-base cursor-pointer">
198
-
<div>
199
-
<div>
200
-
<a
201
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
202
-
class="inline no-underline hover:underline dark:text-white">
203
-
{{ index $messageParts 0 }}
204
-
</a>
205
-
{{ if gt (len $messageParts) 1 }}
172
+
<div id="commit-log" class="md:col-span-1 px-2 pb-4">
173
+
<div class="flex justify-between items-center">
174
+
<a href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}" class="flex items-center gap-2 pb-2 cursor-pointer font-bold hover:text-gray-600 dark:hover:text-gray-300 hover:no-underline">
175
+
{{ i "logs" "w-4 h-4" }} commits
176
+
<span class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ .TotalCommits }}</span>
177
+
</a>
178
+
</div>
179
+
<div class="flex flex-col gap-6">
180
+
{{ range .CommitsTrunc }}
181
+
<div>
182
+
<div id="commit-message">
183
+
{{ $messageParts := splitN .Message "\n\n" 2 }}
184
+
<div class="text-base cursor-pointer">
185
+
<div>
186
+
<div>
187
+
<a
188
+
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
189
+
class="inline no-underline hover:underline dark:text-white"
190
+
>{{ index $messageParts 0 }}</a
191
+
>
192
+
{{ if gt (len $messageParts) 1 }}
206
193
207
-
<button
208
-
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
209
-
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
210
-
{{ i "ellipsis" "w-3 h-3" }}
211
-
</button>
212
-
{{ end }}
213
-
</div>
214
-
{{ if gt (len $messageParts) 1 }}
215
-
<p
216
-
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
217
-
{{ nl2br (index $messageParts 1) }}
218
-
</p>
194
+
<button
195
+
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
196
+
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')"
197
+
>
198
+
{{ i "ellipsis" "w-3 h-3" }}
199
+
</button>
219
200
{{ end }}
220
-
</div>
221
201
</div>
202
+
{{ if gt (len $messageParts) 1 }}
203
+
<p
204
+
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300"
205
+
>
206
+
{{ nl2br (index $messageParts 1) }}
207
+
</p>
208
+
{{ end }}
222
209
</div>
210
+
</div>
211
+
</div>
223
212
224
-
<!-- commit info bar -->
225
-
<div
226
-
class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center flex-wrap">
227
-
{{ $verified := $.VerifiedCommits.IsVerified .Hash.String }}
228
-
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
229
-
{{ if $verified }}
213
+
<!-- commit info bar -->
214
+
<div class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center flex-wrap">
215
+
{{ $verified := $.VerifiedCommits.IsVerified .Hash.String }}
216
+
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
217
+
{{ if $verified }}
230
218
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
231
-
{{ end }}
232
-
<span class="font-mono">
233
-
<a
234
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
235
-
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
236
-
{{ slice .Hash.String 0 8 }}
237
-
{{ if $verified }}
238
-
{{ i "shield-check" "w-3 h-3" }}
239
-
{{ end }}
219
+
{{ end }}
220
+
<span class="font-mono">
221
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
222
+
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
223
+
{{ slice .Hash.String 0 8 }}
224
+
{{ if $verified }}
225
+
{{ i "shield-check" "w-3 h-3" }}
226
+
{{ end }}
240
227
</a>
241
-
</span>
242
-
<span class="mx-1 before:content-['·'] before:select-none"></span>
243
-
<span>
244
-
{{ $didOrHandle := index $.EmailToDidOrHandle .Author.Email }}
245
-
<a
246
-
href="{{ if $didOrHandle }}
247
-
/{{ $didOrHandle }}
248
-
{{ else }}
249
-
mailto:{{ .Author.Email }}
250
-
{{ end }}"
251
-
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
252
-
{{ if $didOrHandle }}
253
-
{{ template "user/fragments/picHandleLink" $didOrHandle }}
254
-
{{ else }}
255
-
{{ .Author.Name }}
256
-
{{ end }}
257
-
</a>
258
-
</span>
259
-
<div
260
-
class="inline-block px-1 select-none after:content-['·']"></div>
261
-
{{ template "repo/fragments/time" .Committer.When }}
228
+
</span>
229
+
<span
230
+
class="mx-1 before:content-['·'] before:select-none"
231
+
></span>
232
+
<span>
233
+
{{ $didOrHandle := index $.EmailToDidOrHandle .Author.Email }}
234
+
<a
235
+
href="{{ if $didOrHandle }}
236
+
/{{ $didOrHandle }}
237
+
{{ else }}
238
+
mailto:{{ .Author.Email }}
239
+
{{ end }}"
240
+
class="text-gray-500 dark:text-gray-400 no-underline hover:underline"
241
+
>{{ if $didOrHandle }}
242
+
{{ template "user/fragments/picHandleLink" $didOrHandle }}
243
+
{{ else }}
244
+
{{ .Author.Name }}
245
+
{{ end }}</a
246
+
>
247
+
</span>
248
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
249
+
{{ template "repo/fragments/time" .Committer.When }}
262
250
251
+
<!-- tags/branches -->
252
+
{{ $tagsForCommit := index $.TagMap .Hash.String }}
253
+
{{ if gt (len $tagsForCommit) 0 }}
254
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
255
+
{{ end }}
256
+
{{ range $tagsForCommit }}
257
+
<span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-[2px] inline-flex items-center">
258
+
{{ . }}
259
+
</span>
260
+
{{ end }}
263
261
264
-
<!-- tags/branches -->
265
-
{{ $tagsForCommit := index $.TagMap .Hash.String }}
266
-
{{ if gt (len $tagsForCommit) 0 }}
267
-
<div
268
-
class="inline-block px-1 select-none after:content-['·']"></div>
269
-
{{ end }}
270
-
{{ range $tagsForCommit }}
271
-
<span
272
-
class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-[2px] inline-flex items-center">
273
-
{{ . }}
274
-
</span>
275
-
{{ end }}
276
-
277
-
278
-
<!-- ci status -->
279
-
{{ $pipeline := index $.Pipelines .Hash.String }}
280
-
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
281
-
<div
282
-
class="inline-block px-1 select-none after:content-['·']"></div>
283
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "RepoInfo" $.RepoInfo "Pipeline" $pipeline) }}
284
-
{{ end }}
285
-
</div>
286
-
</div>
287
-
{{ end }}
262
+
<!-- ci status -->
263
+
{{ $pipeline := index $.Pipelines .Hash.String }}
264
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
265
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
266
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "RepoInfo" $.RepoInfo "Pipeline" $pipeline) }}
267
+
{{ end }}
268
+
</div>
288
269
</div>
270
+
{{ end }}
289
271
</div>
272
+
</div>
290
273
{{ end }}
291
274
292
275
{{ define "branchList" }}
293
276
{{ if gt (len .BranchesTrunc) 0 }}
294
-
<div
295
-
id="branches"
296
-
class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
297
-
<a
298
-
href="/{{ .RepoInfo.FullName }}/branches"
299
-
class="flex items-center gap-2 pb-2 cursor-pointer font-bold hover:text-gray-600 dark:hover:text-gray-300 hover:no-underline">
277
+
<div id="branches" class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
278
+
<a href="/{{ .RepoInfo.FullName }}/branches" class="flex items-center gap-2 pb-2 cursor-pointer font-bold hover:text-gray-600 dark:hover:text-gray-300 hover:no-underline">
300
279
{{ i "git-branch" "w-4 h-4" }} branches
301
-
<span
302
-
class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
303
-
{{ len .Branches }}
304
-
</span>
280
+
<span class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ len .Branches }}</span>
305
281
</a>
306
282
<div class="flex flex-col gap-1">
307
283
{{ range .BranchesTrunc }}
308
-
<div
309
-
class="text-base flex items-center justify-between overflow-hidden">
310
-
<div class="flex items-center gap-2 min-w-0 flex-1">
311
-
<a
312
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
313
-
class="inline-block truncate no-underline hover:underline dark:text-white">
314
-
{{ .Reference.Name }}
315
-
</a>
316
-
{{ if .Commit }}
317
-
<span
318
-
class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
319
-
<span
320
-
class="whitespace-nowrap text-xs text-gray-500 dark:text-gray-400 shrink-0">
321
-
{{ template "repo/fragments/time" .Commit.Committer.When }}
322
-
</span>
323
-
{{ end }}
324
-
{{ if .IsDefault }}
325
-
<span
326
-
class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
327
-
<span
328
-
class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono shrink-0">
329
-
default
330
-
</span>
331
-
{{ end }}
332
-
</div>
333
-
{{ if ne $.Ref .Reference.Name }}
334
-
<a
335
-
href="/{{ $.RepoInfo.FullName }}/compare/{{ $.Ref | urlquery }}...{{ .Reference.Name | urlquery }}"
336
-
class="text-xs flex gap-2 items-center shrink-0 ml-2"
337
-
title="Compare branches or tags">
338
-
{{ i "git-compare" "w-3 h-3" }} compare
339
-
</a>
284
+
<div class="text-base flex items-center justify-between overflow-hidden">
285
+
<div class="flex items-center gap-2 min-w-0 flex-1">
286
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
287
+
class="inline-block truncate no-underline hover:underline dark:text-white">
288
+
{{ .Reference.Name }}
289
+
</a>
290
+
{{ if .Commit }}
291
+
<span class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
292
+
<span class="whitespace-nowrap text-xs text-gray-500 dark:text-gray-400 shrink-0">{{ template "repo/fragments/time" .Commit.Committer.When }}</span>
293
+
{{ end }}
294
+
{{ if .IsDefault }}
295
+
<span class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
296
+
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono shrink-0">default</span>
340
297
{{ end }}
341
298
</div>
299
+
{{ if ne $.Ref .Reference.Name }}
300
+
<a href="/{{ $.RepoInfo.FullName }}/compare/{{ $.Ref | urlquery }}...{{ .Reference.Name | urlquery }}"
301
+
class="text-xs flex gap-2 items-center shrink-0 ml-2"
302
+
title="Compare branches or tags">
303
+
{{ i "git-compare" "w-3 h-3" }} compare
304
+
</a>
305
+
{{ end }}
306
+
</div>
342
307
{{ end }}
343
308
</div>
344
309
</div>
···
347
312
348
313
{{ define "tagList" }}
349
314
{{ if gt (len .TagsTrunc) 0 }}
350
-
<div
351
-
id="tags"
352
-
class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
315
+
<div id="tags" class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
353
316
<div class="flex justify-between items-center">
354
-
<a
355
-
href="/{{ .RepoInfo.FullName }}/tags"
356
-
class="flex items-center gap-2 pb-2 cursor-pointer font-bold hover:text-gray-600 dark:hover:text-gray-300 hover:no-underline">
317
+
<a href="/{{ .RepoInfo.FullName }}/tags" class="flex items-center gap-2 pb-2 cursor-pointer font-bold hover:text-gray-600 dark:hover:text-gray-300 hover:no-underline">
357
318
{{ i "tags" "w-4 h-4" }} tags
358
-
<span
359
-
class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
360
-
{{ len .Tags }}
361
-
</span>
319
+
<span class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ len .Tags }}</span>
362
320
</a>
363
321
</div>
364
322
<div class="flex flex-col gap-1">
365
323
{{ range $idx, $tag := .TagsTrunc }}
366
-
{{ with $tag }}
367
-
<div>
368
-
<div class="text-base flex items-center gap-2">
369
-
<a
370
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
371
-
class="inline no-underline hover:underline dark:text-white">
372
-
{{ .Reference.Name }}
373
-
</a>
374
-
</div>
375
-
<div>
376
-
{{ with .Tag }}
377
-
<span class="text-xs text-gray-500 dark:text-gray-400">
378
-
{{ template "repo/fragments/time" .Tagger.When }}
379
-
</span>
380
-
{{ end }}
381
-
{{ if eq $idx 0 }}
382
-
{{ with .Tag }}
383
-
<span
384
-
class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·']"></span>
385
-
{{ end }}
386
-
<span
387
-
class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono">
388
-
latest
389
-
</span>
390
-
{{ end }}
391
-
</div>
392
-
</div>
393
-
{{ end }}
324
+
{{ with $tag }}
325
+
<div>
326
+
<div class="text-base flex items-center gap-2">
327
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
328
+
class="inline no-underline hover:underline dark:text-white">
329
+
{{ .Reference.Name }}
330
+
</a>
331
+
</div>
332
+
<div>
333
+
{{ with .Tag }}
334
+
<span class="text-xs text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .Tagger.When }}</span>
335
+
{{ end }}
336
+
{{ if eq $idx 0 }}
337
+
{{ with .Tag }}<span class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·']"></span>{{ end }}
338
+
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono">latest</span>
339
+
{{ end }}
340
+
</div>
341
+
</div>
342
+
{{ end }}
394
343
{{ end }}
395
344
</div>
396
345
</div>
···
398
347
{{ end }}
399
348
400
349
{{ define "repoAfter" }}
401
-
{{- if or .HTMLReadme .Readme -}}
402
-
<section
403
-
class="p-6 mt-4 rounded-br rounded-bl bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm w-full mx-auto overflow-auto {{ if not .Raw }}
404
-
prose dark:prose-invert dark:[&_pre]:bg-gray-900
405
-
dark:[&_code]:text-gray-300 dark:[&_pre_code]:bg-gray-900
406
-
dark:[&_pre]:border dark:[&_pre]:border-gray-700
407
-
{{ end }}">
408
-
<article class="{{ if .Raw }}whitespace-pre{{ end }}">
409
-
{{- if .Raw -}}
410
-
<pre class="dark:bg-gray-800 dark:text-white overflow-x-auto">
350
+
{{- if or .HTMLReadme .Readme -}}
351
+
<section
352
+
class="p-6 mt-4 rounded-br rounded-bl bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm w-full mx-auto overflow-auto {{ if not .Raw }}
353
+
prose dark:prose-invert dark:[&_pre]:bg-gray-900
354
+
dark:[&_code]:text-gray-300 dark:[&_pre_code]:bg-gray-900
355
+
dark:[&_pre]:border dark:[&_pre]:border-gray-700
356
+
{{ end }}"
357
+
>
358
+
<article class="{{ if .Raw }}whitespace-pre{{ end }}">{{- if .Raw -}}<pre class="dark:bg-gray-800 dark:text-white overflow-x-auto">
411
359
{{- .Readme -}}
412
-
</pre
413
-
>
414
-
{{- else -}}
415
-
{{ .HTMLReadme }}
416
-
{{- end -}}
417
-
</article>
418
-
</section>
419
-
{{- end -}}
360
+
</pre>
361
+
{{- else -}}
362
+
{{ .HTMLReadme }}
363
+
{{- end -}}</article>
364
+
</section>
365
+
{{- end -}}
420
366
421
-
{{ template "repo/fragments/cloneInstructions" . }}
367
+
{{ template "repo/fragments/cloneInstructions" . }}
422
368
{{ end }}
+39
-44
appview/pages/templates/repo/issues/fragments/editIssueComment.html
+39
-44
appview/pages/templates/repo/issues/fragments/editIssueComment.html
···
1
1
{{ define "repo/issues/fragments/editIssueComment" }}
2
2
{{ with .Comment }}
3
-
<div id="comment-container-{{ .CommentId }}">
4
-
<div
5
-
class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
6
-
{{ $owner := didOrHandle $.LoggedInUser.Did $.LoggedInUser.Handle }}
7
-
<a href="/{{ $owner }}" class="no-underline hover:underline">
8
-
{{ $owner }}
9
-
</a>
3
+
<div id="comment-container-{{.CommentId}}">
4
+
<div class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
5
+
{{ $owner := didOrHandle $.LoggedInUser.Did $.LoggedInUser.Handle }}
6
+
<a href="/{{ $owner }}" class="no-underline hover:underline">{{ $owner }}</a>
10
7
11
-
<!-- show user "hats" -->
12
-
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
13
-
{{ if $isIssueAuthor }}
14
-
<span class="before:content-['·']"></span>
15
-
author
16
-
{{ end }}
17
-
8
+
<!-- show user "hats" -->
9
+
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
10
+
{{ if $isIssueAuthor }}
11
+
<span class="before:content-['·']"></span>
12
+
author
13
+
{{ end }}
18
14
19
-
<span class="before:content-['·']"></span>
20
-
<a
15
+
<span class="before:content-['·']"></span>
16
+
<a
21
17
href="#{{ .CommentId }}"
22
18
class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-400 hover:underline no-underline"
23
19
id="{{ .CommentId }}">
24
-
{{ template "repo/fragments/time" .Created }}
25
-
</a>
20
+
{{ template "repo/fragments/time" .Created }}
21
+
</a>
26
22
27
-
<button
28
-
class="btn px-2 py-1 flex items-center gap-2 text-sm group"
29
-
hx-post="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
30
-
hx-include="#edit-textarea-{{ .CommentId }}"
31
-
hx-target="#comment-container-{{ .CommentId }}"
32
-
hx-swap="outerHTML">
33
-
{{ i "check" "w-4 h-4" }}
34
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
35
-
</button>
36
-
<button
37
-
class="btn px-2 py-1 flex items-center gap-2 text-sm"
38
-
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
39
-
hx-target="#comment-container-{{ .CommentId }}"
40
-
hx-swap="outerHTML">
41
-
{{ i "x" "w-4 h-4" }}
42
-
</button>
43
-
<span id="comment-{{ .CommentId }}-status"></span>
44
-
</div>
23
+
<button
24
+
class="btn px-2 py-1 flex items-center gap-2 text-sm group"
25
+
hx-post="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
26
+
hx-include="#edit-textarea-{{ .CommentId }}"
27
+
hx-target="#comment-container-{{ .CommentId }}"
28
+
hx-swap="outerHTML">
29
+
{{ i "check" "w-4 h-4" }}
30
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
31
+
</button>
32
+
<button
33
+
class="btn px-2 py-1 flex items-center gap-2 text-sm"
34
+
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
35
+
hx-target="#comment-container-{{ .CommentId }}"
36
+
hx-swap="outerHTML">
37
+
{{ i "x" "w-4 h-4" }}
38
+
</button>
39
+
<span id="comment-{{.CommentId}}-status"></span>
40
+
</div>
45
41
46
-
<div>
47
-
<textarea
48
-
id="edit-textarea-{{ .CommentId }}"
49
-
name="body"
50
-
class="w-full p-2 border rounded min-h-[100px]">
51
-
{{ .Body }}</textarea
52
-
>
53
-
</div>
42
+
<div>
43
+
<textarea
44
+
id="edit-textarea-{{ .CommentId }}"
45
+
name="body"
46
+
class="w-full p-2 border rounded min-h-[100px]">{{ .Body }}</textarea>
54
47
</div>
48
+
</div>
55
49
{{ end }}
56
50
{{ end }}
51
+
+45
-48
appview/pages/templates/repo/issues/fragments/issueComment.html
+45
-48
appview/pages/templates/repo/issues/fragments/issueComment.html
···
1
1
{{ define "repo/issues/fragments/issueComment" }}
2
2
{{ with .Comment }}
3
-
<div id="comment-container-{{ .CommentId }}">
4
-
<div
5
-
class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
6
-
{{ template "user/fragments/picHandleLink" .OwnerDid }}
7
-
8
-
9
-
<!-- show user "hats" -->
10
-
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
11
-
{{ if $isIssueAuthor }}
12
-
<span class="before:content-['·']"></span>
13
-
author
14
-
{{ end }}
15
-
3
+
<div id="comment-container-{{.CommentId}}">
4
+
<div class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
5
+
{{ template "user/fragments/picHandleLink" .OwnerDid }}
16
6
7
+
<!-- show user "hats" -->
8
+
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
9
+
{{ if $isIssueAuthor }}
17
10
<span class="before:content-['·']"></span>
18
-
<a
11
+
author
12
+
{{ end }}
13
+
14
+
<span class="before:content-['·']"></span>
15
+
<a
19
16
href="#{{ .CommentId }}"
20
17
class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-400 hover:underline no-underline"
21
18
id="{{ .CommentId }}">
22
-
{{ if .Deleted }}
23
-
deleted
24
-
{{ template "repo/fragments/time" .Deleted }}
25
-
{{ else if .Edited }}
26
-
edited
27
-
{{ template "repo/fragments/time" .Edited }}
28
-
{{ else }}
29
-
{{ template "repo/fragments/time" .Created }}
30
-
{{ end }}
31
-
</a>
32
-
33
-
{{ $isCommentOwner := and $.LoggedInUser (eq $.LoggedInUser.Did .OwnerDid) }}
34
-
{{ if and $isCommentOwner (not .Deleted) }}
35
-
<button
36
-
class="btn px-2 py-1 text-sm"
37
-
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
38
-
hx-swap="outerHTML"
39
-
hx-target="#comment-container-{{ .CommentId }}">
40
-
{{ i "pencil" "w-4 h-4" }}
41
-
</button>
42
-
<button
43
-
class="btn px-2 py-1 text-sm text-red-500 flex gap-2 items-center group"
44
-
hx-delete="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
45
-
hx-confirm="Are you sure you want to delete your comment?"
46
-
hx-swap="outerHTML"
47
-
hx-target="#comment-container-{{ .CommentId }}">
48
-
{{ i "trash-2" "w-4 h-4" }}
49
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
50
-
</button>
19
+
{{ if .Deleted }}
20
+
deleted {{ template "repo/fragments/time" .Deleted }}
21
+
{{ else if .Edited }}
22
+
edited {{ template "repo/fragments/time" .Edited }}
23
+
{{ else }}
24
+
{{ template "repo/fragments/time" .Created }}
51
25
{{ end }}
26
+
</a>
52
27
53
-
</div>
54
-
{{ if not .Deleted }}
55
-
<div class="prose dark:prose-invert">
56
-
{{ .Body | markdown }}
57
-
</div>
28
+
{{ $isCommentOwner := and $.LoggedInUser (eq $.LoggedInUser.Did .OwnerDid) }}
29
+
{{ if and $isCommentOwner (not .Deleted) }}
30
+
<button
31
+
class="btn px-2 py-1 text-sm"
32
+
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
33
+
hx-swap="outerHTML"
34
+
hx-target="#comment-container-{{.CommentId}}"
35
+
>
36
+
{{ i "pencil" "w-4 h-4" }}
37
+
</button>
38
+
<button
39
+
class="btn px-2 py-1 text-sm text-red-500 flex gap-2 items-center group"
40
+
hx-delete="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
41
+
hx-confirm="Are you sure you want to delete your comment?"
42
+
hx-swap="outerHTML"
43
+
hx-target="#comment-container-{{.CommentId}}"
44
+
>
45
+
{{ i "trash-2" "w-4 h-4" }}
46
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
47
+
</button>
58
48
{{ end }}
49
+
59
50
</div>
51
+
{{ if not .Deleted }}
52
+
<div class="prose dark:prose-invert">
53
+
{{ .Body | markdown }}
54
+
</div>
55
+
{{ end }}
56
+
</div>
60
57
{{ end }}
61
58
{{ end }}
+119
-123
appview/pages/templates/repo/issues/issue.html
+119
-123
appview/pages/templates/repo/issues/issue.html
···
1
-
{{ define "title" }}
2
-
{{ .Issue.Title }} · issue #{{ .Issue.IssueId }} ·
3
-
{{ .RepoInfo.FullName }}
4
-
{{ end }}
1
+
{{ define "title" }}{{ .Issue.Title }} · issue #{{ .Issue.IssueId }} · {{ .RepoInfo.FullName }}{{ end }}
2
+
5
3
6
4
{{ define "extrameta" }}
7
-
{{ $title := printf "%s · issue #%d · %s" .Issue.Title .Issue.IssueId .RepoInfo.FullName }}
8
-
{{ $url := printf "https://tangled.sh/%s/issues/%d" .RepoInfo.FullName .Issue.IssueId }}
5
+
{{ $title := printf "%s · issue #%d · %s" .Issue.Title .Issue.IssueId .RepoInfo.FullName }}
6
+
{{ $url := printf "https://tangled.sh/%s/issues/%d" .RepoInfo.FullName .Issue.IssueId }}
9
7
10
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
8
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
11
9
{{ end }}
12
10
13
11
{{ define "repoContent" }}
14
-
<header class="pb-4">
15
-
<h1 class="text-2xl">
12
+
<header class="pb-4">
13
+
<h1 class="text-2xl">
16
14
{{ .Issue.Title }}
17
-
<span class="text-gray-500 dark:text-gray-400">
18
-
#{{ .Issue.IssueId }}
19
-
</span>
20
-
</h1>
21
-
</header>
15
+
<span class="text-gray-500 dark:text-gray-400">#{{ .Issue.IssueId }}</span>
16
+
</h1>
17
+
</header>
22
18
23
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
24
-
{{ $icon := "ban" }}
25
-
{{ if eq .State "open" }}
26
-
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
27
-
{{ $icon = "circle-dot" }}
28
-
{{ end }}
19
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
20
+
{{ $icon := "ban" }}
21
+
{{ if eq .State "open" }}
22
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
23
+
{{ $icon = "circle-dot" }}
24
+
{{ end }}
29
25
26
+
<section class="mt-2">
27
+
<div class="inline-flex items-center gap-2">
28
+
<div id="state"
29
+
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
30
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
31
+
<span class="text-white">{{ .State }}</span>
32
+
</div>
33
+
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
34
+
opened by
35
+
{{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }}
36
+
{{ template "user/fragments/picHandleLink" $owner }}
37
+
<span class="select-none before:content-['\00B7']"></span>
38
+
{{ template "repo/fragments/time" .Issue.Created }}
39
+
</span>
40
+
</div>
30
41
31
-
<section class="mt-2">
32
-
<div class="inline-flex items-center gap-2">
33
-
<div
34
-
id="state"
35
-
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
36
-
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
37
-
<span class="text-white">{{ .State }}</span>
38
-
</div>
39
-
<span
40
-
class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
41
-
opened by
42
-
{{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }}
43
-
{{ template "user/fragments/picHandleLink" $owner }}
44
-
<span class="select-none before:content-['\00B7']"></span>
45
-
{{ template "repo/fragments/time" .Issue.Created }}
46
-
</span>
47
-
</div>
42
+
{{ if .Issue.Body }}
43
+
<article id="body" class="mt-8 prose dark:prose-invert">
44
+
{{ .Issue.Body | markdown }}
45
+
</article>
46
+
{{ end }}
48
47
49
-
{{ if .Issue.Body }}
50
-
<article id="body" class="mt-8 prose dark:prose-invert">
51
-
{{ .Issue.Body | markdown }}
52
-
</article>
53
-
{{ end }}
54
-
55
-
56
-
<div class="flex items-center gap-2 mt-2">
57
-
{{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }}
58
-
{{ range $kind := .OrderedReactionKinds }}
59
-
{{ template "repo/fragments/reaction"
60
-
(dict
61
-
"Kind" $kind
62
-
"Count" (index $.Reactions $kind)
63
-
"IsReacted" (index $.UserReacted $kind)
64
-
"ThreadAt" $.Issue.IssueAt)
65
-
}}
66
-
{{ end }}
67
-
</div>
68
-
</section>
48
+
<div class="flex items-center gap-2 mt-2">
49
+
{{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }}
50
+
{{ range $kind := .OrderedReactionKinds }}
51
+
{{
52
+
template "repo/fragments/reaction"
53
+
(dict
54
+
"Kind" $kind
55
+
"Count" (index $.Reactions $kind)
56
+
"IsReacted" (index $.UserReacted $kind)
57
+
"ThreadAt" $.Issue.IssueAt)
58
+
}}
59
+
{{ end }}
60
+
</div>
61
+
</section>
69
62
{{ end }}
70
63
71
64
{{ define "repoAfter" }}
72
-
<section id="comments" class="my-2 mt-2 space-y-2 relative">
73
-
{{ range $index, $comment := .Comments }}
74
-
<div
75
-
id="comment-{{ .CommentId }}"
76
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-2 px-4 relative w-full md:max-w-3/5 md:w-fit">
77
-
{{ if gt $index 0 }}
78
-
<div
79
-
class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
65
+
<section id="comments" class="my-2 mt-2 space-y-2 relative">
66
+
{{ range $index, $comment := .Comments }}
67
+
<div
68
+
id="comment-{{ .CommentId }}"
69
+
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-2 px-4 relative w-full md:max-w-3/5 md:w-fit">
70
+
{{ if gt $index 0 }}
71
+
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
72
+
{{ end }}
73
+
{{ template "repo/issues/fragments/issueComment" (dict "RepoInfo" $.RepoInfo "LoggedInUser" $.LoggedInUser "Issue" $.Issue "Comment" .)}}
74
+
</div>
80
75
{{ end }}
81
-
{{ template "repo/issues/fragments/issueComment" (dict "RepoInfo" $.RepoInfo "LoggedInUser" $.LoggedInUser "Issue" $.Issue "Comment" .) }}
82
-
</div>
83
-
{{ end }}
84
-
</section>
76
+
</section>
85
77
86
-
{{ block "newComment" . }}{{ end }}
78
+
{{ block "newComment" . }} {{ end }}
87
79
88
80
{{ end }}
89
81
90
82
{{ define "newComment" }}
91
83
{{ if .LoggedInUser }}
92
-
<form
84
+
<form
93
85
id="comment-form"
94
86
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
95
-
hx-on::after-request="if(event.detail.successful) this.reset()">
96
-
<div
97
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full md:w-3/5">
98
-
<div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
99
-
{{ template "user/fragments/picHandleLink" (didOrHandle .LoggedInUser.Did .LoggedInUser.Handle) }}
100
-
</div>
101
-
<textarea
102
-
id="comment-textarea"
103
-
name="body"
104
-
class="w-full p-2 rounded border border-gray-200 dark:border-gray-700"
105
-
placeholder="Add to the discussion. Markdown is supported."
106
-
onkeyup="updateCommentForm()"></textarea>
107
-
<div id="issue-comment"></div>
108
-
<div id="issue-action" class="error"></div>
87
+
hx-on::after-request="if(event.detail.successful) this.reset()"
88
+
>
89
+
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full md:w-3/5">
90
+
<div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
91
+
{{ template "user/fragments/picHandleLink" (didOrHandle .LoggedInUser.Did .LoggedInUser.Handle) }}
109
92
</div>
93
+
<textarea
94
+
id="comment-textarea"
95
+
name="body"
96
+
class="w-full p-2 rounded border border-gray-200 dark:border-gray-700"
97
+
placeholder="Add to the discussion. Markdown is supported."
98
+
onkeyup="updateCommentForm()"
99
+
></textarea>
100
+
<div id="issue-comment"></div>
101
+
<div id="issue-action" class="error"></div>
102
+
</div>
110
103
111
-
<div class="flex gap-2 mt-2">
104
+
<div class="flex gap-2 mt-2">
112
105
<button
113
-
id="comment-button"
114
-
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
115
-
type="submit"
116
-
hx-disabled-elt="#comment-button"
117
-
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group"
118
-
disabled>
119
-
{{ i "message-square-plus" "w-4 h-4" }}
120
-
comment
121
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
106
+
id="comment-button"
107
+
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
108
+
type="submit"
109
+
hx-disabled-elt="#comment-button"
110
+
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group"
111
+
disabled
112
+
>
113
+
{{ i "message-square-plus" "w-4 h-4" }}
114
+
comment
115
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
122
116
</button>
123
117
124
118
{{ $isIssueAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Issue.OwnerDid) }}
125
119
{{ $isRepoCollaborator := .RepoInfo.Roles.IsCollaborator }}
126
120
{{ $isRepoOwner := .RepoInfo.Roles.IsOwner }}
127
121
{{ if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "open") }}
128
-
<button
122
+
<button
129
123
id="close-button"
130
124
type="button"
131
125
class="btn flex items-center gap-2"
132
126
hx-indicator="#close-spinner"
133
-
hx-trigger="click">
127
+
hx-trigger="click"
128
+
>
134
129
{{ i "ban" "w-4 h-4" }}
135
130
close
136
131
<span id="close-spinner" class="group">
137
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
132
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
138
133
</span>
139
-
</button>
140
-
<div
134
+
</button>
135
+
<div
141
136
id="close-with-comment"
142
137
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
143
138
hx-trigger="click from:#close-button"
···
145
140
hx-target="#issue-comment"
146
141
hx-indicator="#close-spinner"
147
142
hx-vals="js:{body: document.getElementById('comment-textarea').value.trim() !== '' ? document.getElementById('comment-textarea').value : ''}"
148
-
hx-swap="none"></div>
149
-
<div
143
+
hx-swap="none"
144
+
>
145
+
</div>
146
+
<div
150
147
id="close-issue"
151
148
hx-disabled-elt="#close-issue"
152
149
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/close"
153
150
hx-trigger="click from:#close-button"
154
151
hx-target="#issue-action"
155
152
hx-indicator="#close-spinner"
156
-
hx-swap="none"></div>
157
-
<script>
158
-
document.addEventListener("htmx:configRequest", function (evt) {
159
-
if (evt.target.id === "close-with-comment") {
160
-
const commentText = document
161
-
.getElementById("comment-textarea")
162
-
.value.trim();
163
-
if (commentText === "") {
164
-
evt.detail.parameters = {};
165
-
evt.preventDefault();
153
+
hx-swap="none"
154
+
>
155
+
</div>
156
+
<script>
157
+
document.addEventListener('htmx:configRequest', function(evt) {
158
+
if (evt.target.id === 'close-with-comment') {
159
+
const commentText = document.getElementById('comment-textarea').value.trim();
160
+
if (commentText === '') {
161
+
evt.detail.parameters = {};
162
+
evt.preventDefault();
163
+
}
166
164
}
167
-
}
168
165
});
169
-
</script>
166
+
</script>
170
167
{{ else if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "closed") }}
171
-
<button
168
+
<button
172
169
type="button"
173
170
class="btn flex items-center gap-2"
174
171
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/reopen"
175
172
hx-indicator="#reopen-spinner"
176
-
hx-swap="none">
173
+
hx-swap="none"
174
+
>
177
175
{{ i "refresh-ccw-dot" "w-4 h-4" }}
178
176
reopen
179
177
<span id="reopen-spinner" class="group">
180
178
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
181
179
</span>
182
-
</button>
180
+
</button>
183
181
{{ end }}
184
182
185
183
<script>
···
217
215
updateCommentForm();
218
216
});
219
217
</script>
220
-
</div>
221
-
</form>
218
+
</div>
219
+
</form>
222
220
{{ else }}
223
-
<div
224
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-fit">
225
-
<a href="/login" class="underline">login</a>
226
-
to join the discussion
221
+
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-fit">
222
+
<a href="/login" class="underline">login</a> to join the discussion
227
223
</div>
228
224
{{ end }}
229
225
{{ end }}
+83
-94
appview/pages/templates/repo/issues/issues.html
+83
-94
appview/pages/templates/repo/issues/issues.html
···
1
1
{{ define "title" }}issues · {{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
{{ $title := "issues" }}
5
-
{{ $url := printf "https://tangled.sh/%s/issues" .RepoInfo.FullName }}
4
+
{{ $title := "issues"}}
5
+
{{ $url := printf "https://tangled.sh/%s/issues" .RepoInfo.FullName }}
6
6
7
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
7
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
8
8
{{ end }}
9
9
10
10
{{ define "repoContent" }}
11
-
<div class="flex justify-between items-center gap-4">
12
-
<div class="flex gap-4">
13
-
<a
11
+
<div class="flex justify-between items-center gap-4">
12
+
<div class="flex gap-4">
13
+
<a
14
14
href="?state=open"
15
-
class="flex items-center gap-2 {{ if .FilteringByOpen }}
16
-
font-bold
17
-
{{ else }}
18
-
text-gray-500 dark:text-gray-400
19
-
{{ end }}">
15
+
class="flex items-center gap-2 {{ if .FilteringByOpen }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
16
+
>
20
17
{{ i "circle-dot" "w-4 h-4" }}
21
18
<span>{{ .RepoInfo.Stats.IssueCount.Open }} open</span>
22
-
</a>
23
-
<a
19
+
</a>
20
+
<a
24
21
href="?state=closed"
25
-
class="flex items-center gap-2 {{ if not .FilteringByOpen }}
26
-
font-bold
27
-
{{ else }}
28
-
text-gray-500 dark:text-gray-400
29
-
{{ end }}">
22
+
class="flex items-center gap-2 {{ if not .FilteringByOpen }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
23
+
>
30
24
{{ i "ban" "w-4 h-4" }}
31
25
<span>{{ .RepoInfo.Stats.IssueCount.Closed }} closed</span>
32
-
</a>
33
-
</div>
34
-
<a
26
+
</a>
27
+
</div>
28
+
<a
35
29
href="/{{ .RepoInfo.FullName }}/issues/new"
36
-
class="btn-create text-sm flex items-center justify-center gap-2 no-underline hover:no-underline hover:text-white">
30
+
class="btn-create text-sm flex items-center justify-center gap-2 no-underline hover:no-underline hover:text-white"
31
+
>
37
32
{{ i "circle-plus" "w-4 h-4" }}
38
33
<span>new</span>
39
-
</a>
40
-
</div>
41
-
<div class="error" id="issues"></div>
34
+
</a>
35
+
</div>
36
+
<div class="error" id="issues"></div>
42
37
{{ end }}
43
38
44
39
{{ define "repoAfter" }}
45
-
<div class="flex flex-col gap-2 mt-2">
46
-
{{ range .Issues }}
47
-
<div
48
-
class="rounded drop-shadow-sm bg-white px-6 py-4 dark:bg-gray-800 dark:border-gray-700">
49
-
<div class="pb-2">
50
-
<a
51
-
href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}"
52
-
class="no-underline hover:underline">
53
-
{{ .Title }}
54
-
<span class="text-gray-500">#{{ .IssueId }}</span>
55
-
</a>
56
-
</div>
57
-
<p
58
-
class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
59
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
60
-
{{ $icon := "ban" }}
61
-
{{ $state := "closed" }}
62
-
{{ if .Open }}
63
-
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
64
-
{{ $icon = "circle-dot" }}
65
-
{{ $state = "open" }}
66
-
{{ end }}
40
+
<div class="flex flex-col gap-2 mt-2">
41
+
{{ range .Issues }}
42
+
<div class="rounded drop-shadow-sm bg-white px-6 py-4 dark:bg-gray-800 dark:border-gray-700">
43
+
<div class="pb-2">
44
+
<a
45
+
href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}"
46
+
class="no-underline hover:underline"
47
+
>
48
+
{{ .Title }}
49
+
<span class="text-gray-500">#{{ .IssueId }}</span>
50
+
</a>
51
+
</div>
52
+
<p class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
53
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
54
+
{{ $icon := "ban" }}
55
+
{{ $state := "closed" }}
56
+
{{ if .Open }}
57
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
58
+
{{ $icon = "circle-dot" }}
59
+
{{ $state = "open" }}
60
+
{{ end }}
67
61
62
+
<span class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
63
+
{{ i $icon "w-3 h-3 mr-1.5 text-white dark:text-white" }}
64
+
<span class="text-white dark:text-white">{{ $state }}</span>
65
+
</span>
68
66
69
-
<span
70
-
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
71
-
{{ i $icon "w-3 h-3 mr-1.5 text-white dark:text-white" }}
72
-
<span class="text-white dark:text-white">{{ $state }}</span>
73
-
</span>
74
-
75
-
<span class="ml-1">
76
-
{{ template "user/fragments/picHandleLink" .OwnerDid }}
77
-
</span>
67
+
<span class="ml-1">
68
+
{{ template "user/fragments/picHandleLink" .OwnerDid }}
69
+
</span>
78
70
79
-
<span class="before:content-['·']">
80
-
{{ template "repo/fragments/time" .Created }}
81
-
</span>
71
+
<span class="before:content-['·']">
72
+
{{ template "repo/fragments/time" .Created }}
73
+
</span>
82
74
83
-
<span class="before:content-['·']">
84
-
{{ $s := "s" }}
85
-
{{ if eq .Metadata.CommentCount 1 }}
86
-
{{ $s = "" }}
87
-
{{ end }}
88
-
<a
89
-
href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}"
90
-
class="text-gray-500 dark:text-gray-400">
91
-
{{ .Metadata.CommentCount }}
92
-
comment{{ $s }}
93
-
</a>
94
-
</span>
95
-
</p>
96
-
</div>
97
-
{{ end }}
75
+
<span class="before:content-['·']">
76
+
{{ $s := "s" }}
77
+
{{ if eq .Metadata.CommentCount 1 }}
78
+
{{ $s = "" }}
79
+
{{ end }}
80
+
<a href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}" class="text-gray-500 dark:text-gray-400">{{ .Metadata.CommentCount }} comment{{$s}}</a>
81
+
</span>
82
+
</p>
98
83
</div>
84
+
{{ end }}
85
+
</div>
99
86
100
-
{{ block "pagination" . }}{{ end }}
87
+
{{ block "pagination" . }} {{ end }}
101
88
102
89
{{ end }}
103
90
104
91
{{ define "pagination" }}
105
-
<div class="flex justify-end mt-4 gap-2">
92
+
<div class="flex justify-end mt-4 gap-2">
106
93
{{ $currentState := "closed" }}
107
94
{{ if .FilteringByOpen }}
108
95
{{ $currentState = "open" }}
109
96
{{ end }}
110
97
111
98
{{ if gt .Page.Offset 0 }}
112
-
{{ $prev := .Page.Previous }}
113
-
<a
114
-
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
115
-
hx-boost="true"
116
-
href="/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $prev.Offset }}&limit={{ $prev.Limit }}">
117
-
{{ i "chevron-left" "w-4 h-4" }}
118
-
previous
119
-
</a>
99
+
{{ $prev := .Page.Previous }}
100
+
<a
101
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
102
+
hx-boost="true"
103
+
href = "/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $prev.Offset }}&limit={{ $prev.Limit }}"
104
+
>
105
+
{{ i "chevron-left" "w-4 h-4" }}
106
+
previous
107
+
</a>
120
108
{{ else }}
121
-
<div></div>
109
+
<div></div>
122
110
{{ end }}
123
111
124
112
{{ if eq (len .Issues) .Page.Limit }}
125
-
{{ $next := .Page.Next }}
126
-
<a
127
-
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
128
-
hx-boost="true"
129
-
href="/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $next.Offset }}&limit={{ $next.Limit }}">
130
-
next
131
-
{{ i "chevron-right" "w-4 h-4" }}
132
-
</a>
113
+
{{ $next := .Page.Next }}
114
+
<a
115
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
116
+
hx-boost="true"
117
+
href = "/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $next.Offset }}&limit={{ $next.Limit }}"
118
+
>
119
+
next
120
+
{{ i "chevron-right" "w-4 h-4" }}
121
+
</a>
133
122
{{ end }}
134
-
</div>
123
+
</div>
135
124
{{ end }}
+33
-31
appview/pages/templates/repo/issues/new.html
+33
-31
appview/pages/templates/repo/issues/new.html
···
1
1
{{ define "title" }}new issue · {{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "repoContent" }}
4
-
<form
5
-
hx-post="/{{ .RepoInfo.FullName }}/issues/new"
6
-
class="mt-6 space-y-6"
7
-
hx-swap="none"
8
-
hx-indicator="#spinner">
9
-
<div class="flex flex-col gap-4">
10
-
<div>
11
-
<label for="title">title</label>
12
-
<input type="text" name="title" id="title" class="w-full" />
13
-
</div>
14
-
<div>
15
-
<label for="body">body</label>
16
-
<textarea
17
-
name="body"
18
-
id="body"
19
-
rows="6"
20
-
class="w-full resize-y"
21
-
placeholder="Describe your issue. Markdown is supported."></textarea>
22
-
</div>
23
-
<div>
24
-
<button type="submit" class="btn-create flex items-center gap-2">
25
-
{{ i "circle-plus" "w-4 h-4" }}
26
-
create issue
27
-
<span id="create-pull-spinner" class="group">
28
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
29
-
</span>
30
-
</button>
31
-
</div>
32
-
</div>
33
-
<div id="issues" class="error"></div>
34
-
</form>
4
+
<form
5
+
hx-post="/{{ .RepoInfo.FullName }}/issues/new"
6
+
class="mt-6 space-y-6"
7
+
hx-swap="none"
8
+
hx-indicator="#spinner"
9
+
>
10
+
<div class="flex flex-col gap-4">
11
+
<div>
12
+
<label for="title">title</label>
13
+
<input type="text" name="title" id="title" class="w-full" />
14
+
</div>
15
+
<div>
16
+
<label for="body">body</label>
17
+
<textarea
18
+
name="body"
19
+
id="body"
20
+
rows="6"
21
+
class="w-full resize-y"
22
+
placeholder="Describe your issue. Markdown is supported."
23
+
></textarea>
24
+
</div>
25
+
<div>
26
+
<button type="submit" class="btn-create flex items-center gap-2">
27
+
{{ i "circle-plus" "w-4 h-4" }}
28
+
create issue
29
+
<span id="create-pull-spinner" class="group">
30
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
31
+
</span>
32
+
</button>
33
+
</div>
34
+
</div>
35
+
<div id="issues" class="error"></div>
36
+
</form>
35
37
{{ end }}
+135
-208
appview/pages/templates/repo/log.html
+135
-208
appview/pages/templates/repo/log.html
···
1
1
{{ define "title" }}commits · {{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
{{ $title := printf "commits · %s" .RepoInfo.FullName }}
5
-
{{ $url := printf "https://tangled.sh/%s/commits" .RepoInfo.FullName }}
4
+
{{ $title := printf "commits · %s" .RepoInfo.FullName }}
5
+
{{ $url := printf "https://tangled.sh/%s/commits" .RepoInfo.FullName }}
6
6
7
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
7
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
8
8
{{ end }}
9
9
10
10
{{ define "repoContent" }}
11
-
<section id="commit-table" class="overflow-x-auto">
12
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">commits</h2>
11
+
<section id="commit-table" class="overflow-x-auto">
12
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
13
+
commits
14
+
</h2>
13
15
14
16
<!-- desktop view (hidden on small screens) -->
15
-
<div
16
-
class="hidden md:flex md:flex-col divide-y divide-gray-200 dark:divide-gray-700">
17
+
<div class="hidden md:flex md:flex-col divide-y divide-gray-200 dark:divide-gray-700">
17
18
{{ $grid := "grid grid-cols-14 gap-4" }}
18
19
<div class="{{ $grid }}">
19
-
<div
20
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-2">
21
-
Author
22
-
</div>
23
-
<div
24
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-3">
25
-
Commit
26
-
</div>
27
-
<div
28
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-6">
29
-
Message
30
-
</div>
31
-
<div
32
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-1"></div>
33
-
<div
34
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-2 justify-self-end">
35
-
Date
36
-
</div>
20
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-2">Author</div>
21
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-3">Commit</div>
22
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-6">Message</div>
23
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-1"></div>
24
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-2 justify-self-end">Date</div>
37
25
</div>
38
26
{{ range $index, $commit := .Commits }}
39
27
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
40
28
<div class="{{ $grid }} py-3">
41
29
<div class="align-top truncate col-span-2">
42
-
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
43
-
{{ if $didOrHandle }}
44
-
{{ template "user/fragments/picHandleLink" $didOrHandle }}
45
-
{{ else }}
46
-
<a
47
-
href="mailto:{{ $commit.Author.Email }}"
48
-
class="text-gray-700 dark:text-gray-300 no-underline hover:underline">
49
-
{{ $commit.Author.Name }}
50
-
</a>
51
-
{{ end }}
30
+
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
31
+
{{ if $didOrHandle }}
32
+
{{ template "user/fragments/picHandleLink" $didOrHandle }}
33
+
{{ else }}
34
+
<a href="mailto:{{ $commit.Author.Email }}" class="text-gray-700 dark:text-gray-300 no-underline hover:underline">{{ $commit.Author.Name }}</a>
35
+
{{ end }}
52
36
</div>
53
37
<div class="align-top font-mono flex items-start col-span-3">
54
-
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
55
-
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
56
-
{{ if $verified }}
57
-
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
58
-
{{ end }}
59
-
<a
60
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
61
-
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1/2 rounded flex items-center gap-2">
62
-
{{ slice $commit.Hash.String 0 8 }}
38
+
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
39
+
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
63
40
{{ if $verified }}
64
-
{{ i "shield-check" "w-4 h-4" }}
41
+
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
65
42
{{ end }}
66
-
</a>
67
-
<div class="{{ if not $verified }}ml-6{{ end }}inline-flex">
68
-
<button
69
-
class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
70
-
title="Copy SHA"
71
-
onclick="navigator.clipboard.writeText('{{ $commit.Hash.String }}'); this.innerHTML=`{{ i "copy-check" "w-4 h-4" }}`; setTimeout(() => this.innerHTML=`{{ i "copy" "w-4 h-4" }}`, 1500)">
72
-
{{ i "copy" "w-4 h-4" }}
73
-
</button>
74
-
<a
75
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
76
-
class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
77
-
title="Browse repository at this commit">
78
-
{{ i "folder-code" "w-4 h-4" }}
43
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}" class="no-underline hover:underline {{ $hashStyle }} px-2 py-1/2 rounded flex items-center gap-2">
44
+
{{ slice $commit.Hash.String 0 8 }}
45
+
{{ if $verified }}
46
+
{{ i "shield-check" "w-4 h-4" }}
47
+
{{ end }}
79
48
</a>
80
-
</div>
49
+
<div class="{{ if not $verified }} ml-6 {{ end }}inline-flex">
50
+
<button class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
51
+
title="Copy SHA"
52
+
onclick="navigator.clipboard.writeText('{{ $commit.Hash.String }}'); this.innerHTML=`{{ i "copy-check" "w-4 h-4" }}`; setTimeout(() => this.innerHTML=`{{ i "copy" "w-4 h-4" }}`, 1500)">
53
+
{{ i "copy" "w-4 h-4" }}
54
+
</button>
55
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}" class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" title="Browse repository at this commit">
56
+
{{ i "folder-code" "w-4 h-4" }}
57
+
</a>
58
+
</div>
59
+
81
60
</div>
82
61
<div class="align-top col-span-6">
83
62
<div>
84
-
<a
85
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
86
-
class="dark:text-white no-underline hover:underline">
87
-
{{ index $messageParts 0 }}
88
-
</a>
89
-
{{ if gt (len $messageParts) 1 }}
90
-
<button
91
-
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 rounded"
92
-
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
93
-
{{ i "ellipsis" "w-3 h-3" }}
94
-
</button>
95
-
{{ end }}
63
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}" class="dark:text-white no-underline hover:underline">{{ index $messageParts 0 }}</a>
64
+
{{ if gt (len $messageParts) 1 }}
65
+
<button class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 rounded" hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">{{ i "ellipsis" "w-3 h-3" }}</button>
66
+
{{ end }}
96
67
97
-
{{ if index $.TagMap $commit.Hash.String }}
98
-
{{ range $tag := index $.TagMap $commit.Hash.String }}
99
-
<span
100
-
class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
101
-
{{ $tag }}
102
-
</span>
68
+
{{ if index $.TagMap $commit.Hash.String }}
69
+
{{ range $tag := index $.TagMap $commit.Hash.String }}
70
+
<span class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
71
+
{{ $tag }}
72
+
</span>
73
+
{{ end }}
103
74
{{ end }}
104
-
{{ end }}
105
75
</div>
106
76
107
77
{{ if gt (len $messageParts) 1 }}
108
-
<p class="hidden mt-1 text-sm text-gray-600 dark:text-gray-400">
109
-
{{ nl2br (index $messageParts 1) }}
110
-
</p>
78
+
<p class="hidden mt-1 text-sm text-gray-600 dark:text-gray-400">{{ nl2br (index $messageParts 1) }}</p>
111
79
{{ end }}
112
80
</div>
113
81
<div class="align-top col-span-1">
114
-
<!-- ci status -->
115
-
{{ $pipeline := index $.Pipelines .Hash.String }}
116
-
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
117
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
118
-
{{ end }}
119
-
</div>
120
-
<div
121
-
class="align-top justify-self-end text-gray-500 dark:text-gray-400 col-span-2">
122
-
{{ template "repo/fragments/shortTimeAgo" $commit.Committer.When }}
82
+
<!-- ci status -->
83
+
{{ $pipeline := index $.Pipelines .Hash.String }}
84
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
85
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
86
+
{{ end }}
123
87
</div>
88
+
<div class="align-top justify-self-end text-gray-500 dark:text-gray-400 col-span-2">{{ template "repo/fragments/shortTimeAgo" $commit.Committer.When }}</div>
124
89
</div>
125
90
{{ end }}
126
91
</div>
127
92
128
93
<!-- mobile view (visible only on small screens) -->
129
94
<div class="md:hidden">
130
-
{{ range $index, $commit := .Commits }}
131
-
<div
132
-
class="relative p-2 mb-2 {{ if ne $index (sub (len $.Commits) 1) }}
133
-
border-b border-gray-200 dark:border-gray-700
134
-
{{ end }}">
135
-
<div id="commit-message">
136
-
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
137
-
<div class="text-base cursor-pointer">
138
-
<div class="flex items-center justify-between">
139
-
<div class="flex-1">
140
-
<div>
141
-
<a
142
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
143
-
class="inline no-underline hover:underline dark:text-white">
144
-
{{ index $messageParts 0 }}
145
-
</a>
146
-
{{ if gt (len $messageParts) 1 }}
147
-
<button
148
-
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
149
-
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
150
-
{{ i "ellipsis" "w-3 h-3" }}
151
-
</button>
152
-
{{ end }}
95
+
{{ range $index, $commit := .Commits }}
96
+
<div class="relative p-2 mb-2 {{ if ne $index (sub (len $.Commits) 1) }}border-b border-gray-200 dark:border-gray-700{{ end }}">
97
+
<div id="commit-message">
98
+
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
99
+
<div class="text-base cursor-pointer">
100
+
<div class="flex items-center justify-between">
101
+
<div class="flex-1">
102
+
<div>
103
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
104
+
class="inline no-underline hover:underline dark:text-white">
105
+
{{ index $messageParts 0 }}
106
+
</a>
107
+
{{ if gt (len $messageParts) 1 }}
108
+
<button
109
+
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
110
+
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
111
+
{{ i "ellipsis" "w-3 h-3" }}
112
+
</button>
113
+
{{ end }}
114
+
115
+
{{ if index $.TagMap $commit.Hash.String }}
116
+
{{ range $tag := index $.TagMap $commit.Hash.String }}
117
+
<span class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
118
+
{{ $tag }}
119
+
</span>
120
+
{{ end }}
121
+
{{ end }}
122
+
</div>
153
123
154
-
{{ if index $.TagMap $commit.Hash.String }}
155
-
{{ range $tag := index $.TagMap $commit.Hash.String }}
156
-
<span
157
-
class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
158
-
{{ $tag }}
159
-
</span>
160
-
{{ end }}
124
+
{{ if gt (len $messageParts) 1 }}
125
+
<p class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
126
+
{{ nl2br (index $messageParts 1) }}
127
+
</p>
128
+
{{ end }}
129
+
</div>
130
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
131
+
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
132
+
title="Browse repository at this commit">
133
+
{{ i "folder-code" "w-4 h-4" }}
134
+
</a>
135
+
</div>
136
+
</div>
137
+
</div>
138
+
139
+
<div class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center">
140
+
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
141
+
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
142
+
{{ if $verified }}
143
+
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
161
144
{{ end }}
162
-
</div>
145
+
<span class="font-mono">
146
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
147
+
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
148
+
{{ slice $commit.Hash.String 0 8 }}
149
+
{{ if $verified }}
150
+
{{ i "shield-check" "w-3 h-3" }}
151
+
{{ end }}
152
+
</a>
153
+
</span>
154
+
<span class="mx-2 before:content-['·'] before:select-none"></span>
155
+
<span>
156
+
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
157
+
<a href="{{ if $didOrHandle }}/{{ $didOrHandle }}{{ else }}mailto:{{ $commit.Author.Email }}{{ end }}"
158
+
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
159
+
{{ if $didOrHandle }}{{ template "user/fragments/picHandleLink" $didOrHandle }}{{ else }}{{ $commit.Author.Name }}{{ end }}
160
+
</a>
161
+
</span>
162
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
163
+
<span>{{ template "repo/fragments/shortTime" $commit.Committer.When }}</span>
163
164
164
-
{{ if gt (len $messageParts) 1 }}
165
-
<p
166
-
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
167
-
{{ nl2br (index $messageParts 1) }}
168
-
</p>
169
-
{{ end }}
165
+
<!-- ci status -->
166
+
{{ $pipeline := index $.Pipelines .Hash.String }}
167
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
168
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
169
+
<span class="text-sm">
170
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
171
+
</span>
172
+
{{ end }}
170
173
</div>
171
-
<a
172
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
173
-
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
174
-
title="Browse repository at this commit">
175
-
{{ i "folder-code" "w-4 h-4" }}
176
-
</a>
177
-
</div>
178
174
</div>
179
-
</div>
175
+
{{ end }}
176
+
</div>
177
+
</section>
180
178
181
-
<div
182
-
class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center">
183
-
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
184
-
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
185
-
{{ if $verified }}
186
-
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
187
-
{{ end }}
188
-
<span class="font-mono">
189
-
<a
190
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
191
-
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
192
-
{{ slice $commit.Hash.String 0 8 }}
193
-
{{ if $verified }}
194
-
{{ i "shield-check" "w-3 h-3" }}
195
-
{{ end }}
196
-
</a>
197
-
</span>
198
-
<span class="mx-2 before:content-['·'] before:select-none"></span>
199
-
<span>
200
-
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
201
-
<a
202
-
href="{{ if $didOrHandle }}
203
-
/{{ $didOrHandle }}
204
-
{{ else }}
205
-
mailto:{{ $commit.Author.Email }}
206
-
{{ end }}"
207
-
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
208
-
{{ if $didOrHandle }}
209
-
{{ template "user/fragments/picHandleLink" $didOrHandle }}
210
-
{{ else }}
211
-
{{ $commit.Author.Name }}
212
-
{{ end }}
213
-
</a>
214
-
</span>
215
-
<div
216
-
class="inline-block px-1 select-none after:content-['·']"></div>
217
-
<span>
218
-
{{ template "repo/fragments/shortTime" $commit.Committer.When }}
219
-
</span>
220
-
221
-
<!-- ci status -->
222
-
{{ $pipeline := index $.Pipelines .Hash.String }}
223
-
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
224
-
<div
225
-
class="inline-block px-1 select-none after:content-['·']"></div>
226
-
<span class="text-sm">
227
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
228
-
</span>
229
-
{{ end }}
230
-
</div>
231
-
</div>
232
-
{{ end }}
233
-
</div>
234
-
</section>
235
179
{{ end }}
236
180
237
181
{{ define "repoAfter" }}
238
182
{{ $commits_len := len .Commits }}
239
183
<div class="flex justify-end mt-4 gap-2">
240
-
{{ if gt .Page 1 }}
241
-
<a
242
-
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
243
-
hx-boost="true"
244
-
onclick="window.location.href = window.location.pathname + '?page={{ sub .Page 1 }}'">
245
-
{{ i "chevron-left" "w-4 h-4" }} previous
246
-
</a>
247
-
{{ else }}
248
-
<div></div>
249
-
{{ end }}
250
-
{{ if eq $commits_len 60 }}
251
-
<a
252
-
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
253
-
hx-boost="true"
254
-
onclick="window.location.href = window.location.pathname + '?page={{ add .Page 1 }}'">
255
-
next
256
-
{{ i "chevron-right" "w-4 h-4" }}
257
-
</a>
258
-
{{ end }}
184
+
{{ if gt .Page 1 }}<a class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700" hx-boost="true" onclick="window.location.href = window.location.pathname + '?page={{ sub .Page 1 }}'">{{ i "chevron-left" "w-4 h-4" }} previous</a>{{ else }}<div></div>{{ end }}
185
+
{{ if eq $commits_len 60 }}<a class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700" hx-boost="true" onclick="window.location.href = window.location.pathname + '?page={{ add .Page 1 }}'">next {{ i "chevron-right" "w-4 h-4" }}</a>{{ end }}
259
186
</div>
260
187
{{ end }}
+49
-56
appview/pages/templates/repo/new.html
+49
-56
appview/pages/templates/repo/new.html
···
1
1
{{ define "title" }}new repo{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<div class="p-6">
5
-
<p class="text-xl font-bold dark:text-white">Create a new repository</p>
6
-
</div>
7
-
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
8
-
<form
9
-
hx-post="/repo/new"
10
-
class="space-y-12"
11
-
hx-swap="none"
12
-
hx-indicator="#spinner">
13
-
<div class="space-y-2">
14
-
<label for="name" class="-mb-1 dark:text-white">Repository name</label>
15
-
<input
4
+
<div class="p-6">
5
+
<p class="text-xl font-bold dark:text-white">Create a new repository</p>
6
+
</div>
7
+
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
8
+
<form hx-post="/repo/new" class="space-y-12" hx-swap="none" hx-indicator="#spinner">
9
+
<div class="space-y-2">
10
+
<label for="name" class="-mb-1 dark:text-white">Repository name</label>
11
+
<input
16
12
type="text"
17
13
id="name"
18
14
name="name"
19
15
required
20
-
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600" />
21
-
<p class="text-sm text-gray-500 dark:text-gray-400">
22
-
All repositories are publicly visible.
23
-
</p>
16
+
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600"
17
+
/>
18
+
<p class="text-sm text-gray-500 dark:text-gray-400">All repositories are publicly visible.</p>
24
19
25
-
<label for="branch" class="dark:text-white">Default branch</label>
26
-
<input
20
+
<label for="branch" class="dark:text-white">Default branch</label>
21
+
<input
27
22
type="text"
28
23
id="branch"
29
24
name="branch"
30
25
value="main"
31
26
required
32
-
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600" />
27
+
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600"
28
+
/>
33
29
34
-
<label for="description" class="dark:text-white">Description</label>
35
-
<input
30
+
<label for="description" class="dark:text-white">Description</label>
31
+
<input
36
32
type="text"
37
33
id="description"
38
34
name="description"
39
-
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600" />
40
-
</div>
35
+
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600"
36
+
/>
37
+
</div>
41
38
42
-
<fieldset class="space-y-3">
43
-
<legend class="dark:text-white">Select a knot</legend>
44
-
<div class="space-y-2">
45
-
<div class="flex flex-col">
46
-
{{ range .Knots }}
47
-
<div class="flex items-center">
48
-
<input
49
-
type="radio"
50
-
name="domain"
51
-
value="{{ . }}"
52
-
class="mr-2"
53
-
id="domain-{{ . }}" />
54
-
<span class="dark:text-white">{{ . }}</span>
55
-
</div>
56
-
{{ else }}
57
-
<p class="dark:text-white">No knots available.</p>
58
-
{{ end }}
39
+
<fieldset class="space-y-3">
40
+
<legend class="dark:text-white">Select a knot</legend>
41
+
<div class="space-y-2">
42
+
<div class="flex flex-col">
43
+
{{ range .Knots }}
44
+
<div class="flex items-center">
45
+
<input
46
+
type="radio"
47
+
name="domain"
48
+
value="{{ . }}"
49
+
class="mr-2"
50
+
id="domain-{{ . }}"
51
+
/>
52
+
<span class="dark:text-white">{{ . }}</span>
59
53
</div>
54
+
{{ else }}
55
+
<p class="dark:text-white">No knots available.</p>
56
+
{{ end }}
60
57
</div>
61
-
<p class="text-sm text-gray-500 dark:text-gray-400">
62
-
A knot hosts repository data.
63
-
<a href="/knots" class="underline">
64
-
Learn how to register your own knot.
65
-
</a>
66
-
</p>
67
-
</fieldset>
58
+
</div>
59
+
<p class="text-sm text-gray-500 dark:text-gray-400">A knot hosts repository data. <a href="/knots" class="underline">Learn how to register your own knot.</a></p>
60
+
</fieldset>
68
61
69
-
<div class="space-y-2">
62
+
<div class="space-y-2">
70
63
<button type="submit" class="btn-create flex items-center gap-2">
71
-
{{ i "book-plus" "w-4 h-4" }}
72
-
create repo
73
-
<span id="create-pull-spinner" class="group">
74
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
75
-
</span>
64
+
{{ i "book-plus" "w-4 h-4" }}
65
+
create repo
66
+
<span id="create-pull-spinner" class="group">
67
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
68
+
</span>
76
69
</button>
77
70
<div id="repo" class="error"></div>
78
-
</div>
79
-
</form>
80
-
</div>
71
+
</div>
72
+
</form>
73
+
</div>
81
74
{{ end }}
+12
-21
appview/pages/templates/repo/pipelines/fragments/logBlock.html
+12
-21
appview/pages/templates/repo/pipelines/fragments/logBlock.html
···
1
1
{{ define "repo/pipelines/fragments/logBlock" }}
2
-
<div id="lines" hx-swap-oob="beforeend">
3
-
<details
4
-
id="step-{{ .Id }}"
5
-
{{ if not .Collapsed }}open{{ end }}
6
-
class="group pb-2 rounded-sm border border-gray-200 dark:border-gray-700">
7
-
<summary
8
-
class="sticky top-0 pt-2 px-2 group-open:pb-2 group-open:mb-2 list-none cursor-pointer group-open:border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 hover:text-gray-500 hover:dark:text-gray-400">
9
-
<div class="group-open:hidden flex items-center gap-1">
10
-
{{ i "chevron-right" "w-4 h-4" }}
11
-
{{ .Name }}
12
-
</div>
13
-
<div class="hidden group-open:flex items-center gap-1">
14
-
{{ i "chevron-down" "w-4 h-4" }}
15
-
{{ .Name }}
16
-
</div>
17
-
</summary>
18
-
<div class="font-mono whitespace-pre overflow-x-auto px-2">
19
-
<div class="text-blue-600 dark:text-blue-300">{{ .Command }}</div>
20
-
<div id="step-body-{{ .Id }}"></div>
2
+
<div id="lines" hx-swap-oob="beforeend">
3
+
<details id="step-{{ .Id }}" {{if not .Collapsed}}open{{end}} class="group pb-2 rounded-sm border border-gray-200 dark:border-gray-700">
4
+
<summary class="sticky top-0 pt-2 px-2 group-open:pb-2 group-open:mb-2 list-none cursor-pointer group-open:border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 hover:text-gray-500 hover:dark:text-gray-400">
5
+
<div class="group-open:hidden flex items-center gap-1">
6
+
{{ i "chevron-right" "w-4 h-4" }} {{ .Name }}
7
+
</div>
8
+
<div class="hidden group-open:flex items-center gap-1">
9
+
{{ i "chevron-down" "w-4 h-4" }} {{ .Name }}
21
10
</div>
22
-
</details>
23
-
</div>
11
+
</summary>
12
+
<div class="font-mono whitespace-pre overflow-x-auto px-2"><div class="text-blue-600 dark:text-blue-300">{{ .Command }}</div><div id="step-body-{{ .Id }}"></div></div>
13
+
</details>
14
+
</div>
24
15
{{ end }}
+2
-3
appview/pages/templates/repo/pipelines/fragments/logLine.html
+2
-3
appview/pages/templates/repo/pipelines/fragments/logLine.html
···
1
1
{{ define "repo/pipelines/fragments/logLine" }}
2
-
<div id="step-body-{{ .Id }}" hx-swap-oob="beforeend" class="whitespace-pre">
3
-
<p>{{ .Content }}</p>
4
-
</div>
2
+
<div id="step-body-{{ .Id }}" hx-swap-oob="beforeend" class="whitespace-pre"><p>{{ .Content }}</p></div>
5
3
{{ end }}
4
+
+9
-22
appview/pages/templates/repo/pipelines/fragments/pipelineSymbol.html
+9
-22
appview/pages/templates/repo/pipelines/fragments/pipelineSymbol.html
···
37
37
{{ $offset := 0.0 }}
38
38
<div class="flex gap-1 items-center">
39
39
<svg class="w-4 h-4 transform -rotate-90" viewBox="0 0 20 20">
40
-
<circle
41
-
cx="10"
42
-
cy="10"
43
-
r="{{ $radius }}"
44
-
fill="none"
45
-
stroke="#f3f4f633"
46
-
stroke-width="2" />
40
+
<circle cx="10" cy="10" r="{{ $radius }}" fill="none" stroke="#f3f4f633" stroke-width="2"/>
47
41
48
42
{{ range $kind, $count := $c }}
49
43
{{ $color := "" }}
50
44
{{ if or (eq $kind "pending") (eq $kind "running") }}
51
-
{{ $color = "#eab308" }}
52
-
{{/* amber-500 */}}
45
+
{{ $color = "#eab308" }} {{/* amber-500 */}}
53
46
{{ else if eq $kind "success" }}
54
-
{{ $color = "#10b981" }}
55
-
{{/* green-500 */}}
47
+
{{ $color = "#10b981" }} {{/* green-500 */}}
56
48
{{ else if eq $kind "cancelled" }}
57
-
{{ $color = "#6b7280" }}
58
-
{{/* gray-500 */}}
49
+
{{ $color = "#6b7280" }} {{/* gray-500 */}}
59
50
{{ else if eq $kind "timeout" }}
60
-
{{ $color = "#fb923c" }}
61
-
{{/* orange-400 */}}
51
+
{{ $color = "#fb923c" }} {{/* orange-400 */}}
62
52
{{ else }}
63
-
{{ $color = "#ef4444" }}
64
-
{{/* red-500 for failed or unknown */}}
53
+
{{ $color = "#ef4444" }} {{/* red-500 for failed or unknown */}}
65
54
{{ end }}
66
55
67
56
{{ $percent := divf64 (f64 $count) (f64 $total) }}
68
57
{{ $length := mulf64 $percent $circumference }}
69
-
70
58
71
59
<circle
72
-
cx="10"
73
-
cy="10"
74
-
r="{{ $radius }}"
60
+
cx="10" cy="10" r="{{ $radius }}"
75
61
fill="none"
76
62
stroke="{{ $color }}"
77
63
stroke-width="2"
78
64
stroke-dasharray="{{ printf "%.2f %.2f" $length (subf64 $circumference $length) }}"
79
-
stroke-dashoffset="{{ printf "%.2f" (negf64 $offset) }}" />
65
+
stroke-dashoffset="{{ printf "%.2f" (negf64 $offset) }}"
66
+
/>
80
67
{{ $offset = addf64 $offset $length }}
81
68
{{ end }}
82
69
</svg>
+22
-27
appview/pages/templates/repo/pipelines/fragments/tooltip.html
+22
-27
appview/pages/templates/repo/pipelines/fragments/tooltip.html
···
2
2
{{ $repoinfo := .RepoInfo }}
3
3
{{ $pipeline := .Pipeline }}
4
4
{{ $id := $pipeline.Id }}
5
-
<div
6
-
class="absolute z-[9999] bg-white dark:bg-gray-900 text-black dark:text-white rounded shadow-sm w-80 top-full mt-2 p-2">
5
+
<div class="absolute z-[9999] bg-white dark:bg-gray-900 text-black dark:text-white rounded shadow-sm w-80 top-full mt-2 p-2">
7
6
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700">
8
7
{{ range $name, $all := $pipeline.Statuses }}
9
-
<a
10
-
href="/{{ $repoinfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}"
11
-
class="hover:no-underline">
12
-
<div class="flex items-center justify-between p-2">
13
-
{{ $lastStatus := $all.Latest }}
14
-
{{ $kind := $lastStatus.Status.String }}
8
+
<a href="/{{ $repoinfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}" class="hover:no-underline">
9
+
<div class="flex items-center justify-between p-2">
10
+
{{ $lastStatus := $all.Latest }}
11
+
{{ $kind := $lastStatus.Status.String }}
15
12
16
-
17
-
<div id="left" class="flex items-center gap-2 flex-shrink-0">
18
-
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
19
-
{{ $name }}
20
-
</div>
21
-
<div id="right" class="flex items-center gap-2 flex-shrink-0">
22
-
<span class="font-bold">{{ $kind }}</span>
23
-
{{ if .TimeTaken }}
24
-
{{ template "repo/fragments/duration" .TimeTaken }}
25
-
{{ else }}
26
-
{{ template "repo/fragments/shortTimeAgo" $pipeline.Created }}
27
-
{{ end }}
28
-
</div>
13
+
<div id="left" class="flex items-center gap-2 flex-shrink-0">
14
+
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
15
+
{{ $name }}
16
+
</div>
17
+
<div id="right" class="flex items-center gap-2 flex-shrink-0">
18
+
<span class="font-bold">{{ $kind }}</span>
19
+
{{ if .TimeTaken }}
20
+
{{ template "repo/fragments/duration" .TimeTaken }}
21
+
{{ else }}
22
+
{{ template "repo/fragments/shortTimeAgo" $pipeline.Created }}
23
+
{{ end }}
29
24
</div>
30
-
</a>
31
-
{{ else }}
32
-
<div
33
-
class="flex items-center gap-2 p-2 italic text-gray-600 dark:text-gray-400 ">
34
-
{{ i "hourglass" "size-4" }}
35
-
Waiting for spindle ...
36
25
</div>
26
+
</a>
27
+
{{ else }}
28
+
<div class="flex items-center gap-2 p-2 italic text-gray-600 dark:text-gray-400 ">
29
+
{{ i "hourglass" "size-4" }}
30
+
Waiting for spindle ...
31
+
</div>
37
32
{{ end }}
38
33
</div>
39
34
</div>
+72
-82
appview/pages/templates/repo/pipelines/pipelines.html
+72
-82
appview/pages/templates/repo/pipelines/pipelines.html
···
1
1
{{ define "title" }}pipelines · {{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
{{ $title := "pipelines" }}
5
-
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
6
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
4
+
{{ $title := "pipelines"}}
5
+
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
6
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
7
7
{{ end }}
8
8
9
9
{{ define "repoContent" }}
10
-
<div class="flex justify-between items-center gap-4">
11
-
<div class="w-full flex flex-col gap-2">
12
-
{{ range .Pipelines }}
13
-
{{ block "pipeline" (list $ .) }}{{ end }}
14
-
{{ else }}
15
-
<p class="text-center pt-5 text-gray-400 dark:text-gray-500">
16
-
No pipelines run for this repository.
17
-
</p>
18
-
{{ end }}
19
-
</div>
10
+
<div class="flex justify-between items-center gap-4">
11
+
<div class="w-full flex flex-col gap-2">
12
+
{{ range .Pipelines }}
13
+
{{ block "pipeline" (list $ .) }} {{ end }}
14
+
{{ else }}
15
+
<p class="text-center pt-5 text-gray-400 dark:text-gray-500">
16
+
No pipelines run for this repository.
17
+
</p>
18
+
{{ end }}
20
19
</div>
20
+
</div>
21
21
{{ end }}
22
+
22
23
23
24
{{ define "pipeline" }}
24
25
{{ $root := index . 0 }}
25
26
{{ $p := index . 1 }}
26
27
<div class="py-2 bg-white dark:bg-gray-800 dark:text-white">
27
-
{{ block "pipelineHeader" $ }}{{ end }}
28
+
{{ block "pipelineHeader" $ }} {{ end }}
28
29
</div>
29
30
{{ end }}
30
31
···
32
33
{{ $root := index . 0 }}
33
34
{{ $p := index . 1 }}
34
35
{{ with $p }}
35
-
<div class="grid grid-cols-6 md:grid-cols-12 gap-2 items-center w-full">
36
-
<div class="text-sm md:text-base col-span-1">
37
-
{{ .Trigger.Kind.String }}
38
-
</div>
36
+
<div class="grid grid-cols-6 md:grid-cols-12 gap-2 items-center w-full">
37
+
<div class="text-sm md:text-base col-span-1">
38
+
{{ .Trigger.Kind.String }}
39
+
</div>
39
40
40
-
<div class="col-span-2 md:col-span-7 flex items-center gap-4">
41
-
{{ $target := .Trigger.TargetRef }}
42
-
{{ $workflows := .Workflows }}
43
-
{{ $link := "" }}
44
-
{{ if .IsResponding }}
45
-
{{ $link = printf "/%s/pipelines/%s/workflow/%d" $root.RepoInfo.FullName .Id (index $workflows 0) }}
46
-
{{ end }}
47
-
{{ if .Trigger.IsPush }}
48
-
<span class="font-bold">{{ $target }}</span>
49
-
<span
50
-
class="hidden md:inline-flex gap-2 items-center font-mono text-sm">
51
-
{{ $old := deref .Trigger.PushOldSha }}
52
-
{{ $new := deref .Trigger.PushNewSha }}
53
-
54
-
55
-
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $new }}">
56
-
{{ slice $new 0 8 }}
57
-
</a>
58
-
{{ i "arrow-left" "size-4" }}
59
-
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $old }}">
60
-
{{ slice $old 0 8 }}
61
-
</a>
62
-
</span>
63
-
{{ else if .Trigger.IsPullRequest }}
64
-
{{ $sha := deref .Trigger.PRSourceSha }}
65
-
<span class="inline-flex gap-2 items-center">
41
+
<div class="col-span-2 md:col-span-7 flex items-center gap-4">
42
+
{{ $target := .Trigger.TargetRef }}
43
+
{{ $workflows := .Workflows }}
44
+
{{ $link := "" }}
45
+
{{ if .IsResponding }}
46
+
{{ $link = printf "/%s/pipelines/%s/workflow/%d" $root.RepoInfo.FullName .Id (index $workflows 0) }}
47
+
{{ end }}
48
+
{{ if .Trigger.IsPush }}
66
49
<span class="font-bold">{{ $target }}</span>
67
-
{{ i "arrow-left" "size-4" }}
68
-
{{ .Trigger.PRSourceBranch }}
69
-
<span class="text-sm font-mono">
70
-
@
71
-
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $sha }}">
72
-
{{ slice $sha 0 8 }}
73
-
</a>
50
+
<span class="hidden md:inline-flex gap-2 items-center font-mono text-sm">
51
+
{{ $old := deref .Trigger.PushOldSha }}
52
+
{{ $new := deref .Trigger.PushNewSha }}
53
+
54
+
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $new }}">{{ slice $new 0 8 }}</a>
55
+
{{ i "arrow-left" "size-4" }}
56
+
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $old }}">{{ slice $old 0 8 }}</a>
74
57
</span>
75
-
</span>
76
-
{{ end }}
77
-
</div>
58
+
{{ else if .Trigger.IsPullRequest }}
59
+
{{ $sha := deref .Trigger.PRSourceSha }}
60
+
<span class="inline-flex gap-2 items-center">
61
+
<span class="font-bold">{{ $target }}</span>
62
+
{{ i "arrow-left" "size-4" }}
63
+
{{ .Trigger.PRSourceBranch }}
64
+
<span class="text-sm font-mono">
65
+
@
66
+
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $sha }}">{{ slice $sha 0 8 }}</a>
67
+
</span>
68
+
</span>
69
+
{{ end }}
70
+
</div>
78
71
79
-
<div class="text-sm md:text-base col-span-1">
80
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" . "RepoInfo" $root.RepoInfo) }}
81
-
</div>
72
+
<div class="text-sm md:text-base col-span-1">
73
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" . "RepoInfo" $root.RepoInfo) }}
74
+
</div>
75
+
76
+
<div class="text-sm md:text-base col-span-1 text-right">
77
+
{{ template "repo/fragments/shortTimeAgo" .Created }}
78
+
</div>
82
79
83
-
<div class="text-sm md:text-base col-span-1 text-right">
84
-
{{ template "repo/fragments/shortTimeAgo" .Created }}
85
-
</div>
80
+
{{ $t := .TimeTaken }}
81
+
<div class="text-sm md:text-base col-span-1 text-right">
82
+
{{ if $t }}
83
+
<time title="{{ $t }}">{{ $t | durationFmt }}</time>
84
+
{{ else }}
85
+
<time>--</time>
86
+
{{ end }}
87
+
</div>
86
88
87
-
{{ $t := .TimeTaken }}
88
-
<div class="text-sm md:text-base col-span-1 text-right">
89
-
{{ if $t }}
90
-
<time title="{{ $t }}">{{ $t | durationFmt }}</time>
91
-
{{ else }}
92
-
<time>--</time>
93
-
{{ end }}
94
-
</div>
89
+
<div class="col-span-1 flex justify-end">
90
+
{{ if $link }}
91
+
<a class="md:hidden" href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
92
+
{{ i "arrow-up-right" "size-4" }}
93
+
</a>
94
+
<a class="hidden md:inline underline" href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
95
+
view
96
+
</a>
97
+
{{ end }}
98
+
</div>
95
99
96
-
<div class="col-span-1 flex justify-end">
97
-
{{ if $link }}
98
-
<a
99
-
class="md:hidden"
100
-
href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
101
-
{{ i "arrow-up-right" "size-4" }}
102
-
</a>
103
-
<a
104
-
class="hidden md:inline underline"
105
-
href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
106
-
view
107
-
</a>
108
-
{{ end }}
109
100
</div>
110
-
</div>
111
101
{{ end }}
112
102
{{ end }}
+37
-48
appview/pages/templates/repo/pipelines/workflow.html
+37
-48
appview/pages/templates/repo/pipelines/workflow.html
···
1
-
{{ define "title" }}
2
-
{{ .Workflow }} · pipeline {{ .Pipeline.Id }} ·
3
-
{{ .RepoInfo.FullName }}
4
-
{{ end }}
1
+
{{ define "title" }} {{ .Workflow }} · pipeline {{ .Pipeline.Id }} · {{ .RepoInfo.FullName }}{{ end }}
5
2
6
3
{{ define "extrameta" }}
7
-
{{ $title := "pipelines" }}
8
-
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
9
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
4
+
{{ $title := "pipelines"}}
5
+
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
6
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
10
7
{{ end }}
11
8
12
9
{{ define "repoContent" }}
13
-
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2 mt-2">
14
-
<div class="col-span-1">
15
-
{{ block "sidebar" . }}{{ end }}
16
-
</div>
17
-
<div class="col-span-1 md:col-span-3">
18
-
{{ block "logs" . }}{{ end }}
19
-
</div>
20
-
</section>
10
+
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2 mt-2">
11
+
<div class="col-span-1">
12
+
{{ block "sidebar" . }} {{ end }}
13
+
</div>
14
+
<div class="col-span-1 md:col-span-3">
15
+
{{ block "logs" . }} {{ end }}
16
+
</div>
17
+
</section>
21
18
{{ end }}
22
19
23
20
{{ define "sidebar" }}
···
28
25
29
26
{{ with .Pipeline }}
30
27
{{ $id := .Id }}
31
-
<div
32
-
class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
28
+
<div class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
33
29
{{ range $name, $all := .Statuses }}
34
-
<a
35
-
href="/{{ $.RepoInfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}"
36
-
class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
37
-
<div
38
-
class="flex gap-2 items-center justify-between p-2 {{ if eq $name $active }}
39
-
{{ $activeTab }}
30
+
<a href="/{{ $.RepoInfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
31
+
<div
32
+
class="flex gap-2 items-center justify-between p-2 {{ if eq $name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}">
33
+
{{ $lastStatus := $all.Latest }}
34
+
{{ $kind := $lastStatus.Status.String }}
35
+
36
+
<div id="left" class="flex items-center gap-2 flex-shrink-0">
37
+
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
38
+
{{ $name }}
39
+
</div>
40
+
<div id="right" class="flex items-center gap-2 flex-shrink-0">
41
+
<span class="font-bold">{{ $kind }}</span>
42
+
{{ if .TimeTaken }}
43
+
{{ template "repo/fragments/duration" .TimeTaken }}
40
44
{{ else }}
41
-
{{ $inactiveTab }}
42
-
{{ end }}">
43
-
{{ $lastStatus := $all.Latest }}
44
-
{{ $kind := $lastStatus.Status.String }}
45
-
46
-
47
-
<div id="left" class="flex items-center gap-2 flex-shrink-0">
48
-
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
49
-
{{ $name }}
50
-
</div>
51
-
<div id="right" class="flex items-center gap-2 flex-shrink-0">
52
-
<span class="font-bold">{{ $kind }}</span>
53
-
{{ if .TimeTaken }}
54
-
{{ template "repo/fragments/duration" .TimeTaken }}
55
-
{{ else }}
56
-
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
57
-
{{ end }}
58
-
</div>
45
+
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
46
+
{{ end }}
59
47
</div>
60
-
</a>
48
+
</div>
49
+
</a>
61
50
{{ end }}
62
51
</div>
63
52
{{ end }}
64
53
{{ end }}
65
54
66
55
{{ define "logs" }}
67
-
<div
68
-
id="log-stream"
69
-
class="text-sm"
70
-
hx-ext="ws"
71
-
ws-connect="/{{ $.RepoInfo.FullName }}/pipelines/{{ .Pipeline.Id }}/workflow/{{ .Workflow }}/logs">
72
-
<div id="lines" class="flex flex-col gap-2"></div>
56
+
<div id="log-stream"
57
+
class="text-sm"
58
+
hx-ext="ws"
59
+
ws-connect="/{{ $.RepoInfo.FullName }}/pipelines/{{ .Pipeline.Id }}/workflow/{{ .Workflow }}/logs">
60
+
<div id="lines" class="flex flex-col gap-2">
61
+
</div>
73
62
</div>
74
63
{{ end }}
+63
-62
appview/pages/templates/repo/pulls/fragments/pullActions.html
+63
-62
appview/pages/templates/repo/pulls/fragments/pullActions.html
···
23
23
{{ $isSameRepoBranch := .Pull.IsBranchBased }}
24
24
{{ $isUpToDate := .ResubmitCheck.No }}
25
25
<div class="relative w-fit">
26
-
<div id="actions-{{ $roundNumber }}" class="flex flex-wrap gap-2">
27
-
<button
28
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ $roundNumber }}/comment"
29
-
hx-target="#actions-{{ $roundNumber }}"
30
-
hx-swap="outerHtml"
31
-
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group">
32
-
{{ i "message-square-plus" "w-4 h-4" }}
33
-
<span>comment</span>
34
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
35
-
</button>
36
-
{{ if and $isPushAllowed $isOpen $isLastRound }}
37
-
{{ $disabled := "" }}
38
-
{{ if $isConflicted }}
39
-
{{ $disabled = "disabled" }}
26
+
<div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2">
27
+
<button
28
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ $roundNumber }}/comment"
29
+
hx-target="#actions-{{$roundNumber}}"
30
+
hx-swap="outerHtml"
31
+
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group">
32
+
{{ i "message-square-plus" "w-4 h-4" }}
33
+
<span>comment</span>
34
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
35
+
</button>
36
+
{{ if and $isPushAllowed $isOpen $isLastRound }}
37
+
{{ $disabled := "" }}
38
+
{{ if $isConflicted }}
39
+
{{ $disabled = "disabled" }}
40
+
{{ end }}
41
+
<button
42
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge"
43
+
hx-swap="none"
44
+
hx-confirm="Are you sure you want to merge pull #{{ .Pull.PullId }} into the `{{ .Pull.TargetBranch }}` branch?"
45
+
class="btn p-2 flex items-center gap-2 group" {{ $disabled }}>
46
+
{{ i "git-merge" "w-4 h-4" }}
47
+
<span>merge{{if $stackCount}} {{$stackCount}}{{end}}</span>
48
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
49
+
</button>
40
50
{{ end }}
41
-
<button
42
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge"
43
-
hx-swap="none"
44
-
hx-confirm="Are you sure you want to merge pull #{{ .Pull.PullId }} into the `{{ .Pull.TargetBranch }}` branch?"
45
-
class="btn p-2 flex items-center gap-2 group"
46
-
{{ $disabled }}>
47
-
{{ i "git-merge" "w-4 h-4" }}
48
-
<span>merge{{ if $stackCount }}{{ $stackCount }}{{ end }}</span>
49
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
50
-
</button>
51
-
{{ end }}
52
51
53
-
{{ if and $isPullAuthor $isOpen $isLastRound }}
54
-
{{ $disabled := "" }}
55
-
{{ if $isUpToDate }}
56
-
{{ $disabled = "disabled" }}
57
-
{{ end }}
58
-
<button
59
-
id="resubmitBtn"
60
-
{{ if not .Pull.IsPatchBased }}
61
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
62
-
{{ else }}
63
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
64
-
hx-target="#actions-{{ $roundNumber }}" hx-swap="outerHtml"
52
+
{{ if and $isPullAuthor $isOpen $isLastRound }}
53
+
{{ $disabled := "" }}
54
+
{{ if $isUpToDate }}
55
+
{{ $disabled = "disabled" }}
65
56
{{ end }}
57
+
<button id="resubmitBtn"
58
+
{{ if not .Pull.IsPatchBased }}
59
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
60
+
{{ else }}
61
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
62
+
hx-target="#actions-{{$roundNumber}}"
63
+
hx-swap="outerHtml"
64
+
{{ end }}
66
65
67
-
hx-disabled-elt="#resubmitBtn"
68
-
class="btn p-2 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed group"
69
-
{{ $disabled }}
66
+
hx-disabled-elt="#resubmitBtn"
67
+
class="btn p-2 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed group" {{ $disabled }}
70
68
71
-
{{ if $disabled }}
72
-
title="Update this branch to resubmit this pull request"
73
-
{{ else }}
74
-
title="Resubmit this pull request"
75
-
{{ end }}>
76
-
{{ i "rotate-ccw" "w-4 h-4" }}
77
-
<span>resubmit</span>
78
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
79
-
</button>
80
-
{{ end }}
69
+
{{ if $disabled }}
70
+
title="Update this branch to resubmit this pull request"
71
+
{{ else }}
72
+
title="Resubmit this pull request"
73
+
{{ end }}
74
+
>
75
+
{{ i "rotate-ccw" "w-4 h-4" }}
76
+
<span>resubmit</span>
77
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
78
+
</button>
79
+
{{ end }}
81
80
82
-
{{ if and (or $isPullAuthor $isPushAllowed) $isOpen $isLastRound }}
83
-
<button
81
+
{{ if and (or $isPullAuthor $isPushAllowed) $isOpen $isLastRound }}
82
+
<button
84
83
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/close"
85
84
hx-swap="none"
86
85
class="btn p-2 flex items-center gap-2 group">
87
-
{{ i "ban" "w-4 h-4" }}
88
-
<span>close</span>
89
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
86
+
{{ i "ban" "w-4 h-4" }}
87
+
<span>close</span>
88
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
90
89
</button>
91
-
{{ end }}
90
+
{{ end }}
92
91
93
-
{{ if and (or $isPullAuthor $isPushAllowed) $isClosed $isLastRound }}
94
-
<button
92
+
{{ if and (or $isPullAuthor $isPushAllowed) $isClosed $isLastRound }}
93
+
<button
95
94
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/reopen"
96
95
hx-swap="none"
97
96
class="btn p-2 flex items-center gap-2 group">
98
-
{{ i "refresh-ccw-dot" "w-4 h-4" }}
99
-
<span>reopen</span>
100
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
97
+
{{ i "refresh-ccw-dot" "w-4 h-4" }}
98
+
<span>reopen</span>
99
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
101
100
</button>
102
-
{{ end }}
101
+
{{ end }}
103
102
</div>
104
103
</div>
105
104
{{ end }}
105
+
106
+
+39
-42
appview/pages/templates/repo/pulls/fragments/pullCompareBranches.html
+39
-42
appview/pages/templates/repo/pulls/fragments/pullCompareBranches.html
···
1
1
{{ define "repo/pulls/fragments/pullCompareBranches" }}
2
-
<div id="patch-upload">
3
-
<label for="targetBranch" class="dark:text-white">
4
-
select a source branch
5
-
</label>
6
-
<div class="flex flex-wrap gap-2 items-center">
7
-
<select
8
-
name="sourceBranch"
9
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600">
10
-
<option disabled selected>source branch</option>
2
+
<div id="patch-upload">
3
+
<label for="targetBranch" class="dark:text-white">select a source branch</label>
4
+
<div class="flex flex-wrap gap-2 items-center">
5
+
<select
6
+
name="sourceBranch"
7
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
8
+
>
9
+
<option disabled selected>source branch</option>
11
10
12
-
{{ $recent := index .Branches 0 }}
13
-
{{ range .Branches }}
14
-
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
15
-
{{ $preset := false }}
16
-
{{ if $.SourceBranch }}
17
-
{{ $preset = eq .Reference.Name $.SourceBranch }}
18
-
{{ else }}
19
-
{{ $preset = $isRecent }}
20
-
{{ end }}
11
+
{{ $recent := index .Branches 0 }}
12
+
{{ range .Branches }}
13
+
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
14
+
{{ $preset := false }}
15
+
{{ if $.SourceBranch }}
16
+
{{ $preset = eq .Reference.Name $.SourceBranch }}
17
+
{{ else }}
18
+
{{ $preset = $isRecent }}
19
+
{{ end }}
20
+
21
+
<option
22
+
value="{{ .Reference.Name }}"
23
+
{{ if $preset }}
24
+
selected
25
+
{{ end }}
26
+
class="py-1"
27
+
>
28
+
{{ .Reference.Name }}
29
+
{{ if $isRecent }}(new){{ end }}
30
+
</option>
31
+
{{ end }}
32
+
</select>
33
+
</div>
34
+
</div>
21
35
22
-
23
-
<option
24
-
value="{{ .Reference.Name }}"
25
-
{{ if $preset }}
26
-
selected
27
-
{{ end }}
28
-
class="py-1">
29
-
{{ .Reference.Name }}
30
-
{{ if $isRecent }}(new){{ end }}
31
-
</option>
32
-
{{ end }}
33
-
</select>
36
+
<div class="flex items-center gap-2">
37
+
<input type="checkbox" id="isStacked" name="isStacked" value="on">
38
+
<label for="isStacked" class="my-0 py-0 normal-case font-normal">Submit as stacked PRs</label>
34
39
</div>
35
-
</div>
36
40
37
-
<div class="flex items-center gap-2">
38
-
<input type="checkbox" id="isStacked" name="isStacked" value="on" />
39
-
<label for="isStacked" class="my-0 py-0 normal-case font-normal">
40
-
Submit as stacked PRs
41
-
</label>
42
-
</div>
43
-
44
-
<p class="mt-4">
45
-
Title and description are optional; if left out, they will be extracted from
46
-
the first commit.
47
-
</p>
41
+
<p class="mt-4">
42
+
Title and description are optional; if left out, they will be extracted
43
+
from the first commit.
44
+
</p>
48
45
{{ end }}
+45
-45
appview/pages/templates/repo/pulls/fragments/pullCompareForks.html
+45
-45
appview/pages/templates/repo/pulls/fragments/pullCompareForks.html
···
1
1
{{ define "repo/pulls/fragments/pullCompareForks" }}
2
-
<div id="patch-upload">
3
-
<label for="forkSelect" class="dark:text-white">
4
-
select a fork to compare
5
-
</label>
6
-
selected:
7
-
{{ .Selected }}
8
-
<div class="flex flex-wrap gap-4 items-center">
9
-
<div class="flex flex-wrap gap-2 items-center">
10
-
<select
11
-
id="forkSelect"
12
-
name="fork"
13
-
required
14
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
15
-
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
16
-
hx-target="#branch-selection"
17
-
hx-vals='{"fork": this.value}'
18
-
hx-swap="innerHTML"
19
-
onchange="document.getElementById('hiddenForkInput').value = this.value;">
20
-
<option disabled selected>select a fork</option>
21
-
{{ range .Forks }}
22
-
<option
23
-
value="{{ .Name }}"
24
-
{{ if eq .Name $.Selected }}selected{{ end }}
25
-
class="py-1">
26
-
{{ .Name }}
27
-
</option>
28
-
{{ end }}
29
-
</select>
2
+
<div id="patch-upload">
3
+
<label for="forkSelect" class="dark:text-white"
4
+
>select a fork to compare</label
5
+
>
6
+
selected: {{ .Selected }}
7
+
<div class="flex flex-wrap gap-4 items-center">
8
+
<div class="flex flex-wrap gap-2 items-center">
9
+
<select
10
+
id="forkSelect"
11
+
name="fork"
12
+
required
13
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
14
+
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
15
+
hx-target="#branch-selection"
16
+
hx-vals='{"fork": this.value}'
17
+
hx-swap="innerHTML"
18
+
onchange="document.getElementById('hiddenForkInput').value = this.value;"
19
+
>
20
+
<option disabled selected>select a fork</option>
21
+
{{ range .Forks }}
22
+
<option value="{{ .Name }}" {{ if eq .Name $.Selected }}selected{{ end }} class="py-1">
23
+
{{ .Name }}
24
+
</option>
25
+
{{ end }}
26
+
</select>
30
27
31
-
<input type="hidden" id="hiddenForkInput" name="fork" value="" />
32
-
</div>
28
+
<input
29
+
type="hidden"
30
+
id="hiddenForkInput"
31
+
name="fork"
32
+
value=""
33
+
/>
34
+
</div>
33
35
34
-
<div id="branch-selection">
35
-
<div class="text-sm text-gray-500 dark:text-gray-400">
36
-
Select a fork first to view available branches
36
+
<div id="branch-selection">
37
+
<div class="text-sm text-gray-500 dark:text-gray-400">
38
+
Select a fork first to view available branches
39
+
</div>
40
+
</div>
37
41
</div>
38
-
</div>
39
42
</div>
40
-
</div>
41
43
42
-
<div class="flex items-center gap-2">
43
-
<input type="checkbox" id="isStacked" name="isStacked" value="on" />
44
-
<label for="isStacked" class="my-0 py-0 normal-case font-normal">
45
-
Submit as stacked PRs
46
-
</label>
47
-
</div>
44
+
<div class="flex items-center gap-2">
45
+
<input type="checkbox" id="isStacked" name="isStacked" value="on">
46
+
<label for="isStacked" class="my-0 py-0 normal-case font-normal">Submit as stacked PRs</label>
47
+
</div>
48
48
49
-
<p class="mt-4">
50
-
Title and description are optional; if left out, they will be extracted from
51
-
the first commit.
52
-
</p>
49
+
<p class="mt-4">
50
+
Title and description are optional; if left out, they will be extracted
51
+
from the first commit.
52
+
</p>
53
53
{{ end }}
+22
-20
appview/pages/templates/repo/pulls/fragments/pullCompareForksBranches.html
+22
-20
appview/pages/templates/repo/pulls/fragments/pullCompareForksBranches.html
···
1
1
{{ define "repo/pulls/fragments/pullCompareForksBranches" }}
2
-
<div class="flex flex-wrap gap-2 items-center">
3
-
<select
4
-
name="sourceBranch"
5
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600">
6
-
<option disabled selected>source branch</option>
2
+
<div class="flex flex-wrap gap-2 items-center">
3
+
<select
4
+
name="sourceBranch"
5
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
6
+
>
7
+
<option disabled selected>source branch</option>
7
8
8
-
{{ $recent := index .SourceBranches 0 }}
9
-
{{ range .SourceBranches }}
10
-
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
11
-
<option
12
-
value="{{ .Reference.Name }}"
13
-
{{ if $isRecent }}
14
-
selected
15
-
{{ end }}
16
-
class="py-1">
17
-
{{ .Reference.Name }}
18
-
{{ if $isRecent }}(new){{ end }}
19
-
</option>
20
-
{{ end }}
21
-
</select>
22
-
</div>
9
+
{{ $recent := index .SourceBranches 0 }}
10
+
{{ range .SourceBranches }}
11
+
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
12
+
<option
13
+
value="{{ .Reference.Name }}"
14
+
{{ if $isRecent }}
15
+
selected
16
+
{{ end }}
17
+
class="py-1"
18
+
>
19
+
{{ .Reference.Name }}
20
+
{{ if $isRecent }}(new){{ end }}
21
+
</option>
22
+
{{ end }}
23
+
</select>
24
+
</div>
23
25
{{ end }}
+59
-68
appview/pages/templates/repo/pulls/fragments/pullHeader.html
+59
-68
appview/pages/templates/repo/pulls/fragments/pullHeader.html
···
1
1
{{ define "repo/pulls/fragments/pullHeader" }}
2
-
<header class="pb-4">
2
+
<header class="pb-4">
3
3
<h1 class="text-2xl dark:text-white">
4
-
{{ .Pull.Title }}
5
-
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
4
+
{{ .Pull.Title }}
5
+
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
6
6
</h1>
7
-
</header>
7
+
</header>
8
8
9
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
10
-
{{ $icon := "ban" }}
9
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
10
+
{{ $icon := "ban" }}
11
11
12
-
{{ if .Pull.State.IsOpen }}
12
+
{{ if .Pull.State.IsOpen }}
13
13
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
14
14
{{ $icon = "git-pull-request" }}
15
-
{{ else if .Pull.State.IsMerged }}
15
+
{{ else if .Pull.State.IsMerged }}
16
16
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
17
17
{{ $icon = "git-merge" }}
18
-
{{ end }}
18
+
{{ end }}
19
19
20
-
{{ $owner := resolve .Pull.OwnerDid }}
21
-
<section class="mt-2">
20
+
{{ $owner := resolve .Pull.OwnerDid }}
21
+
<section class="mt-2">
22
22
<div class="flex items-center gap-2">
23
-
<div
24
-
id="state"
25
-
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
26
-
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
27
-
<span class="text-white">{{ .Pull.State.String }}</span>
28
-
</div>
29
-
<span
30
-
class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
31
-
opened by
32
-
{{ template "user/fragments/picHandleLink" .Pull.OwnerDid }}
33
-
<span class="select-none before:content-['\00B7']"></span>
34
-
{{ template "repo/fragments/time" .Pull.Created }}
23
+
<div
24
+
id="state"
25
+
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
26
+
>
27
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
28
+
<span class="text-white">{{ .Pull.State.String }}</span>
29
+
</div>
30
+
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
31
+
opened by
32
+
{{ template "user/fragments/picHandleLink" .Pull.OwnerDid }}
33
+
<span class="select-none before:content-['\00B7']"></span>
34
+
{{ template "repo/fragments/time" .Pull.Created }}
35
35
36
-
37
-
<span class="select-none before:content-['\00B7']"></span>
38
-
<span>
39
-
targeting
40
-
<span
41
-
class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
42
-
<a
43
-
href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}"
44
-
class="no-underline hover:underline">
45
-
{{ .Pull.TargetBranch }}
46
-
</a>
47
-
</span>
36
+
<span class="select-none before:content-['\00B7']"></span>
37
+
<span>
38
+
targeting
39
+
<span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
40
+
<a href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}" class="no-underline hover:underline">{{ .Pull.TargetBranch }}</a>
41
+
</span>
42
+
</span>
43
+
{{ if not .Pull.IsPatchBased }}
44
+
from
45
+
<span class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
46
+
{{ if .Pull.IsForkBased }}
47
+
{{ if .Pull.PullSource.Repo }}
48
+
<a href="/{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}</a>:
49
+
{{- else -}}
50
+
<span class="italic">[deleted fork]</span>
51
+
{{- end -}}
52
+
{{- end -}}
53
+
{{- .Pull.PullSource.Branch -}}
54
+
</span>
55
+
{{ end }}
48
56
</span>
49
-
{{ if not .Pull.IsPatchBased }}
50
-
from
51
-
<span
52
-
class="text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 mx-1/2 inline-flex items-center">
53
-
{{ if .Pull.IsForkBased }}
54
-
{{ if .Pull.PullSource.Repo }}
55
-
<a
56
-
href="/{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}"
57
-
class="no-underline hover:underline">
58
-
{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}
59
-
</a>
60
-
:
61
-
{{- else -}}
62
-
<span class="italic">[deleted fork]</span>
63
-
{{- end -}}
64
-
{{- end -}}
65
-
{{- .Pull.PullSource.Branch -}}
66
-
</span>
67
-
{{ end }}
68
-
</span>
69
57
</div>
70
58
71
59
{{ if .Pull.Body }}
72
-
<article id="body" class="mt-8 prose dark:prose-invert">
73
-
{{ .Pull.Body | markdown }}
74
-
</article>
60
+
<article id="body" class="mt-8 prose dark:prose-invert">
61
+
{{ .Pull.Body | markdown }}
62
+
</article>
75
63
{{ end }}
76
64
77
65
{{ with .OrderedReactionKinds }}
78
-
<div class="flex items-center gap-2 mt-2">
66
+
<div class="flex items-center gap-2 mt-2">
79
67
{{ template "repo/fragments/reactionsPopUp" . }}
80
68
{{ range $kind := . }}
81
-
{{ template "repo/fragments/reaction"
82
-
(dict
83
-
"Kind" $kind
84
-
"Count" (index $.Reactions $kind)
85
-
"IsReacted" (index $.UserReacted $kind)
86
-
"ThreadAt" $.Pull.PullAt)
87
-
}}
69
+
{{
70
+
template "repo/fragments/reaction"
71
+
(dict
72
+
"Kind" $kind
73
+
"Count" (index $.Reactions $kind)
74
+
"IsReacted" (index $.UserReacted $kind)
75
+
"ThreadAt" $.Pull.PullAt)
76
+
}}
88
77
{{ end }}
89
-
</div>
78
+
</div>
90
79
{{ end }}
91
-
</section>
80
+
</section>
81
+
82
+
92
83
{{ end }}
+31
-28
appview/pages/templates/repo/pulls/fragments/pullNewComment.html
+31
-28
appview/pages/templates/repo/pulls/fragments/pullNewComment.html
···
1
1
{{ define "repo/pulls/fragments/pullNewComment" }}
2
-
<div
3
-
id="pull-comment-card-{{ .RoundNumber }}"
4
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm p-4 relative w-full flex flex-col gap-2">
5
-
<div class="text-sm text-gray-500 dark:text-gray-400">
6
-
{{ didOrHandle .LoggedInUser.Did .LoggedInUser.Handle }}
7
-
</div>
8
-
<form
9
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/comment"
10
-
hx-indicator="#create-comment-spinner"
11
-
hx-swap="none"
12
-
class="w-full flex flex-wrap gap-2">
13
-
<textarea
2
+
<div
3
+
id="pull-comment-card-{{ .RoundNumber }}"
4
+
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm p-4 relative w-full flex flex-col gap-2">
5
+
<div class="text-sm text-gray-500 dark:text-gray-400">
6
+
{{ didOrHandle .LoggedInUser.Did .LoggedInUser.Handle }}
7
+
</div>
8
+
<form
9
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/comment"
10
+
hx-indicator="#create-comment-spinner"
11
+
hx-swap="none"
12
+
class="w-full flex flex-wrap gap-2"
13
+
>
14
+
<textarea
14
15
name="body"
15
16
class="w-full p-2 rounded border border-gray-200"
16
-
placeholder="Add to the discussion..."></textarea>
17
-
<button type="submit" class="btn flex items-center gap-2">
17
+
placeholder="Add to the discussion..."></textarea
18
+
>
19
+
<button type="submit" class="btn flex items-center gap-2">
18
20
{{ i "message-square" "w-4 h-4" }}
19
21
<span>comment</span>
20
22
<span id="create-comment-spinner" class="group">
21
23
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
22
24
</span>
23
-
</button>
24
-
<button
25
-
type="button"
26
-
class="btn flex items-center gap-2 group"
27
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/actions"
28
-
hx-swap="outerHTML"
29
-
hx-target="#pull-comment-card-{{ .RoundNumber }}">
30
-
{{ i "x" "w-4 h-4" }}
31
-
<span>cancel</span>
32
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
33
-
</button>
34
-
<div id="pull-comment"></div>
35
-
</form>
36
-
</div>
25
+
</button>
26
+
<button
27
+
type="button"
28
+
class="btn flex items-center gap-2 group"
29
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/actions"
30
+
hx-swap="outerHTML"
31
+
hx-target="#pull-comment-card-{{ .RoundNumber }}"
32
+
>
33
+
{{ i "x" "w-4 h-4" }}
34
+
<span>cancel</span>
35
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
36
+
</button>
37
+
<div id="pull-comment"></div>
38
+
</form>
39
+
</div>
37
40
{{ end }}
+17
-19
appview/pages/templates/repo/pulls/fragments/pullPatchUpload.html
+17
-19
appview/pages/templates/repo/pulls/fragments/pullPatchUpload.html
···
1
1
{{ define "repo/pulls/fragments/pullPatchUpload" }}
2
-
<div id="patch-upload">
3
-
<p>
4
-
You can paste a
5
-
<code>git diff</code>
6
-
or a
7
-
<code>git format-patch</code>
8
-
patch series here.
9
-
</p>
10
-
<textarea
11
-
hx-trigger="keyup changed delay:500ms, paste delay:500ms"
12
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/new/validate-patch"
13
-
hx-swap="none"
14
-
name="patch"
15
-
id="patch"
16
-
rows="12"
17
-
class="w-full mt-2 resize-y font-mono dark:bg-gray-700 dark:text-white dark:border-gray-600"
18
-
placeholder="diff --git a/file.txt b/file.txt
2
+
<div id="patch-upload">
3
+
<p>
4
+
You can paste a <code>git diff</code> or a
5
+
<code>git format-patch</code> patch series here.
6
+
</p>
7
+
<textarea
8
+
hx-trigger="keyup changed delay:500ms, paste delay:500ms"
9
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/new/validate-patch"
10
+
hx-swap="none"
11
+
name="patch"
12
+
id="patch"
13
+
rows="12"
14
+
class="w-full mt-2 resize-y font-mono dark:bg-gray-700 dark:text-white dark:border-gray-600"
15
+
placeholder="diff --git a/file.txt b/file.txt
19
16
index 1234567..abcdefg 100644
20
17
--- a/file.txt
21
-
+++ b/file.txt"></textarea>
22
-
</div>
18
+
+++ b/file.txt"
19
+
></textarea>
20
+
</div>
23
21
{{ end }}
+57
-53
appview/pages/templates/repo/pulls/fragments/pullResubmit.html
+57
-53
appview/pages/templates/repo/pulls/fragments/pullResubmit.html
···
1
1
{{ define "repo/pulls/fragments/pullResubmit" }}
2
2
<div
3
-
id="resubmit-pull-card"
4
-
class="rounded relative border bg-amber-50 dark:bg-amber-900 border-amber-200 dark:border-amber-500 px-6 py-2">
5
-
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-50">
6
-
{{ i "pencil" "w-4 h-4" }}
7
-
<span class="font-medium">resubmit your patch</span>
8
-
</div>
3
+
id="resubmit-pull-card"
4
+
class="rounded relative border bg-amber-50 dark:bg-amber-900 border-amber-200 dark:border-amber-500 px-6 py-2">
9
5
10
-
<div class="mt-2 text-sm text-gray-700 dark:text-gray-200">
11
-
You can update this patch to address any reviews. This will begin a new
12
-
round of reviews, but you'll still be able to view your previous
13
-
submissions and feedback.
14
-
</div>
6
+
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-50">
7
+
{{ i "pencil" "w-4 h-4" }}
8
+
<span class="font-medium">resubmit your patch</span>
9
+
</div>
15
10
16
-
<div class="mt-4 flex flex-col">
17
-
<form
18
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
19
-
hx-swap="none"
20
-
class="w-full flex flex-wrap gap-2"
21
-
hx-indicator="#resubmit-spinner">
22
-
<textarea
23
-
name="patch"
24
-
class="w-full p-2 mb-2"
25
-
placeholder="Paste your updated patch here."
26
-
rows="15">
27
-
{{ .Pull.LatestPatch }}
28
-
</textarea
11
+
<div class="mt-2 text-sm text-gray-700 dark:text-gray-200">
12
+
You can update this patch to address any reviews.
13
+
This will begin a new round of reviews,
14
+
but you'll still be able to view your previous submissions and feedback.
15
+
</div>
16
+
17
+
<div class="mt-4 flex flex-col">
18
+
<form
19
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
20
+
hx-swap="none"
21
+
class="w-full flex flex-wrap gap-2"
22
+
hx-indicator="#resubmit-spinner"
29
23
>
30
-
<button
31
-
type="submit"
32
-
class="btn flex items-center gap-2"
33
-
{{ if or .Pull.State.IsClosed }}
34
-
disabled
35
-
{{ end }}>
36
-
{{ i "rotate-ccw" "w-4 h-4" }}
37
-
<span>resubmit</span>
38
-
<span id="resubmit-spinner" class="group">
39
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
40
-
</span>
41
-
</button>
42
-
<button
43
-
type="button"
44
-
class="btn flex items-center gap-2"
45
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Pull.LastRoundNumber }}/actions"
46
-
hx-swap="outerHTML"
47
-
hx-target="#resubmit-pull-card"
48
-
hx-indicator="#cancel-resubmit-spinner">
49
-
{{ i "x" "w-4 h-4" }}
50
-
<span>cancel</span>
51
-
<span id="cancel-resubmit-spinner" class="group">
52
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
53
-
</span>
54
-
</button>
55
-
</form>
24
+
<textarea
25
+
name="patch"
26
+
class="w-full p-2 mb-2"
27
+
placeholder="Paste your updated patch here."
28
+
rows="15"
29
+
>
30
+
{{.Pull.LatestPatch}}
31
+
</textarea>
32
+
<button
33
+
type="submit"
34
+
class="btn flex items-center gap-2"
35
+
{{ if or .Pull.State.IsClosed }}
36
+
disabled
37
+
{{ end }}
38
+
>
39
+
{{ i "rotate-ccw" "w-4 h-4" }}
40
+
<span>resubmit</span>
41
+
<span id="resubmit-spinner" class="group">
42
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
43
+
</span>
44
+
</button>
45
+
<button
46
+
type="button"
47
+
class="btn flex items-center gap-2"
48
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Pull.LastRoundNumber }}/actions"
49
+
hx-swap="outerHTML"
50
+
hx-target="#resubmit-pull-card"
51
+
hx-indicator="#cancel-resubmit-spinner"
52
+
>
53
+
{{ i "x" "w-4 h-4" }}
54
+
<span>cancel</span>
55
+
<span id="cancel-resubmit-spinner" class="group">
56
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
57
+
</span>
58
+
</button>
59
+
</form>
56
60
57
-
<div id="resubmit-error" class="error"></div>
58
-
<div id="resubmit-success" class="success"></div>
59
-
</div>
61
+
<div id="resubmit-error" class="error"></div>
62
+
<div id="resubmit-success" class="success"></div>
63
+
</div>
60
64
</div>
61
65
{{ end }}
+10
-27
appview/pages/templates/repo/pulls/fragments/pullStack.html
+10
-27
appview/pages/templates/repo/pulls/fragments/pullStack.html
···
1
1
{{ define "repo/pulls/fragments/pullStack" }}
2
2
<details class="bg-white dark:bg-gray-800 group" open>
3
-
<summary
4
-
class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
3
+
<summary class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
5
4
<span class="flex items-center gap-2">
6
5
<span class="group-open:hidden">
7
6
{{ i "chevrons-up-down" "w-4 h-4" }}
···
10
9
{{ i "chevrons-down-up" "w-4 h-4" }}
11
10
</span>
12
11
STACK
13
-
<span
14
-
class="bg-gray-200 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
15
-
{{ len .Stack }}
16
-
</span>
12
+
<span class="bg-gray-200 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ len .Stack }}</span>
17
13
</span>
18
14
</summary>
19
-
{{ block "pullList" (list .Stack $) }}{{ end }}
15
+
{{ block "pullList" (list .Stack $) }} {{ end }}
20
16
</details>
21
17
22
18
{{ if gt (len .AbandonedPulls) 0 }}
23
19
<details class="mt-4 bg-white dark:bg-gray-800 group" open>
24
-
<summary
25
-
class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
20
+
<summary class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
26
21
<span class="flex items-center gap-2">
27
22
<span class="group-open:hidden">
28
23
{{ i "chevrons-up-down" "w-4 h-4" }}
···
31
26
{{ i "chevrons-down-up" "w-4 h-4" }}
32
27
</span>
33
28
ABANDONED PULLS
34
-
<span
35
-
class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm ml-1">
36
-
{{ len .AbandonedPulls }}
37
-
</span>
29
+
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm ml-1">{{ len .AbandonedPulls }}</span>
38
30
</span>
39
31
</summary>
40
-
{{ block "pullList" (list .AbandonedPulls $) }}{{ end }}
32
+
{{ block "pullList" (list .AbandonedPulls $) }} {{ end }}
41
33
</details>
42
34
{{ end }}
43
35
{{ end }}
···
45
37
{{ define "pullList" }}
46
38
{{ $list := index . 0 }}
47
39
{{ $root := index . 1 }}
48
-
<div
49
-
class="grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
40
+
<div class="grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
50
41
{{ range $pull := $list }}
51
42
{{ $isCurrent := false }}
52
43
{{ $pipeline := index $root.Pipelines $pull.LatestSha }}
53
44
{{ with $root.Pull }}
54
45
{{ $isCurrent = eq $pull.PullId $root.Pull.PullId }}
55
46
{{ end }}
56
-
<a
57
-
href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $pull.PullId }}"
58
-
class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
59
-
<div
60
-
class="flex gap-2 items-center px-2 {{ if $isCurrent }}
61
-
bg-gray-100/50 dark:bg-gray-700/50
62
-
{{ end }}">
47
+
<a href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $pull.PullId }}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
48
+
<div class="flex gap-2 items-center px-2 {{ if $isCurrent }}bg-gray-100/50 dark:bg-gray-700/50{{ end }}">
63
49
{{ if $isCurrent }}
64
50
<div class="flex-shrink-0">
65
51
{{ i "arrow-right" "w-4 h-4" }}
66
52
</div>
67
53
{{ end }}
68
-
<div
69
-
class="{{ if not $isCurrent }}
70
-
pl-6
71
-
{{ end }} flex-grow min-w-0 w-full py-2">
54
+
<div class="{{ if not $isCurrent }} pl-6 {{ end }} flex-grow min-w-0 w-full py-2">
72
55
{{ template "repo/pulls/fragments/summarizedHeader" (list $pull $pipeline) }}
73
56
</div>
74
57
</div>
+4
-7
appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html
+4
-7
appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html
···
19
19
{{ $commentCount := len $lastSubmission.Comments }}
20
20
{{ if and $pipeline $pipeline.Id }}
21
21
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
22
-
<span
23
-
class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
22
+
<span class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
24
23
{{ end }}
25
24
<span>
26
25
<div class="inline-flex items-center gap-1">
27
26
{{ i "message-square" "w-3 h-3 md:hidden" }}
28
27
{{ $commentCount }}
29
-
<span class="hidden md:inline">
30
-
comment{{ if ne $commentCount 1 }}s{{ end }}
31
-
</span>
28
+
<span class="hidden md:inline">comment{{if ne $commentCount 1}}s{{end}}</span>
32
29
</div>
33
30
</span>
34
-
<span
35
-
class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
31
+
<span class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
36
32
<span>
37
33
<span class="hidden md:inline">round</span>
38
34
<span class="font-mono">#{{ $latestRound }}</span>
···
41
37
</div>
42
38
{{ end }}
43
39
{{ end }}
40
+
+1
appview/pages/templates/repo/pulls/fragments/summarizedPullState.html
+1
appview/pages/templates/repo/pulls/fragments/summarizedPullState.html
+20
-23
appview/pages/templates/repo/pulls/interdiff.html
+20
-23
appview/pages/templates/repo/pulls/interdiff.html
···
1
1
{{ define "title" }}
2
-
interdiff of round #{{ .Round }} and #{{ sub .Round 1 }} · pull
3
-
#{{ .Pull.PullId }} ·
4
-
{{ .RepoInfo.FullName }}
2
+
interdiff of round #{{ .Round }} and #{{ sub .Round 1 }} · pull #{{ .Pull.PullId }} · {{ .RepoInfo.FullName }}
5
3
{{ end }}
4
+
6
5
7
6
{{ define "extrameta" }}
8
-
{{ $title := printf "interdiff of %d and %d · %s · pull #%d · %s" .Round (sub .Round 1) .Pull.Title .Pull.PullId .RepoInfo.FullName }}
9
-
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
10
-
11
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" (unescapeHtml $title) "Url" $url) }}
7
+
{{ $title := printf "interdiff of %d and %d · %s · pull #%d · %s" .Round (sub .Round 1) .Pull.Title .Pull.PullId .RepoInfo.FullName }}
8
+
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
9
+
10
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" (unescapeHtml $title) "Url" $url) }}
12
11
{{ end }}
13
12
14
13
{{ define "content" }}
15
-
<section
16
-
class="rounded drop-shadow-sm bg-white dark:bg-gray-800 py-4 px-6 dark:text-white">
14
+
<section class="rounded drop-shadow-sm bg-white dark:bg-gray-800 py-4 px-6 dark:text-white">
17
15
<header class="pb-2">
18
16
<div class="flex gap-3 items-center mb-3">
19
-
<a
20
-
href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/"
21
-
class="flex items-center gap-2 font-medium">
17
+
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/" class="flex items-center gap-2 font-medium">
22
18
{{ i "arrow-left" "w-5 h-5" }}
23
19
back
24
20
</a>
25
21
<span class="select-none before:content-['\00B7']"></span>
26
-
interdiff of round #{{ .Round }} and
27
-
#{{ sub .Round 1 }}
22
+
interdiff of round #{{ .Round }} and #{{ sub .Round 1 }}
28
23
</div>
29
24
<div class="border-t border-gray-200 dark:border-gray-700 my-2"></div>
30
25
{{ template "repo/pulls/fragments/pullHeader" . }}
31
26
</header>
32
27
</section>
28
+
33
29
{{ end }}
34
30
35
31
{{ define "topbarLayout" }}
···
45
41
{{ end }}
46
42
47
43
{{ block "contentAfterLayout" . }}
48
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
49
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
50
-
{{ block "contentAfterLeft" . }}{{ end }}
51
-
</div>
52
-
<main class="col-span-1 md:col-span-10">
53
-
{{ block "contentAfter" . }}{{ end }}
54
-
</main>
44
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
45
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
46
+
{{ block "contentAfterLeft" . }} {{ end }}
55
47
</div>
48
+
<main class="col-span-1 md:col-span-10">
49
+
{{ block "contentAfter" . }}{{ end }}
50
+
</main>
51
+
</div>
56
52
{{ end }}
57
53
</div>
58
54
{{ end }}
···
63
59
</footer>
64
60
{{ end }}
65
61
62
+
66
63
{{ define "contentAfter" }}
67
64
{{ template "repo/fragments/interdiff" (list .RepoInfo.FullName .Interdiff .DiffOpts) }}
68
-
{{ end }}
65
+
{{end}}
69
66
70
67
{{ define "contentAfterLeft" }}
71
68
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
74
71
<div class="sticky top-0 flex-grow max-h-screen">
75
72
{{ template "repo/fragments/interdiffFiles" .Interdiff }}
76
73
</div>
77
-
{{ end }}
74
+
{{end}}
+132
-122
appview/pages/templates/repo/pulls/new.html
+132
-122
appview/pages/templates/repo/pulls/new.html
···
1
1
{{ define "title" }}new pull · {{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "repoContent" }}
4
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
5
-
Create new pull request
6
-
</h2>
4
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
5
+
Create new pull request
6
+
</h2>
7
7
8
-
<form
9
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/new"
10
-
hx-indicator="#create-pull-spinner"
11
-
hx-swap="none">
12
-
<div class="flex flex-col gap-6">
13
-
<div class="flex gap-2 items-center">
14
-
<p>First, choose a target branch on {{ .RepoInfo.FullName }}:</p>
15
-
<div>
16
-
<select
17
-
required
18
-
name="targetBranch"
19
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600">
20
-
<option disabled selected>target branch</option>
8
+
<form
9
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/new"
10
+
hx-indicator="#create-pull-spinner"
11
+
hx-swap="none"
12
+
>
13
+
<div class="flex flex-col gap-6">
14
+
<div class="flex gap-2 items-center">
15
+
<p>First, choose a target branch on {{ .RepoInfo.FullName }}:</p>
16
+
<div>
17
+
<select
18
+
required
19
+
name="targetBranch"
20
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
21
+
>
22
+
<option disabled selected>target branch</option>
21
23
22
-
{{ range .Branches }}
23
-
{{ $preset := false }}
24
-
{{ if $.TargetBranch }}
25
-
{{ $preset = eq .Reference.Name $.TargetBranch }}
26
-
{{ else }}
27
-
{{ $preset = .IsDefault }}
28
-
{{ end }}
29
24
25
+
{{ range .Branches }}
30
26
31
-
<option
32
-
value="{{ .Reference.Name }}"
33
-
class="py-1"
34
-
{{ if $preset }}selected{{ end }}>
35
-
{{ .Reference.Name }}
36
-
</option>
37
-
{{ end }}
38
-
</select>
39
-
</div>
40
-
</div>
27
+
{{ $preset := false }}
28
+
{{ if $.TargetBranch }}
29
+
{{ $preset = eq .Reference.Name $.TargetBranch }}
30
+
{{ else }}
31
+
{{ $preset = .IsDefault }}
32
+
{{ end }}
33
+
34
+
<option value="{{ .Reference.Name }}" class="py-1" {{if $preset}}selected{{end}}>
35
+
{{ .Reference.Name }}
36
+
</option>
37
+
{{ end }}
38
+
</select>
39
+
</div>
40
+
</div>
41
41
42
-
<div class="flex flex-col gap-2">
43
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
44
-
Choose pull strategy
45
-
</h2>
46
-
<nav class="flex space-x-4 items-center">
47
-
<button
48
-
type="button"
49
-
class="btn"
50
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/patch-upload"
51
-
hx-target="#patch-strategy"
52
-
hx-swap="innerHTML">
53
-
paste patch
54
-
</button>
42
+
<div class="flex flex-col gap-2">
43
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
44
+
Choose pull strategy
45
+
</h2>
46
+
<nav class="flex space-x-4 items-center">
47
+
<button
48
+
type="button"
49
+
class="btn"
50
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/patch-upload"
51
+
hx-target="#patch-strategy"
52
+
hx-swap="innerHTML"
53
+
>
54
+
paste patch
55
+
</button>
55
56
56
-
{{ if .RepoInfo.Roles.IsPushAllowed }}
57
-
<span class="text-sm text-gray-500 dark:text-gray-400">or</span>
58
-
<button
59
-
type="button"
60
-
class="btn"
61
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-branches"
62
-
hx-target="#patch-strategy"
63
-
hx-swap="innerHTML">
64
-
compare branches
65
-
</button>
66
-
{{ end }}
57
+
{{ if .RepoInfo.Roles.IsPushAllowed }}
58
+
<span class="text-sm text-gray-500 dark:text-gray-400">
59
+
or
60
+
</span>
61
+
<button
62
+
type="button"
63
+
class="btn"
64
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-branches"
65
+
hx-target="#patch-strategy"
66
+
hx-swap="innerHTML"
67
+
>
68
+
compare branches
69
+
</button>
70
+
{{ end }}
67
71
68
72
69
-
<span class="text-sm text-gray-500 dark:text-gray-400">or</span>
70
-
<script>
71
-
function getQueryParams() {
72
-
return Object.fromEntries(
73
-
new URLSearchParams(window.location.search),
74
-
);
75
-
}
76
-
</script>
77
-
<!--
73
+
<span class="text-sm text-gray-500 dark:text-gray-400">
74
+
or
75
+
</span>
76
+
<script>
77
+
function getQueryParams() {
78
+
return Object.fromEntries(new URLSearchParams(window.location.search));
79
+
}
80
+
</script>
81
+
<!--
78
82
since compare-forks need the server to load forks, we
79
83
hx-get this button; unlike simply loading the pullCompareForks template
80
84
as we do for the rest of the gang below. the hx-vals thing just populates
81
85
the query params so the forks page gets it.
82
86
-->
83
-
<button
84
-
type="button"
85
-
class="btn"
86
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-forks"
87
-
hx-target="#patch-strategy"
88
-
hx-swap="innerHTML"
89
-
{{ if eq .Strategy "fork" }}
90
-
hx-trigger="click, load" hx-vals='js:{...getQueryParams()}'
91
-
{{ end }}>
92
-
compare forks
93
-
</button>
94
-
</nav>
95
-
<section id="patch-strategy" class="flex flex-col gap-2">
96
-
{{ if eq .Strategy "patch" }}
97
-
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
98
-
{{ else if eq .Strategy "branch" }}
99
-
{{ template "repo/pulls/fragments/pullCompareBranches" . }}
100
-
{{ else }}
101
-
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
102
-
{{ end }}
103
-
</section>
87
+
<button
88
+
type="button"
89
+
class="btn"
90
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-forks"
91
+
hx-target="#patch-strategy"
92
+
hx-swap="innerHTML"
93
+
{{ if eq .Strategy "fork" }}
94
+
hx-trigger="click, load"
95
+
hx-vals='js:{...getQueryParams()}'
96
+
{{ end }}
97
+
>
98
+
compare forks
99
+
</button>
104
100
105
-
<div id="patch-error" class="error dark:text-red-300"></div>
106
-
</div>
107
101
108
-
<div>
109
-
<label for="title" class="dark:text-white">write a title</label>
102
+
</nav>
103
+
<section id="patch-strategy" class="flex flex-col gap-2">
104
+
{{ if eq .Strategy "patch" }}
105
+
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
106
+
{{ else if eq .Strategy "branch" }}
107
+
{{ template "repo/pulls/fragments/pullCompareBranches" . }}
108
+
{{ else }}
109
+
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
110
+
{{ end }}
111
+
</section>
110
112
111
-
<input
112
-
type="text"
113
-
name="title"
114
-
id="title"
115
-
value="{{ .Title }}"
116
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600"
117
-
placeholder="One-line summary of your change." />
118
-
</div>
113
+
<div id="patch-error" class="error dark:text-red-300"></div>
114
+
</div>
115
+
116
+
<div>
117
+
<label for="title" class="dark:text-white">write a title</label>
118
+
119
+
<input
120
+
type="text"
121
+
name="title"
122
+
id="title"
123
+
value="{{ .Title }}"
124
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600"
125
+
placeholder="One-line summary of your change."
126
+
/>
127
+
</div>
119
128
120
-
<div>
121
-
<label for="body" class="dark:text-white">add a description</label>
129
+
<div>
130
+
<label for="body" class="dark:text-white"
131
+
>add a description</label
132
+
>
122
133
123
-
<textarea
124
-
name="body"
125
-
id="body"
126
-
rows="6"
127
-
class="w-full resize-y dark:bg-gray-700 dark:text-white dark:border-gray-600"
128
-
placeholder="Describe your change. Markdown is supported.">
129
-
{{ .Body }}</textarea
130
-
>
131
-
</div>
134
+
<textarea
135
+
name="body"
136
+
id="body"
137
+
rows="6"
138
+
class="w-full resize-y dark:bg-gray-700 dark:text-white dark:border-gray-600"
139
+
placeholder="Describe your change. Markdown is supported."
140
+
>{{ .Body }}</textarea>
141
+
</div>
132
142
133
-
<div class="flex justify-start items-center gap-2 mt-4">
134
-
<button type="submit" class="btn-create flex items-center gap-2">
135
-
{{ i "git-pull-request-create" "w-4 h-4" }}
136
-
create pull
137
-
<span id="create-pull-spinner" class="group">
138
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
139
-
</span>
140
-
</button>
141
-
</div>
142
-
</div>
143
-
<div id="pull" class="error dark:text-red-300"></div>
144
-
</form>
143
+
<div class="flex justify-start items-center gap-2 mt-4">
144
+
<button type="submit" class="btn-create flex items-center gap-2">
145
+
{{ i "git-pull-request-create" "w-4 h-4" }}
146
+
create pull
147
+
<span id="create-pull-spinner" class="group">
148
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
149
+
</span>
150
+
</button>
151
+
</div>
152
+
</div>
153
+
<div id="pull" class="error dark:text-red-300"></div>
154
+
</form>
145
155
{{ end }}
+34
-39
appview/pages/templates/repo/pulls/patch.html
+34
-39
appview/pages/templates/repo/pulls/patch.html
···
1
1
{{ define "title" }}
2
-
patch of {{ .Pull.Title }} · round #{{ .Round }} · pull
3
-
#{{ .Pull.PullId }} ·
4
-
{{ .RepoInfo.FullName }}
2
+
patch of {{ .Pull.Title }} · round #{{ .Round }} · pull #{{ .Pull.PullId }} · {{ .RepoInfo.FullName }}
5
3
{{ end }}
4
+
6
5
7
6
{{ define "extrameta" }}
8
-
{{ $title := printf "patch of %s · pull #%d · %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
9
-
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
7
+
{{ $title := printf "patch of %s · pull #%d · %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
8
+
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
9
+
10
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
11
+
{{ end }}
10
12
11
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
12
-
{{ end }}
13
13
14
14
{{ define "content" }}
15
-
<section>
15
+
<section>
16
16
<section
17
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
18
-
<div class="flex gap-3 items-center mb-3">
19
-
<a
20
-
href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/"
21
-
class="flex items-center gap-2 font-medium">
22
-
{{ i "arrow-left" "w-5 h-5" }}
23
-
back
24
-
</a>
25
-
<span class="select-none before:content-['\00B7']"></span>
26
-
round
27
-
<span class="flex items-center">
28
-
{{ i "hash" "w-4 h-4" }}{{ .Round }}
29
-
</span>
30
-
<span class="select-none before:content-['\00B7']"></span>
31
-
<a
32
-
href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Round }}.patch">
33
-
view raw
34
-
</a>
35
-
</div>
36
-
<div class="border-t border-gray-200 dark:border-gray-700 my-2"></div>
37
-
{{ template "repo/pulls/fragments/pullHeader" . }}
17
+
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"
18
+
>
19
+
<div class="flex gap-3 items-center mb-3">
20
+
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/" class="flex items-center gap-2 font-medium">
21
+
{{ i "arrow-left" "w-5 h-5" }}
22
+
back
23
+
</a>
24
+
<span class="select-none before:content-['\00B7']"></span>
25
+
round<span class="flex items-center">{{ i "hash" "w-4 h-4" }}{{ .Round }}</span>
26
+
<span class="select-none before:content-['\00B7']"></span>
27
+
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Round }}.patch">
28
+
view raw
29
+
</a>
30
+
</div>
31
+
<div class="border-t border-gray-200 dark:border-gray-700 my-2"></div>
32
+
{{ template "repo/pulls/fragments/pullHeader" . }}
38
33
</section>
39
-
</section>
34
+
</section>
40
35
{{ end }}
41
36
42
37
{{ define "topbarLayout" }}
···
52
47
{{ end }}
53
48
54
49
{{ block "contentAfterLayout" . }}
55
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
56
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
57
-
{{ block "contentAfterLeft" . }}{{ end }}
58
-
</div>
59
-
<main class="col-span-1 md:col-span-10">
60
-
{{ block "contentAfter" . }}{{ end }}
61
-
</main>
50
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
51
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
52
+
{{ block "contentAfterLeft" . }} {{ end }}
62
53
</div>
54
+
<main class="col-span-1 md:col-span-10">
55
+
{{ block "contentAfter" . }}{{ end }}
56
+
</main>
57
+
</div>
63
58
{{ end }}
64
59
</div>
65
60
{{ end }}
···
72
67
73
68
{{ define "contentAfter" }}
74
69
{{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }}
75
-
{{ end }}
70
+
{{end}}
76
71
77
72
{{ define "contentAfterLeft" }}
78
73
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
81
76
<div class="sticky top-0 flex-grow max-h-screen">
82
77
{{ template "repo/fragments/diffChangedFiles" .Diff }}
83
78
</div>
84
-
{{ end }}
79
+
{{end}}
+153
-204
appview/pages/templates/repo/pulls/pull.html
+153
-204
appview/pages/templates/repo/pulls/pull.html
···
1
1
{{ define "title" }}
2
-
{{ .Pull.Title }} · pull #{{ .Pull.PullId }} ·
3
-
{{ .RepoInfo.FullName }}
2
+
{{ .Pull.Title }} · pull #{{ .Pull.PullId }} · {{ .RepoInfo.FullName }}
4
3
{{ end }}
5
4
6
5
{{ define "extrameta" }}
7
-
{{ $title := printf "%s · pull #%d · %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
8
-
{{ $url := printf "https://tangled.sh/%s/pulls/%d" .RepoInfo.FullName .Pull.PullId }}
6
+
{{ $title := printf "%s · pull #%d · %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
7
+
{{ $url := printf "https://tangled.sh/%s/pulls/%d" .RepoInfo.FullName .Pull.PullId }}
9
8
10
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
9
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
11
10
{{ end }}
11
+
12
12
13
13
{{ define "repoContent" }}
14
14
{{ template "repo/pulls/fragments/pullHeader" . }}
···
21
21
{{ end }}
22
22
23
23
{{ define "repoAfter" }}
24
-
<section id="submissions" class="mt-4">
25
-
<div class="flex flex-col gap-4">
26
-
{{ block "submissions" . }}{{ end }}
27
-
</div>
28
-
</section>
24
+
<section id="submissions" class="mt-4">
25
+
<div class="flex flex-col gap-4">
26
+
{{ block "submissions" . }} {{ end }}
27
+
</div>
28
+
</section>
29
29
30
-
<div id="pull-close"></div>
31
-
<div id="pull-reopen"></div>
30
+
<div id="pull-close"></div>
31
+
<div id="pull-reopen"></div>
32
32
{{ end }}
33
33
34
34
{{ define "submissions" }}
···
37
37
{{ $repoName := .RepoInfo.FullName }}
38
38
{{ range $idx, $item := .Pull.Submissions }}
39
39
{{ with $item }}
40
-
<details {{ if eq $idx $lastIdx }}open{{ end }}>
41
-
<summary
42
-
id="round-#{{ .RoundNumber }}"
43
-
class="list-none cursor-pointer">
40
+
<details {{ if eq $idx $lastIdx }}open{{ end }}>
41
+
<summary id="round-#{{ .RoundNumber }}" class="list-none cursor-pointer">
44
42
<div class="flex flex-wrap gap-2 items-center">
45
43
<!-- round number -->
46
-
<div
47
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-3 py-2 dark:text-white">
48
-
<span class="flex items-center">
49
-
{{ i "hash" "w-4 h-4" }}{{ .RoundNumber }}
50
-
</span>
44
+
<div class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-3 py-2 dark:text-white">
45
+
<span class="flex items-center">{{ i "hash" "w-4 h-4" }}{{ .RoundNumber }}</span>
51
46
</div>
52
47
<!-- round summary -->
53
-
<div
54
-
class="rounded drop-shadow-sm bg-white dark:bg-gray-800 p-2 text-gray-500 dark:text-gray-400">
48
+
<div class="rounded drop-shadow-sm bg-white dark:bg-gray-800 p-2 text-gray-500 dark:text-gray-400">
55
49
<span class="gap-1 flex items-center">
56
50
{{ $owner := resolve $.Pull.OwnerDid }}
57
51
{{ $re := "re" }}
58
52
{{ if eq .RoundNumber 0 }}
59
53
{{ $re = "" }}
60
54
{{ end }}
61
-
<span class="hidden md:inline">{{ $re }}submitted</span>
62
-
by
63
-
{{ template "user/fragments/picHandleLink" $.Pull.OwnerDid }}
55
+
<span class="hidden md:inline">{{$re}}submitted</span>
56
+
by {{ template "user/fragments/picHandleLink" $.Pull.OwnerDid }}
64
57
<span class="select-none before:content-['\00B7']"></span>
65
-
<a
66
-
class="text-gray-500 dark:text-gray-400 hover:text-gray-500"
67
-
href="#round-#{{ .RoundNumber }}">
68
-
{{ template "repo/fragments/shortTime" .Created }}
69
-
</a>
58
+
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500" href="#round-#{{ .RoundNumber }}">{{ template "repo/fragments/shortTime" .Created }}</a>
70
59
<span class="select-none before:content-['·']"></span>
71
60
{{ $s := "s" }}
72
61
{{ if eq (len .Comments) 1 }}
73
62
{{ $s = "" }}
74
63
{{ end }}
75
-
{{ len .Comments }}
76
-
comment{{ $s }}
64
+
{{ len .Comments }} comment{{$s}}
77
65
</span>
78
66
</div>
79
67
80
-
<a
81
-
class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
82
-
hx-boost="true"
83
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{ .RoundNumber }}">
68
+
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
69
+
hx-boost="true"
70
+
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}">
84
71
{{ i "file-diff" "w-4 h-4" }}
85
72
<span class="hidden md:inline">diff</span>
86
73
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
87
74
</a>
88
75
{{ if not (eq .RoundNumber 0) }}
89
-
<a
90
-
class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
91
-
hx-boost="true"
92
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{ .RoundNumber }}/interdiff">
93
-
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
94
-
<span class="hidden md:inline">interdiff</span>
95
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
96
-
</a>
97
-
<span id="interdiff-error-{{ .RoundNumber }}"></span>
76
+
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
77
+
hx-boost="true"
78
+
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}/interdiff">
79
+
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
80
+
<span class="hidden md:inline">interdiff</span>
81
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
82
+
</a>
83
+
<span id="interdiff-error-{{.RoundNumber}}"></span>
98
84
{{ end }}
99
85
</div>
100
86
</summary>
101
87
102
88
{{ if .IsFormatPatch }}
103
-
{{ $patches := .AsFormatPatch }}
104
-
{{ $round := .RoundNumber }}
105
-
<details
106
-
class="group py-2 md:ml-[3.5rem] text-gray-500 dark:text-gray-400 flex flex-col gap-2 relative text-sm">
107
-
<summary
108
-
class="py-1 list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
109
-
{{ $s := "s" }}
110
-
{{ if eq (len $patches) 1 }}
111
-
{{ $s = "" }}
112
-
{{ end }}
113
-
<div class="group-open:hidden flex items-center gap-2 ml-2">
114
-
{{ i "chevrons-up-down" "w-4 h-4" }} expand
115
-
{{ len $patches }}
116
-
commit{{ $s }}
117
-
</div>
118
-
<div class="hidden group-open:flex items-center gap-2 ml-2">
119
-
{{ i "chevrons-down-up" "w-4 h-4" }} hide
120
-
{{ len $patches }}
121
-
commit{{ $s }}
122
-
</div>
123
-
</summary>
124
-
{{ range $patches }}
125
-
<div
126
-
id="commit-{{ .SHA }}"
127
-
class="py-1 px-2 relative w-full md:max-w-3/5 md:w-fit flex flex-col">
128
-
<div class="flex items-center gap-2">
129
-
{{ i "git-commit-horizontal" "w-4 h-4" }}
130
-
<div class="text-sm text-gray-500 dark:text-gray-400">
131
-
<!-- attempt to resolve $fullRepo: this is possible only on non-deleted forks and branches -->
132
-
{{ $fullRepo := "" }}
133
-
{{ if and $.Pull.IsForkBased $.Pull.PullSource.Repo }}
134
-
{{ $fullRepo = printf "%s/%s" $owner $.Pull.PullSource.Repo.Name }}
135
-
{{ else if $.Pull.IsBranchBased }}
136
-
{{ $fullRepo = $.RepoInfo.FullName }}
137
-
{{ end }}
89
+
{{ $patches := .AsFormatPatch }}
90
+
{{ $round := .RoundNumber }}
91
+
<details class="group py-2 md:ml-[3.5rem] text-gray-500 dark:text-gray-400 flex flex-col gap-2 relative text-sm">
92
+
<summary class="py-1 list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
93
+
{{ $s := "s" }}
94
+
{{ if eq (len $patches) 1 }}
95
+
{{ $s = "" }}
96
+
{{ end }}
97
+
<div class="group-open:hidden flex items-center gap-2 ml-2">
98
+
{{ i "chevrons-up-down" "w-4 h-4" }} expand {{ len $patches }} commit{{$s}}
99
+
</div>
100
+
<div class="hidden group-open:flex items-center gap-2 ml-2">
101
+
{{ i "chevrons-down-up" "w-4 h-4" }} hide {{ len $patches }} commit{{$s}}
102
+
</div>
103
+
</summary>
104
+
{{ range $patches }}
105
+
<div id="commit-{{.SHA}}" class="py-1 px-2 relative w-full md:max-w-3/5 md:w-fit flex flex-col">
106
+
<div class="flex items-center gap-2">
107
+
{{ i "git-commit-horizontal" "w-4 h-4" }}
108
+
<div class="text-sm text-gray-500 dark:text-gray-400">
109
+
<!-- attempt to resolve $fullRepo: this is possible only on non-deleted forks and branches -->
110
+
{{ $fullRepo := "" }}
111
+
{{ if and $.Pull.IsForkBased $.Pull.PullSource.Repo }}
112
+
{{ $fullRepo = printf "%s/%s" $owner $.Pull.PullSource.Repo.Name }}
113
+
{{ else if $.Pull.IsBranchBased }}
114
+
{{ $fullRepo = $.RepoInfo.FullName }}
115
+
{{ end }}
138
116
139
-
140
-
<!-- if $fullRepo was resolved, link to it, otherwise just span without a link -->
141
-
{{ if $fullRepo }}
142
-
<a
143
-
href="/{{ $fullRepo }}/commit/{{ .SHA }}"
144
-
class="font-mono text-gray-500 dark:text-gray-400">
145
-
{{ slice .SHA 0 8 }}
146
-
</a>
147
-
{{ else }}
148
-
<span class="font-mono">{{ slice .SHA 0 8 }}</span>
149
-
{{ end }}
150
-
</div>
151
-
<div class="flex items-center">
152
-
<span>{{ .Title }}</span>
153
-
{{ if gt (len .Body) 0 }}
154
-
<button
155
-
class="py-1/2 px-1 mx-2 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
156
-
hx-on:click="document.getElementById('body-{{ $round }}-{{ .SHA }}').classList.toggle('hidden')">
157
-
{{ i "ellipsis" "w-3 h-3" }}
158
-
</button>
159
-
{{ end }}
160
-
</div>
161
-
</div>
162
-
{{ if gt (len .Body) 0 }}
163
-
<p
164
-
id="body-{{ $round }}-{{ .SHA }}"
165
-
class="hidden mt-1 text-sm pb-2">
166
-
{{ nl2br .Body }}
167
-
</p>
168
-
{{ end }}
169
-
</div>
170
-
{{ end }}
171
-
</details>
117
+
<!-- if $fullRepo was resolved, link to it, otherwise just span without a link -->
118
+
{{ if $fullRepo }}
119
+
<a href="/{{ $fullRepo }}/commit/{{ .SHA }}" class="font-mono text-gray-500 dark:text-gray-400">{{ slice .SHA 0 8 }}</a>
120
+
{{ else }}
121
+
<span class="font-mono">{{ slice .SHA 0 8 }}</span>
122
+
{{ end }}
123
+
</div>
124
+
<div class="flex items-center">
125
+
<span>{{ .Title }}</span>
126
+
{{ if gt (len .Body) 0 }}
127
+
<button
128
+
class="py-1/2 px-1 mx-2 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
129
+
hx-on:click="document.getElementById('body-{{$round}}-{{.SHA}}').classList.toggle('hidden')"
130
+
>
131
+
{{ i "ellipsis" "w-3 h-3" }}
132
+
</button>
133
+
{{ end }}
134
+
</div>
135
+
</div>
136
+
{{ if gt (len .Body) 0 }}
137
+
<p id="body-{{$round}}-{{.SHA}}" class="hidden mt-1 text-sm pb-2">
138
+
{{ nl2br .Body }}
139
+
</p>
140
+
{{ end }}
141
+
</div>
142
+
{{ end }}
143
+
</details>
172
144
{{ end }}
173
145
174
146
175
147
<div class="md:pl-[3.5rem] flex flex-col gap-2 mt-2 relative">
176
148
{{ range $cidx, $c := .Comments }}
177
-
<div
178
-
id="comment-{{ $c.ID }}"
179
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-2 px-4 relative w-full md:max-w-3/5 md:w-fit">
149
+
<div id="comment-{{$c.ID}}" class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-2 px-4 relative w-full md:max-w-3/5 md:w-fit">
180
150
{{ if gt $cidx 0 }}
181
-
<div
182
-
class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
151
+
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
183
152
{{ end }}
184
-
<div
185
-
class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
153
+
<div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
186
154
{{ template "user/fragments/picHandleLink" $c.OwnerDid }}
187
155
<span class="before:content-['·']"></span>
188
-
<a
189
-
class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
190
-
href="#comment-{{ .ID }}">
191
-
{{ template "repo/fragments/time" $c.Created }}
192
-
</a>
156
+
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="#comment-{{.ID}}">{{ template "repo/fragments/time" $c.Created }}</a>
193
157
</div>
194
158
<div class="prose dark:prose-invert">
195
159
{{ $c.Body | markdown }}
···
197
161
</div>
198
162
{{ end }}
199
163
200
-
{{ block "pipelineStatus" (list $ .) }}{{ end }}
164
+
{{ block "pipelineStatus" (list $ .) }} {{ end }}
201
165
202
166
{{ if eq $lastIdx .RoundNumber }}
203
-
{{ block "mergeStatus" $ }}{{ end }}
204
-
{{ block "resubmitStatus" $ }}{{ end }}
167
+
{{ block "mergeStatus" $ }} {{ end }}
168
+
{{ block "resubmitStatus" $ }} {{ end }}
205
169
{{ end }}
206
170
207
171
{{ if $.LoggedInUser }}
208
172
{{ template "repo/pulls/fragments/pullActions" (dict "LoggedInUser" $.LoggedInUser "Pull" $.Pull "RepoInfo" $.RepoInfo "RoundNumber" .RoundNumber "MergeCheck" $.MergeCheck "ResubmitCheck" $.ResubmitCheck "Stack" $.Stack) }}
209
173
{{ else }}
210
-
<div
211
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm px-6 py-4 w-fit dark:text-white">
212
-
<div
213
-
class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
214
-
<a href="/login" class="underline">login</a>
215
-
to join the discussion
174
+
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm px-6 py-4 w-fit dark:text-white">
175
+
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
176
+
<a href="/login" class="underline">login</a> to join the discussion
216
177
</div>
217
178
{{ end }}
218
179
</div>
219
-
</details>
180
+
</details>
220
181
{{ end }}
221
182
{{ end }}
222
183
{{ end }}
223
184
224
185
{{ define "mergeStatus" }}
225
186
{{ if .Pull.State.IsClosed }}
226
-
<div
227
-
class="bg-gray-50 dark:bg-gray-700 border border-black dark:border-gray-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
228
-
<div class="flex items-center gap-2 text-black dark:text-white">
229
-
{{ i "ban" "w-4 h-4" }}
230
-
<span class="font-medium">closed without merging</span>
231
-
</div>
187
+
<div class="bg-gray-50 dark:bg-gray-700 border border-black dark:border-gray-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
188
+
<div class="flex items-center gap-2 text-black dark:text-white">
189
+
{{ i "ban" "w-4 h-4" }}
190
+
<span class="font-medium">closed without merging</span
191
+
>
232
192
</div>
193
+
</div>
233
194
{{ else if .Pull.State.IsMerged }}
234
-
<div
235
-
class="bg-purple-50 dark:bg-purple-900 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
236
-
<div class="flex items-center gap-2 text-purple-500 dark:text-purple-300">
237
-
{{ i "git-merge" "w-4 h-4" }}
238
-
<span class="font-medium">pull request successfully merged</span>
239
-
</div>
195
+
<div class="bg-purple-50 dark:bg-purple-900 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
196
+
<div class="flex items-center gap-2 text-purple-500 dark:text-purple-300">
197
+
{{ i "git-merge" "w-4 h-4" }}
198
+
<span class="font-medium">pull request successfully merged</span
199
+
>
240
200
</div>
201
+
</div>
241
202
{{ else if .Pull.State.IsDeleted }}
242
-
<div
243
-
class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
244
-
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
245
-
{{ i "git-pull-request-closed" "w-4 h-4" }}
246
-
<span class="font-medium">
247
-
This pull has been deleted (possibly by jj abandon or jj squash)
248
-
</span>
249
-
</div>
203
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
204
+
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
205
+
{{ i "git-pull-request-closed" "w-4 h-4" }}
206
+
<span class="font-medium">This pull has been deleted (possibly by jj abandon or jj squash)</span>
250
207
</div>
208
+
</div>
251
209
{{ else if and .MergeCheck .MergeCheck.Error }}
252
-
<div
253
-
class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
210
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
254
211
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
255
212
{{ i "triangle-alert" "w-4 h-4" }}
256
213
<span class="font-medium">{{ .MergeCheck.Error }}</span>
257
214
</div>
258
215
</div>
259
216
{{ else if and .MergeCheck .MergeCheck.IsConflicted }}
260
-
<div
261
-
class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
217
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
262
218
<div class="flex flex-col gap-2 text-red-500 dark:text-red-300">
263
219
<div class="flex items-center gap-2">
264
220
{{ i "triangle-alert" "w-4 h-4" }}
···
268
224
<ul class="space-y-1">
269
225
{{ range .MergeCheck.Conflicts }}
270
226
{{ if .Filename }}
271
-
<li class="flex items-center">
272
-
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
273
-
<span class="font-mono">{{ .Filename }}</span>
274
-
</li>
227
+
<li class="flex items-center">
228
+
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
229
+
<span class="font-mono">{{ .Filename }}</span>
230
+
</li>
275
231
{{ else if .Reason }}
276
-
<li class="flex items-center">
277
-
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
278
-
<span>{{ .Reason }}</span>
279
-
</li>
232
+
<li class="flex items-center">
233
+
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
234
+
<span>{{.Reason}}</span>
235
+
</li>
280
236
{{ end }}
281
237
{{ end }}
282
238
</ul>
···
284
240
</div>
285
241
</div>
286
242
{{ else if .MergeCheck }}
287
-
<div
288
-
class="bg-green-50 dark:bg-green-900 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
289
-
<div class="flex items-center gap-2 text-green-500 dark:text-green-300">
290
-
{{ i "circle-check-big" "w-4 h-4" }}
291
-
<span class="font-medium">no conflicts, ready to merge</span>
292
-
</div>
243
+
<div class="bg-green-50 dark:bg-green-900 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
244
+
<div class="flex items-center gap-2 text-green-500 dark:text-green-300">
245
+
{{ i "circle-check-big" "w-4 h-4" }}
246
+
<span class="font-medium">no conflicts, ready to merge</span>
293
247
</div>
248
+
</div>
294
249
{{ end }}
295
250
{{ end }}
296
251
297
252
{{ define "resubmitStatus" }}
298
253
{{ if .ResubmitCheck.Yes }}
299
-
<div
300
-
class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
301
-
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
302
-
{{ i "triangle-alert" "w-4 h-4" }}
303
-
<span class="font-medium">
304
-
this branch has been updated, consider resubmitting
305
-
</span>
306
-
</div>
254
+
<div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
255
+
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
256
+
{{ i "triangle-alert" "w-4 h-4" }}
257
+
<span class="font-medium">this branch has been updated, consider resubmitting</span>
307
258
</div>
259
+
</div>
308
260
{{ end }}
309
261
{{ end }}
310
262
···
315
267
{{ with $pipeline }}
316
268
{{ $id := .Id }}
317
269
{{ if .Statuses }}
318
-
<div
319
-
class="max-w-80 grid grid-cols-1 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
270
+
<div class="max-w-80 grid grid-cols-1 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
320
271
{{ range $name, $all := .Statuses }}
321
-
<a
322
-
href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}"
323
-
class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
324
-
<div class="flex gap-2 items-center justify-between p-2">
325
-
{{ $lastStatus := $all.Latest }}
326
-
{{ $kind := $lastStatus.Status.String }}
272
+
<a href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
273
+
<div
274
+
class="flex gap-2 items-center justify-between p-2">
275
+
{{ $lastStatus := $all.Latest }}
276
+
{{ $kind := $lastStatus.Status.String }}
327
277
328
-
329
-
<div id="left" class="flex items-center gap-2 flex-shrink-0">
330
-
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
331
-
{{ $name }}
332
-
</div>
333
-
<div id="right" class="flex items-center gap-2 flex-shrink-0">
334
-
<span class="font-bold">{{ $kind }}</span>
335
-
{{ if .TimeTaken }}
336
-
{{ template "repo/fragments/duration" .TimeTaken }}
337
-
{{ else }}
338
-
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
339
-
{{ end }}
340
-
</div>
278
+
<div id="left" class="flex items-center gap-2 flex-shrink-0">
279
+
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
280
+
{{ $name }}
341
281
</div>
342
-
</a>
282
+
<div id="right" class="flex items-center gap-2 flex-shrink-0">
283
+
<span class="font-bold">{{ $kind }}</span>
284
+
{{ if .TimeTaken }}
285
+
{{ template "repo/fragments/duration" .TimeTaken }}
286
+
{{ else }}
287
+
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
288
+
{{ end }}
289
+
</div>
290
+
</div>
291
+
</a>
343
292
{{ end }}
344
293
</div>
345
294
{{ end }}
+113
-132
appview/pages/templates/repo/pulls/pulls.html
+113
-132
appview/pages/templates/repo/pulls/pulls.html
···
1
1
{{ define "title" }}pulls · {{ .RepoInfo.FullName }}{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
{{ $title := "pulls" }}
5
-
{{ $url := printf "https://tangled.sh/%s/pulls" .RepoInfo.FullName }}
4
+
{{ $title := "pulls"}}
5
+
{{ $url := printf "https://tangled.sh/%s/pulls" .RepoInfo.FullName }}
6
6
7
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
7
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
8
8
{{ end }}
9
9
10
10
{{ define "repoContent" }}
11
-
<div class="flex justify-between items-center">
12
-
<div class="flex gap-4">
13
-
<a
14
-
href="?state=open"
15
-
class="flex items-center gap-2 {{ if .FilteringBy.IsOpen }}
16
-
font-bold
17
-
{{ else }}
18
-
text-gray-500 dark:text-gray-400
19
-
{{ end }}">
20
-
{{ i "git-pull-request" "w-4 h-4" }}
21
-
<span>{{ .RepoInfo.Stats.PullCount.Open }} open</span>
22
-
</a>
23
-
<a
24
-
href="?state=merged"
25
-
class="flex items-center gap-2 {{ if .FilteringBy.IsMerged }}
26
-
font-bold
27
-
{{ else }}
28
-
text-gray-500 dark:text-gray-400
29
-
{{ end }}">
30
-
{{ i "git-merge" "w-4 h-4" }}
31
-
<span>{{ .RepoInfo.Stats.PullCount.Merged }} merged</span>
32
-
</a>
33
-
<a
34
-
href="?state=closed"
35
-
class="flex items-center gap-2 {{ if .FilteringBy.IsClosed }}
36
-
font-bold
37
-
{{ else }}
38
-
text-gray-500 dark:text-gray-400
39
-
{{ end }}">
40
-
{{ i "ban" "w-4 h-4" }}
41
-
<span>{{ .RepoInfo.Stats.PullCount.Closed }} closed</span>
42
-
</a>
11
+
<div class="flex justify-between items-center">
12
+
<div class="flex gap-4">
13
+
<a
14
+
href="?state=open"
15
+
class="flex items-center gap-2 {{ if .FilteringBy.IsOpen }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
16
+
>
17
+
{{ i "git-pull-request" "w-4 h-4" }}
18
+
<span>{{ .RepoInfo.Stats.PullCount.Open }} open</span>
19
+
</a>
20
+
<a
21
+
href="?state=merged"
22
+
class="flex items-center gap-2 {{ if .FilteringBy.IsMerged }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
23
+
>
24
+
{{ i "git-merge" "w-4 h-4" }}
25
+
<span>{{ .RepoInfo.Stats.PullCount.Merged }} merged</span>
26
+
</a>
27
+
<a
28
+
href="?state=closed"
29
+
class="flex items-center gap-2 {{ if .FilteringBy.IsClosed }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
30
+
>
31
+
{{ i "ban" "w-4 h-4" }}
32
+
<span>{{ .RepoInfo.Stats.PullCount.Closed }} closed</span>
33
+
</a>
34
+
</div>
35
+
<a
36
+
href="/{{ .RepoInfo.FullName }}/pulls/new"
37
+
class="btn-create text-sm flex items-center gap-2 no-underline hover:no-underline hover:text-white"
38
+
>
39
+
{{ i "git-pull-request-create" "w-4 h-4" }}
40
+
<span>new</span>
41
+
</a>
43
42
</div>
44
-
<a
45
-
href="/{{ .RepoInfo.FullName }}/pulls/new"
46
-
class="btn-create text-sm flex items-center gap-2 no-underline hover:no-underline hover:text-white">
47
-
{{ i "git-pull-request-create" "w-4 h-4" }}
48
-
<span>new</span>
49
-
</a>
50
-
</div>
51
-
<div class="error" id="pulls"></div>
43
+
<div class="error" id="pulls"></div>
52
44
{{ end }}
53
45
54
46
{{ define "repoAfter" }}
55
-
<div class="flex flex-col gap-2 mt-2">
56
-
{{ range .Pulls }}
57
-
<div class="rounded bg-white dark:bg-gray-800">
58
-
<div class="px-6 py-4 z-5">
59
-
<div class="pb-2">
60
-
<a
61
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ .PullId }}"
62
-
class="dark:text-white">
63
-
{{ .Title }}
64
-
<span class="text-gray-500 dark:text-gray-400">
65
-
#{{ .PullId }}
66
-
</span>
67
-
</a>
68
-
</div>
69
-
<div
70
-
class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
71
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
72
-
{{ $icon := "ban" }}
47
+
<div class="flex flex-col gap-2 mt-2">
48
+
{{ range .Pulls }}
49
+
<div class="rounded bg-white dark:bg-gray-800">
50
+
<div class="px-6 py-4 z-5">
51
+
<div class="pb-2">
52
+
<a href="/{{ $.RepoInfo.FullName }}/pulls/{{ .PullId }}" class="dark:text-white">
53
+
{{ .Title }}
54
+
<span class="text-gray-500 dark:text-gray-400">#{{ .PullId }}</span>
55
+
</a>
56
+
</div>
57
+
<div class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
58
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
59
+
{{ $icon := "ban" }}
73
60
74
-
{{ if .State.IsOpen }}
75
-
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
76
-
{{ $icon = "git-pull-request" }}
77
-
{{ else if .State.IsMerged }}
78
-
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
79
-
{{ $icon = "git-merge" }}
80
-
{{ end }}
61
+
{{ if .State.IsOpen }}
62
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
63
+
{{ $icon = "git-pull-request" }}
64
+
{{ else if .State.IsMerged }}
65
+
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
66
+
{{ $icon = "git-merge" }}
67
+
{{ end }}
81
68
82
69
83
-
<span
84
-
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
85
-
{{ i $icon "w-3 h-3 mr-1.5 text-white" }}
86
-
<span class="text-white">{{ .State.String }}</span>
87
-
</span>
70
+
<span
71
+
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm"
72
+
>
73
+
{{ i $icon "w-3 h-3 mr-1.5 text-white" }}
74
+
<span class="text-white">{{ .State.String }}</span>
75
+
</span>
88
76
89
-
<span class="ml-1">
90
-
{{ template "user/fragments/picHandleLink" .OwnerDid }}
91
-
</span>
77
+
<span class="ml-1">
78
+
{{ template "user/fragments/picHandleLink" .OwnerDid }}
79
+
</span>
92
80
93
-
<span class="before:content-['·']">
94
-
{{ template "repo/fragments/time" .Created }}
95
-
</span>
81
+
<span class="before:content-['·']">
82
+
{{ template "repo/fragments/time" .Created }}
83
+
</span>
96
84
97
-
{{ $latestRound := .LastRoundNumber }}
98
-
{{ $lastSubmission := index .Submissions $latestRound }}
99
85
86
+
{{ $latestRound := .LastRoundNumber }}
87
+
{{ $lastSubmission := index .Submissions $latestRound }}
100
88
101
-
<span class="before:content-['·']">
102
-
{{ $commentCount := len $lastSubmission.Comments }}
103
-
{{ $s := "s" }}
104
-
{{ if eq $commentCount 1 }}
105
-
{{ $s = "" }}
106
-
{{ end }}
89
+
<span class="before:content-['·']">
90
+
{{ $commentCount := len $lastSubmission.Comments }}
91
+
{{ $s := "s" }}
92
+
{{ if eq $commentCount 1 }}
93
+
{{ $s = "" }}
94
+
{{ end }}
107
95
108
-
{{ len $lastSubmission.Comments }}
109
-
comment{{ $s }}
110
-
</span>
96
+
{{ len $lastSubmission.Comments}} comment{{$s}}
97
+
</span>
111
98
112
-
<span class="before:content-['·']">
113
-
round
114
-
<span class="font-mono">
115
-
#{{ .LastRoundNumber }}
116
-
</span>
117
-
</span>
99
+
<span class="before:content-['·']">
100
+
round
101
+
<span class="font-mono">
102
+
#{{ .LastRoundNumber }}
103
+
</span>
104
+
</span>
118
105
119
-
{{ $pipeline := index $.Pipelines .LatestSha }}
120
-
{{ if and $pipeline $pipeline.Id }}
121
-
<span class="before:content-['·']"></span>
122
-
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
123
-
{{ end }}
124
-
</div>
125
-
</div>
126
-
{{ if .StackId }}
127
-
{{ $otherPulls := index $.Stacks .StackId }}
128
-
{{ if gt (len $otherPulls) 0 }}
129
-
<details class="bg-white dark:bg-gray-800 group">
130
-
<summary
131
-
class="pb-4 px-6 text-xs list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
132
-
{{ $s := "s" }}
133
-
{{ if eq (len $otherPulls) 1 }}
134
-
{{ $s = "" }}
106
+
{{ $pipeline := index $.Pipelines .LatestSha }}
107
+
{{ if and $pipeline $pipeline.Id }}
108
+
<span class="before:content-['·']"></span>
109
+
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
110
+
{{ end }}
111
+
</div>
112
+
</div>
113
+
{{ if .StackId }}
114
+
{{ $otherPulls := index $.Stacks .StackId }}
115
+
{{ if gt (len $otherPulls) 0 }}
116
+
<details class="bg-white dark:bg-gray-800 group">
117
+
<summary class="pb-4 px-6 text-xs list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
118
+
{{ $s := "s" }}
119
+
{{ if eq (len $otherPulls) 1 }}
120
+
{{ $s = "" }}
121
+
{{ end }}
122
+
<div class="group-open:hidden flex items-center gap-2">
123
+
{{ i "chevrons-up-down" "w-4 h-4" }} expand {{ len $otherPulls }} pull{{$s}} in this stack
124
+
</div>
125
+
<div class="hidden group-open:flex items-center gap-2">
126
+
{{ i "chevrons-down-up" "w-4 h-4" }} hide {{ len $otherPulls }} pull{{$s}} in this stack
127
+
</div>
128
+
</summary>
129
+
{{ block "pullList" (list $otherPulls $) }} {{ end }}
130
+
</details>
135
131
{{ end }}
136
-
<div class="group-open:hidden flex items-center gap-2">
137
-
{{ i "chevrons-up-down" "w-4 h-4" }} expand
138
-
{{ len $otherPulls }} pull{{ $s }} in this stack
139
-
</div>
140
-
<div class="hidden group-open:flex items-center gap-2">
141
-
{{ i "chevrons-down-up" "w-4 h-4" }} hide
142
-
{{ len $otherPulls }} pull{{ $s }} in this stack
143
-
</div>
144
-
</summary>
145
-
{{ block "pullList" (list $otherPulls $) }}{{ end }}
146
-
</details>
147
-
{{ end }}
132
+
{{ end }}
133
+
</div>
148
134
{{ end }}
149
-
</div>
150
-
{{ end }}
151
-
</div>
135
+
</div>
152
136
{{ end }}
153
137
154
138
{{ define "pullList" }}
155
139
{{ $list := index . 0 }}
156
140
{{ $root := index . 1 }}
157
-
<div
158
-
class="grid grid-cols-1 rounded-b border-b border-t border-gray-200 dark:border-gray-900 divide-y divide-gray-200 dark:divide-gray-900">
141
+
<div class="grid grid-cols-1 rounded-b border-b border-t border-gray-200 dark:border-gray-900 divide-y divide-gray-200 dark:divide-gray-900">
159
142
{{ range $pull := $list }}
160
143
{{ $pipeline := index $root.Pipelines $pull.LatestSha }}
161
-
<a
162
-
href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $pull.PullId }}"
163
-
class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
144
+
<a href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $pull.PullId }}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
164
145
<div class="flex gap-2 items-center px-6">
165
146
<div class="flex-grow min-w-0 w-full py-2">
166
147
{{ template "repo/pulls/fragments/summarizedHeader" (list $pull $pipeline) }}
+39
-45
appview/pages/templates/repo/settings/access.html
+39
-45
appview/pages/templates/repo/settings/access.html
···
1
-
{{ define "title" }}
2
-
{{ .Tab }} settings ·
3
-
{{ .RepoInfo.FullName }}
4
-
{{ end }}
1
+
{{ define "title" }}{{ .Tab }} settings · {{ .RepoInfo.FullName }}{{ end }}
5
2
6
3
{{ define "repoContent" }}
7
4
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2">
···
19
16
<div class="col-span-1">
20
17
<h2 class="text-sm pb-2 uppercase font-bold">Collaborators</h2>
21
18
<p class="text-gray-500 dark:text-gray-400">
22
-
Any user added as a collaborator will be able to push commits and tags
23
-
to this repository, upload releases, and workflows.
19
+
Any user added as a collaborator will be able to push commits and tags to this repository, upload releases, and workflows.
24
20
</p>
25
21
</div>
26
22
{{ template "collaboratorsGrid" . }}
···
38
34
<img
39
35
src="{{ fullAvatar .Handle }}"
40
36
alt="{{ .Handle }}"
41
-
class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0" />
37
+
class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0"/>
42
38
43
39
<div class="flex-1 min-w-0">
44
40
<a href="/{{ .Handle }}" class="block truncate">
···
58
54
popovertarget="add-collaborator-modal"
59
55
popovertargetaction="toggle">
60
56
<div class="flex items-center gap-3">
61
-
<div
62
-
class="w-10 h-10 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center">
57
+
<div class="w-10 h-10 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center">
63
58
{{ i "user-plus" "size-4" }}
64
59
</div>
65
60
···
77
72
{{ end }}
78
73
79
74
{{ define "addCollaboratorModal" }}
80
-
<form
81
-
hx-put="/{{ $.RepoInfo.FullName }}/settings/collaborator"
82
-
hx-indicator="#spinner"
83
-
hx-swap="none"
84
-
class="flex flex-col gap-2">
85
-
<label for="add-collaborator" class="uppercase p-0">ADD COLLABORATOR</label>
86
-
<p class="text-sm text-gray-500 dark:text-gray-400">
87
-
Collaborators can push to this repository.
88
-
</p>
89
-
<input
90
-
type="text"
91
-
id="add-collaborator"
92
-
name="collaborator"
93
-
required
94
-
placeholder="@foo.bsky.social" />
95
-
<div class="flex gap-2 pt-2">
96
-
<button
97
-
type="button"
98
-
popovertarget="add-collaborator-modal"
99
-
popovertargetaction="hide"
100
-
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
101
-
{{ i "x" "size-4" }} cancel
102
-
</button>
103
-
<button type="submit" class="btn w-1/2 flex items-center">
104
-
<span class="inline-flex gap-2 items-center">
105
-
{{ i "user-plus" "size-4" }} add
106
-
</span>
107
-
<span id="spinner" class="group">
108
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
109
-
</span>
110
-
</button>
111
-
</div>
112
-
<div
113
-
id="add-collaborator-error"
114
-
class="text-red-500 dark:text-red-400"></div>
115
-
</form>
75
+
<form
76
+
hx-put="/{{ $.RepoInfo.FullName }}/settings/collaborator"
77
+
hx-indicator="#spinner"
78
+
hx-swap="none"
79
+
class="flex flex-col gap-2"
80
+
>
81
+
<label for="add-collaborator" class="uppercase p-0">
82
+
ADD COLLABORATOR
83
+
</label>
84
+
<p class="text-sm text-gray-500 dark:text-gray-400">Collaborators can push to this repository.</p>
85
+
<input
86
+
type="text"
87
+
id="add-collaborator"
88
+
name="collaborator"
89
+
required
90
+
placeholder="@foo.bsky.social"
91
+
/>
92
+
<div class="flex gap-2 pt-2">
93
+
<button
94
+
type="button"
95
+
popovertarget="add-collaborator-modal"
96
+
popovertargetaction="hide"
97
+
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
98
+
>
99
+
{{ i "x" "size-4" }} cancel
100
+
</button>
101
+
<button type="submit" class="btn w-1/2 flex items-center">
102
+
<span class="inline-flex gap-2 items-center">{{ i "user-plus" "size-4" }} add</span>
103
+
<span id="spinner" class="group">
104
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
105
+
</span>
106
+
</button>
107
+
</div>
108
+
<div id="add-collaborator-error" class="text-red-500 dark:text-red-400"></div>
109
+
</form>
116
110
{{ end }}
+8
-15
appview/pages/templates/repo/settings/fragments/secretListing.html
+8
-15
appview/pages/templates/repo/settings/fragments/secretListing.html
···
1
1
{{ define "repo/settings/fragments/secretListing" }}
2
2
{{ $root := index . 0 }}
3
3
{{ $secret := index . 1 }}
4
-
<div
5
-
id="secret-{{ $secret.Key }}"
6
-
class="flex items-center justify-between p-2">
7
-
<div
8
-
class="hover:no-underline flex flex-col gap-1 text-sm min-w-0 max-w-[80%]">
4
+
<div id="secret-{{$secret.Key}}" class="flex items-center justify-between p-2">
5
+
<div class="hover:no-underline flex flex-col gap-1 text-sm min-w-0 max-w-[80%]">
9
6
<span class="font-mono">
10
7
{{ $secret.Key }}
11
8
</span>
12
-
<div
13
-
class="flex flex-wrap text items-center gap-1 text-gray-500 dark:text-gray-400">
9
+
<div class="flex flex-wrap text items-center gap-1 text-gray-500 dark:text-gray-400">
14
10
<span>added by</span>
15
-
<span>
16
-
{{ template "user/fragments/picHandleLink" $secret.CreatedBy }}
17
-
</span>
11
+
<span>{{ template "user/fragments/picHandleLink" $secret.CreatedBy }}</span>
18
12
<span class="before:content-['·'] before:select-none"></span>
19
-
<span>
20
-
{{ template "repo/fragments/shortTimeAgo" $secret.CreatedAt }}
21
-
</span>
13
+
<span>{{ template "repo/fragments/shortTimeAgo" $secret.CreatedAt }}</span>
22
14
</div>
23
15
</div>
24
16
<button
···
27
19
hx-delete="/{{ $root.RepoInfo.FullName }}/settings/secrets"
28
20
hx-swap="none"
29
21
hx-vals='{"key": "{{ $secret.Key }}"}'
30
-
hx-confirm="Are you sure you want to delete the secret {{ $secret.Key }}?">
22
+
hx-confirm="Are you sure you want to delete the secret {{ $secret.Key }}?"
23
+
>
31
24
{{ i "trash-2" "w-5 h-5" }}
32
-
<span class="hidden md:inline">delete</span>
25
+
<span class="hidden md:inline">delete</span>
33
26
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
34
27
</button>
35
28
</div>
+23
-38
appview/pages/templates/repo/settings/general.html
+23
-38
appview/pages/templates/repo/settings/general.html
···
1
-
{{ define "title" }}
2
-
{{ .Tab }} settings ·
3
-
{{ .RepoInfo.FullName }}
4
-
{{ end }}
1
+
{{ define "title" }}{{ .Tab }} settings · {{ .RepoInfo.FullName }}{{ end }}
5
2
6
3
{{ define "repoContent" }}
7
4
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2">
···
25
22
unless you specify a different branch.
26
23
</p>
27
24
</div>
28
-
<form
29
-
hx-put="/{{ $.RepoInfo.FullName }}/settings/branches/default"
30
-
class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
31
-
<select
32
-
id="branch"
33
-
name="branch"
34
-
required
35
-
class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
36
-
<option value="" disabled selected>Choose a default branch</option>
25
+
<form hx-put="/{{ $.RepoInfo.FullName }}/settings/branches/default" class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
26
+
<select id="branch" name="branch" required class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
27
+
<option value="" disabled selected >
28
+
Choose a default branch
29
+
</option>
37
30
{{ range .Branches }}
38
-
<option
39
-
value="{{ .Name }}"
40
-
class="py-1"
41
-
{{ if .IsDefault }}selected{{ end }}>
31
+
<option value="{{ .Name }}" class="py-1" {{ if .IsDefault }}selected{{ end }} >
42
32
{{ .Name }}
43
33
</option>
44
34
{{ end }}
···
53
43
54
44
{{ define "deleteRepo" }}
55
45
{{ if .RepoInfo.Roles.RepoDeleteAllowed }}
56
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
57
-
<div class="col-span-1 md:col-span-2">
58
-
<h2
59
-
class="text-sm pb-2 uppercase text-red-500 dark:text-red-400 font-bold">
60
-
Delete Repository
61
-
</h2>
62
-
<p class="text-red-500 dark:text-red-400 ">
63
-
Deleting a repository is irreversible and permanent. Be certain before
64
-
deleting a repository.
65
-
</p>
66
-
</div>
67
-
<div class="col-span-1 md:col-span-1 md:justify-self-end">
68
-
<button
69
-
class="btn group text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
70
-
type="button"
71
-
hx-delete="/{{ $.RepoInfo.FullName }}/settings/delete"
72
-
hx-confirm="Are you sure you want to delete {{ $.RepoInfo.FullName }}?">
46
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
47
+
<div class="col-span-1 md:col-span-2">
48
+
<h2 class="text-sm pb-2 uppercase text-red-500 dark:text-red-400 font-bold">Delete Repository</h2>
49
+
<p class="text-red-500 dark:text-red-400 ">
50
+
Deleting a repository is irreversible and permanent. Be certain before deleting a repository.
51
+
</p>
52
+
</div>
53
+
<div class="col-span-1 md:col-span-1 md:justify-self-end">
54
+
<button
55
+
class="btn group text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
56
+
type="button"
57
+
hx-delete="/{{ $.RepoInfo.FullName }}/settings/delete"
58
+
hx-confirm="Are you sure you want to delete {{ $.RepoInfo.FullName }}?">
73
59
{{ i "trash-2" "size-4" }}
74
60
delete
75
-
<span
76
-
class="ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline">
61
+
<span class="ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline">
77
62
{{ i "loader-circle" "w-4 h-4" }}
78
63
</span>
79
-
</button>
80
-
</div>
64
+
</button>
81
65
</div>
66
+
</div>
82
67
{{ end }}
83
68
{{ end }}
+53
-72
appview/pages/templates/repo/settings/pipelines.html
+53
-72
appview/pages/templates/repo/settings/pipelines.html
···
1
-
{{ define "title" }}
2
-
{{ .Tab }} settings ·
3
-
{{ .RepoInfo.FullName }}
4
-
{{ end }}
1
+
{{ define "title" }}{{ .Tab }} settings · {{ .RepoInfo.FullName }}{{ end }}
5
2
6
3
{{ define "repoContent" }}
7
4
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2">
···
25
22
<p class="text-gray-500 dark:text-gray-400">
26
23
Choose a spindle to execute your workflows on. Only repository owners
27
24
can configure spindles. Spindles can be selfhosted,
28
-
<a
29
-
class="text-gray-500 dark:text-gray-400 underline"
30
-
href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
25
+
<a class="text-gray-500 dark:text-gray-400 underline" href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
31
26
click to learn more.
32
27
</a>
33
28
</p>
34
29
</div>
35
30
{{ if not $.RepoInfo.Roles.IsOwner }}
36
-
<div
37
-
class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
31
+
<div class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
38
32
{{ or $.CurrentSpindle "No spindle configured" }}
39
33
</div>
40
34
{{ else }}
41
-
<form
42
-
hx-post="/{{ $.RepoInfo.FullName }}/settings/spindle"
43
-
class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
35
+
<form hx-post="/{{ $.RepoInfo.FullName }}/settings/spindle" class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
44
36
<select
45
37
id="spindle"
46
38
name="spindle"
47
39
required
48
40
class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
49
41
{{/* For some reason, we can't use an empty string in a <select> in all scenarios unless it is preceded by a disabled select?? No idea, could just be a Firefox thing? */}}
50
-
<option
51
-
value="[[none]]"
52
-
class="py-1"
53
-
{{ if not $.CurrentSpindle }}selected{{ end }}>
42
+
<option value="[[none]]" class="py-1" {{ if not $.CurrentSpindle }}selected{{ end }}>
54
43
{{ if not $.CurrentSpindle }}
55
-
Choose a spindle
44
+
Choose a spindle
56
45
{{ else }}
57
-
Disable pipelines
46
+
Disable pipelines
58
47
{{ end }}
59
48
</option>
60
49
{{ range $.Spindles }}
61
-
<option
62
-
value="{{ . }}"
63
-
class="py-1"
64
-
{{ if eq . $.CurrentSpindle }}selected{{ end }}>
50
+
<option value="{{ . }}" class="py-1" {{ if eq . $.CurrentSpindle }}selected{{ end }}>
65
51
{{ . }}
66
52
</option>
67
53
{{ end }}
68
54
</select>
69
-
<button
70
-
class="btn flex gap-2 items-center"
71
-
type="submit"
72
-
{{ if not $.RepoInfo.Roles.IsOwner }}disabled{{ end }}>
55
+
<button class="btn flex gap-2 items-center" type="submit" {{ if not $.RepoInfo.Roles.IsOwner }}disabled{{ end }}>
73
56
{{ i "check" "size-4" }}
74
57
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
75
58
</button>
···
83
66
<div class="col-span-1 md:col-span-2">
84
67
<h2 class="text-sm pb-2 uppercase font-bold">SECRETS</h2>
85
68
<p class="text-gray-500 dark:text-gray-400">
86
-
Secrets are accessible in workflow runs via environment variables.
87
-
Anyone with collaborator access to this repository can add and use
88
-
secrets in workflow runs.
69
+
Secrets are accessible in workflow runs via environment variables. Anyone
70
+
with collaborator access to this repository can add and use secrets in
71
+
workflow runs.
89
72
</p>
90
73
</div>
91
74
<div class="col-span-1 md:col-span-1 md:justify-self-end">
92
75
{{ template "addSecretButton" . }}
93
76
</div>
94
77
</div>
95
-
<div
96
-
class="flex flex-col rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 w-full">
78
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 w-full">
97
79
{{ range .Secrets }}
98
80
{{ template "repo/settings/fragments/secretListing" (list $ .) }}
99
81
{{ else }}
···
118
100
class="bg-white w-full md:w-96 dark:bg-gray-800 p-4 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50">
119
101
{{ template "addSecretModal" . }}
120
102
</div>
121
-
{{ end }}
103
+
{{ end}}
122
104
123
105
{{ define "addSecretModal" }}
124
-
<form
125
-
hx-put="/{{ $.RepoInfo.FullName }}/settings/secrets"
126
-
hx-indicator="#spinner"
127
-
hx-swap="none"
128
-
class="flex flex-col gap-2">
129
-
<p class="uppercase p-0">ADD SECRET</p>
130
-
<p class="text-sm text-gray-500 dark:text-gray-400">
131
-
Secrets are available as environment variables in the workflow.
132
-
</p>
133
-
<input
134
-
type="text"
135
-
id="secret-key"
136
-
name="key"
137
-
required
138
-
placeholder="SECRET_NAME" />
139
-
<textarea
140
-
type="text"
141
-
id="secret-value"
142
-
name="value"
143
-
required
144
-
placeholder="secret value"></textarea>
145
-
<div class="flex gap-2 pt-2">
146
-
<button
147
-
type="button"
148
-
popovertarget="add-secret-modal"
149
-
popovertargetaction="hide"
150
-
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
151
-
{{ i "x" "size-4" }} cancel
152
-
</button>
153
-
<button type="submit" class="btn w-1/2 flex items-center">
154
-
<span class="inline-flex gap-2 items-center">
155
-
{{ i "plus" "size-4" }} add
156
-
</span>
157
-
<span id="spinner" class="group">
158
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
159
-
</span>
160
-
</button>
161
-
</div>
162
-
<div id="add-secret-error" class="text-red-500 dark:text-red-400"></div>
163
-
</form>
106
+
<form
107
+
hx-put="/{{ $.RepoInfo.FullName }}/settings/secrets"
108
+
hx-indicator="#spinner"
109
+
hx-swap="none"
110
+
class="flex flex-col gap-2"
111
+
>
112
+
<p class="uppercase p-0">ADD SECRET</p>
113
+
<p class="text-sm text-gray-500 dark:text-gray-400">Secrets are available as environment variables in the workflow.</p>
114
+
<input
115
+
type="text"
116
+
id="secret-key"
117
+
name="key"
118
+
required
119
+
placeholder="SECRET_NAME"
120
+
/>
121
+
<textarea
122
+
type="text"
123
+
id="secret-value"
124
+
name="value"
125
+
required
126
+
placeholder="secret value"></textarea>
127
+
<div class="flex gap-2 pt-2">
128
+
<button
129
+
type="button"
130
+
popovertarget="add-secret-modal"
131
+
popovertargetaction="hide"
132
+
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
133
+
>
134
+
{{ i "x" "size-4" }} cancel
135
+
</button>
136
+
<button type="submit" class="btn w-1/2 flex items-center">
137
+
<span class="inline-flex gap-2 items-center">{{ i "plus" "size-4" }} add</span>
138
+
<span id="spinner" class="group">
139
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
140
+
</span>
141
+
</button>
142
+
</div>
143
+
<div id="add-secret-error" class="text-red-500 dark:text-red-400"></div>
144
+
</form>
164
145
{{ end }}
+69
-101
appview/pages/templates/repo/tree.html
+69
-101
appview/pages/templates/repo/tree.html
···
1
-
{{ define "title" }}
2
-
{{ range .BreadCrumbs }}{{ pathUnescape (index . 0) }}/{{ end }} at
3
-
{{ .Ref }}
4
-
·
5
-
{{ .RepoInfo.FullName }}
6
-
{{ end }}
1
+
{{ define "title"}}{{ range .BreadCrumbs }}{{ pathUnescape (index . 0)}}/{{ end }} at {{ .Ref }} · {{ .RepoInfo.FullName }}{{ end }}
2
+
7
3
8
4
{{ define "extrameta" }}
9
5
10
-
{{ $path := "" }}
11
-
{{ range .BreadCrumbs }}
6
+
{{ $path := "" }}
7
+
{{ range .BreadCrumbs }}
12
8
{{ $path = printf "%s/%s" $path (index . 0) }}
13
-
{{ end }}
9
+
{{ end }}
14
10
15
-
{{ template "repo/fragments/meta" . }}
16
-
{{ $title := printf "%s at %s · %s" $path .Ref .RepoInfo.FullName }}
17
-
{{ $url := printf "https://tangled.sh/%s/tree/%s%s" .RepoInfo.FullName .Ref $path }}
11
+
{{ template "repo/fragments/meta" . }}
12
+
{{ $title := printf "%s at %s · %s" $path .Ref .RepoInfo.FullName }}
13
+
{{ $url := printf "https://tangled.sh/%s/tree/%s%s" .RepoInfo.FullName .Ref $path }}
18
14
19
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
15
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
20
16
{{ end }}
21
17
22
-
{{ define "repoContent" }}
23
-
<main>
24
-
<div class="tree">
25
-
{{ $linkstyle := "no-underline hover:underline" }}
26
18
19
+
{{define "repoContent"}}
20
+
<main>
21
+
<div class="tree">
22
+
{{ $linkstyle := "no-underline hover:underline" }}
27
23
28
-
<div
29
-
class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
30
-
<div class="flex flex-col md:flex-row md:justify-between gap-2">
31
-
<div
32
-
id="breadcrumbs"
33
-
class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
34
-
{{ range .BreadCrumbs }}
35
-
<a
36
-
href="{{ index . 1 }}"
37
-
class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}">
38
-
{{ pathUnescape (index . 0) }}
39
-
</a>
40
-
/
41
-
{{ end }}
42
-
</div>
43
-
<div
44
-
id="dir-info"
45
-
class="text-gray-500 dark:text-gray-400 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0">
46
-
{{ $stats := .TreeStats }}
24
+
<div class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
25
+
<div class="flex flex-col md:flex-row md:justify-between gap-2">
26
+
<div id="breadcrumbs" class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
27
+
{{ range .BreadCrumbs }}
28
+
<a href="{{ index . 1}}" class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}">{{ pathUnescape (index . 0) }}</a> /
29
+
{{ end }}
30
+
</div>
31
+
<div id="dir-info" class="text-gray-500 dark:text-gray-400 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0">
32
+
{{ $stats := .TreeStats }}
47
33
48
-
49
-
<span>
50
-
at
51
-
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}">
52
-
{{ $.Ref }}
53
-
</a>
54
-
</span>
55
-
{{ if eq $stats.NumFolders 1 }}
56
-
<span
57
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
58
-
<span>{{ $stats.NumFolders }} folder</span>
59
-
{{ else if gt $stats.NumFolders 1 }}
60
-
<span
61
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
62
-
<span>{{ $stats.NumFolders }} folders</span>
63
-
{{ end }}
34
+
<span>at <a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}">{{ $.Ref }}</a></span>
35
+
{{ if eq $stats.NumFolders 1 }}
36
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
37
+
<span>{{ $stats.NumFolders }} folder</span>
38
+
{{ else if gt $stats.NumFolders 1 }}
39
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
40
+
<span>{{ $stats.NumFolders }} folders</span>
41
+
{{ end }}
64
42
65
-
{{ if eq $stats.NumFiles 1 }}
66
-
<span
67
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
68
-
<span>{{ $stats.NumFiles }} file</span>
69
-
{{ else if gt $stats.NumFiles 1 }}
70
-
<span
71
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
72
-
<span>{{ $stats.NumFiles }} files</span>
73
-
{{ end }}
43
+
{{ if eq $stats.NumFiles 1 }}
44
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
45
+
<span>{{ $stats.NumFiles }} file</span>
46
+
{{ else if gt $stats.NumFiles 1 }}
47
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
48
+
<span>{{ $stats.NumFiles }} files</span>
49
+
{{ end }}
74
50
75
-
</div>
76
51
</div>
77
52
</div>
53
+
</div>
78
54
79
-
{{ range .Files }}
80
-
<div class="grid grid-cols-12 gap-4 items-center py-1">
81
-
<div class="col-span-6 md:col-span-4">
82
-
{{ $link := printf "/%s/%s/%s/%s/%s" $.RepoInfo.FullName "tree" (urlquery $.Ref) $.TreePath .Name }}
83
-
{{ $icon := "folder" }}
84
-
{{ $iconStyle := "size-4 fill-current" }}
55
+
{{ range .Files }}
56
+
<div class="grid grid-cols-12 gap-4 items-center py-1">
57
+
<div class="col-span-6 md:col-span-4">
58
+
{{ $link := printf "/%s/%s/%s/%s/%s" $.RepoInfo.FullName "tree" (urlquery $.Ref) $.TreePath .Name }}
59
+
{{ $icon := "folder" }}
60
+
{{ $iconStyle := "size-4 fill-current" }}
85
61
86
-
{{ if .IsFile }}
87
-
{{ $icon = "file" }}
88
-
{{ $iconStyle = "size-4" }}
89
-
{{ end }}
90
-
<a href="{{ $link }}" class="{{ $linkstyle }}">
91
-
<div class="flex items-center gap-2">
92
-
{{ i $icon $iconStyle "flex-shrink-0" }}
93
-
<span class="truncate">{{ .Name }}</span>
94
-
</div>
95
-
</a>
96
-
</div>
62
+
{{ if .IsFile }}
63
+
{{ $icon = "file" }}
64
+
{{ $iconStyle = "size-4" }}
65
+
{{ end }}
66
+
<a href="{{ $link }}" class="{{ $linkstyle }}">
67
+
<div class="flex items-center gap-2">
68
+
{{ i $icon $iconStyle "flex-shrink-0" }}
69
+
<span class="truncate">{{ .Name }}</span>
70
+
</div>
71
+
</a>
72
+
</div>
97
73
98
-
<div class="col-span-0 md:col-span-6 hidden md:block overflow-hidden">
99
-
{{ with .LastCommit }}
100
-
<a
101
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}"
102
-
class="text-gray-500 dark:text-gray-400 block truncate">
103
-
{{ .Message }}
104
-
</a>
105
-
{{ end }}
106
-
</div>
74
+
<div class="col-span-0 md:col-span-6 hidden md:block overflow-hidden">
75
+
{{ with .LastCommit }}
76
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400 block truncate">{{ .Message }}</a>
77
+
{{ end }}
78
+
</div>
107
79
108
-
<div class="col-span-6 md:col-span-2 text-right">
109
-
{{ with .LastCommit }}
110
-
<a
111
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}"
112
-
class="text-gray-500 dark:text-gray-400">
113
-
{{ template "repo/fragments/time" .When }}
114
-
</a>
115
-
{{ end }}
116
-
</div>
80
+
<div class="col-span-6 md:col-span-2 text-right">
81
+
{{ with .LastCommit }}
82
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .When }}</a>
83
+
{{ end }}
117
84
</div>
118
-
{{ end }}
85
+
</div>
86
+
{{ end }}
119
87
120
-
</div>
121
-
</main>
122
-
{{ end }}
88
+
</div>
89
+
</main>
90
+
{{end}}
+143
-174
appview/pages/templates/settings.html
+143
-174
appview/pages/templates/settings.html
···
5
5
<p class="text-xl font-bold dark:text-white">Settings</p>
6
6
</div>
7
7
<div class="flex flex-col">
8
-
{{ block "profile" . }}{{ end }}
9
-
{{ block "keys" . }}{{ end }}
10
-
{{ block "emails" . }}{{ end }}
8
+
{{ block "profile" . }} {{ end }}
9
+
{{ block "keys" . }} {{ end }}
10
+
{{ block "emails" . }} {{ end }}
11
11
</div>
12
12
{{ end }}
13
13
14
14
{{ define "profile" }}
15
-
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">
16
-
profile
17
-
</h2>
18
-
<section
19
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
20
-
<dl class="grid grid-cols-[auto_1fr] gap-x-4 dark:text-gray-200">
21
-
{{ if .LoggedInUser.Handle }}
22
-
<dt class="font-bold">handle</dt>
23
-
<dd>@{{ .LoggedInUser.Handle }}</dd>
24
-
{{ end }}
25
-
<dt class="font-bold">did</dt>
26
-
<dd>{{ .LoggedInUser.Did }}</dd>
27
-
<dt class="font-bold">pds</dt>
28
-
<dd>{{ .LoggedInUser.Pds }}</dd>
29
-
</dl>
30
-
</section>
15
+
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">profile</h2>
16
+
<section class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
17
+
<dl class="grid grid-cols-[auto_1fr] gap-x-4 dark:text-gray-200">
18
+
{{ if .LoggedInUser.Handle }}
19
+
<dt class="font-bold">handle</dt>
20
+
<dd>@{{ .LoggedInUser.Handle }}</dd>
21
+
{{ end }}
22
+
<dt class="font-bold">did</dt>
23
+
<dd>{{ .LoggedInUser.Did }}</dd>
24
+
<dt class="font-bold">pds</dt>
25
+
<dd>{{ .LoggedInUser.Pds }}</dd>
26
+
</dl>
27
+
</section>
31
28
{{ end }}
32
29
33
30
{{ define "keys" }}
34
-
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">
35
-
ssh keys
36
-
</h2>
37
-
<section
38
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
39
-
<p class="mb-8 dark:text-gray-300">
40
-
SSH public keys added here will be broadcasted to knots that you are a
41
-
member of,
42
-
<br />
43
-
allowing you to push to repositories there.
44
-
</p>
45
-
<div id="key-list" class="flex flex-col gap-6 mb-8">
46
-
{{ range $index, $key := .PubKeys }}
47
-
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
48
-
<div class="flex flex-col gap-1">
49
-
<div class="inline-flex items-center gap-4">
50
-
{{ i "key" "w-3 h-3 dark:text-gray-300" }}
51
-
<p class="font-bold dark:text-white">{{ .Name }}</p>
52
-
</div>
53
-
<p class="text-sm text-gray-500 dark:text-gray-400">
54
-
added
55
-
{{ template "repo/fragments/time" .Created }}
56
-
</p>
57
-
<div class="overflow-x-auto whitespace-nowrap flex-1 max-w-full">
58
-
<code class="text-sm text-gray-500 dark:text-gray-400">
59
-
{{ .Key }}
60
-
</code>
61
-
</div>
62
-
</div>
63
-
<button
64
-
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
65
-
title="Delete key"
66
-
hx-delete="/settings/keys?name={{ urlquery .Name }}&rkey={{ urlquery .Rkey }}&key={{ urlquery .Key }}"
67
-
hx-confirm="Are you sure you want to delete the key '{{ .Name }}'?">
68
-
{{ i "trash-2" "w-5 h-5" }}
69
-
<span class="hidden md:inline">delete</span>
70
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
71
-
</button>
31
+
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">ssh keys</h2>
32
+
<section class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
33
+
<p class="mb-8 dark:text-gray-300">SSH public keys added here will be broadcasted to knots that you are a member of, <br> allowing you to push to repositories there.</p>
34
+
<div id="key-list" class="flex flex-col gap-6 mb-8">
35
+
{{ range $index, $key := .PubKeys }}
36
+
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
37
+
<div class="flex flex-col gap-1">
38
+
<div class="inline-flex items-center gap-4">
39
+
{{ i "key" "w-3 h-3 dark:text-gray-300" }}
40
+
<p class="font-bold dark:text-white">{{ .Name }}</p>
41
+
</div>
42
+
<p class="text-sm text-gray-500 dark:text-gray-400">added {{ template "repo/fragments/time" .Created }}</p>
43
+
<div class="overflow-x-auto whitespace-nowrap flex-1 max-w-full">
44
+
<code class="text-sm text-gray-500 dark:text-gray-400">{{ .Key }}</code>
72
45
</div>
73
-
{{ end }}
46
+
</div>
47
+
<button
48
+
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
49
+
title="Delete key"
50
+
hx-delete="/settings/keys?name={{urlquery .Name}}&rkey={{urlquery .Rkey}}&key={{urlquery .Key}}"
51
+
hx-confirm="Are you sure you want to delete the key '{{ .Name }}'?"
52
+
>
53
+
{{ i "trash-2" "w-5 h-5" }}
54
+
<span class="hidden md:inline">delete</span>
55
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
56
+
</button>
74
57
</div>
75
-
<form
58
+
{{ end }}
59
+
</div>
60
+
<form
76
61
hx-put="/settings/keys"
77
62
hx-indicator="#add-sshkey-spinner"
78
63
hx-swap="none"
79
-
class="max-w-2xl mb-8 space-y-4">
64
+
class="max-w-2xl mb-8 space-y-4"
65
+
>
80
66
<input
81
-
type="text"
82
-
id="name"
83
-
name="name"
84
-
placeholder="key name"
85
-
required
86
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400" />
67
+
type="text"
68
+
id="name"
69
+
name="name"
70
+
placeholder="key name"
71
+
required
72
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"/>
87
73
88
74
<input
89
-
id="key"
90
-
name="key"
91
-
placeholder="ssh-rsa AAAAAA..."
92
-
required
93
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400" />
75
+
id="key"
76
+
name="key"
77
+
placeholder="ssh-rsa AAAAAA..."
78
+
required
79
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"/>
94
80
95
-
<button
96
-
class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center"
97
-
type="submit">
98
-
<span>add key</span>
99
-
<span id="add-sshkey-spinner" class="group">
100
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
101
-
</span>
81
+
<button class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center" type="submit">
82
+
<span>add key</span>
83
+
<span id="add-sshkey-spinner" class="group">
84
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
85
+
</span>
102
86
</button>
103
87
104
88
<div id="settings-keys" class="error dark:text-red-400"></div>
105
-
</form>
106
-
</section>
89
+
</form>
90
+
</section>
107
91
{{ end }}
108
92
109
93
{{ define "emails" }}
110
-
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">
111
-
email addresses
112
-
</h2>
113
-
<section
114
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
115
-
<p class="mb-8 dark:text-gray-300">
116
-
Commits authored using emails listed here will be associated with your
117
-
Tangled profile.
118
-
</p>
119
-
<div id="email-list" class="flex flex-col gap-6 mb-8">
120
-
{{ range $index, $email := .Emails }}
121
-
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
122
-
<div class="flex flex-col gap-2">
123
-
<div class="inline-flex items-center gap-4">
124
-
{{ i "mail" "w-3 h-3 dark:text-gray-300" }}
125
-
<p class="font-bold dark:text-white">{{ .Address }}</p>
126
-
<div class="inline-flex items-center gap-1">
127
-
{{ if .Verified }}
128
-
<span
129
-
class="text-xs bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 rounded">
130
-
verified
131
-
</span>
132
-
{{ else }}
133
-
<span
134
-
class="text-xs bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 px-2 py-1 rounded">
135
-
unverified
136
-
</span>
137
-
{{ end }}
138
-
{{ if .Primary }}
139
-
<span
140
-
class="text-xs bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 px-2 py-1 rounded">
141
-
primary
142
-
</span>
143
-
{{ end }}
144
-
</div>
145
-
</div>
146
-
<p class="text-sm text-gray-500 dark:text-gray-400">
147
-
added
148
-
{{ template "repo/fragments/time" .CreatedAt }}
149
-
</p>
150
-
</div>
151
-
<div class="flex gap-2 items-center">
152
-
{{ if not .Verified }}
153
-
<button
154
-
class="btn flex gap-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600"
155
-
hx-post="/settings/emails/verify/resend"
156
-
hx-swap="none"
157
-
href="#"
158
-
hx-vals='{"email": "{{ .Address }}"}'>
159
-
{{ i "rotate-cw" "w-5 h-5" }}
160
-
<span class="hidden md:inline">resend</span>
161
-
</button>
94
+
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">email addresses</h2>
95
+
<section class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
96
+
<p class="mb-8 dark:text-gray-300">Commits authored using emails listed here will be associated with your Tangled profile.</p>
97
+
<div id="email-list" class="flex flex-col gap-6 mb-8">
98
+
{{ range $index, $email := .Emails }}
99
+
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
100
+
<div class="flex flex-col gap-2">
101
+
<div class="inline-flex items-center gap-4">
102
+
{{ i "mail" "w-3 h-3 dark:text-gray-300" }}
103
+
<p class="font-bold dark:text-white">{{ .Address }}</p>
104
+
<div class="inline-flex items-center gap-1">
105
+
{{ if .Verified }}
106
+
<span class="text-xs bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 rounded">verified</span>
107
+
{{ else }}
108
+
<span class="text-xs bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 px-2 py-1 rounded">unverified</span>
162
109
{{ end }}
163
-
{{ if and (not .Primary) .Verified }}
164
-
<a
165
-
class="text-sm dark:text-blue-400 dark:hover:text-blue-300"
166
-
hx-post="/settings/emails/primary"
167
-
hx-swap="none"
168
-
href="#"
169
-
hx-vals='{"email": "{{ .Address }}"}'>
170
-
set as primary
171
-
</a>
172
-
{{ end }}
173
-
{{ if not .Primary }}
174
-
<form
175
-
hx-delete="/settings/emails"
176
-
hx-confirm="Are you sure you wish to delete the email '{{ .Address }}'?"
177
-
hx-indicator="#delete-email-{{ $index }}-spinner">
178
-
<input type="hidden" name="email" value="{{ .Address }}" />
179
-
<button
180
-
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
181
-
title="Delete email"
182
-
type="submit">
183
-
{{ i "trash-2" "w-5 h-5" }}
184
-
<span class="hidden md:inline">delete</span>
185
-
<span id="delete-email-{{ $index }}-spinner" class="group">
186
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
187
-
</span>
188
-
</button>
189
-
</form>
110
+
{{ if .Primary }}
111
+
<span class="text-xs bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 px-2 py-1 rounded">primary</span>
190
112
{{ end }}
191
113
</div>
192
114
</div>
193
-
{{ end }}
115
+
<p class="text-sm text-gray-500 dark:text-gray-400">added {{ template "repo/fragments/time" .CreatedAt }}</p>
116
+
</div>
117
+
<div class="flex gap-2 items-center">
118
+
{{ if not .Verified }}
119
+
<button
120
+
class="btn flex gap-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600"
121
+
hx-post="/settings/emails/verify/resend"
122
+
hx-swap="none"
123
+
href="#"
124
+
hx-vals='{"email": "{{ .Address }}"}'>
125
+
{{ i "rotate-cw" "w-5 h-5" }}
126
+
<span class="hidden md:inline">resend</span>
127
+
</button>
128
+
{{ end }}
129
+
{{ if and (not .Primary) .Verified }}
130
+
<a
131
+
class="text-sm dark:text-blue-400 dark:hover:text-blue-300"
132
+
hx-post="/settings/emails/primary"
133
+
hx-swap="none"
134
+
href="#"
135
+
hx-vals='{"email": "{{ .Address }}"}'>
136
+
set as primary
137
+
</a>
138
+
{{ end }}
139
+
{{ if not .Primary }}
140
+
<form
141
+
hx-delete="/settings/emails"
142
+
hx-confirm="Are you sure you wish to delete the email '{{ .Address }}'?"
143
+
hx-indicator="#delete-email-{{ $index }}-spinner"
144
+
>
145
+
<input type="hidden" name="email" value="{{ .Address }}">
146
+
<button
147
+
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
148
+
title="Delete email"
149
+
type="submit"
150
+
>
151
+
{{ i "trash-2" "w-5 h-5" }}
152
+
<span class="hidden md:inline">delete</span>
153
+
<span id="delete-email-{{ $index }}-spinner" class="group">
154
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
155
+
</span>
156
+
</button>
157
+
</form>
158
+
{{ end }}
159
+
</div>
194
160
</div>
195
-
<form
161
+
{{ end }}
162
+
</div>
163
+
<form
196
164
hx-put="/settings/emails"
197
165
hx-swap="none"
198
166
class="max-w-2xl mb-8 space-y-4"
199
-
hx-indicator="#add-email-spinner">
167
+
hx-indicator="#add-email-spinner"
168
+
>
200
169
<input
201
-
type="email"
202
-
id="email"
203
-
name="email"
204
-
placeholder="your@email.com"
205
-
required
206
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400" />
170
+
type="email"
171
+
id="email"
172
+
name="email"
173
+
placeholder="your@email.com"
174
+
required
175
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"
176
+
>
207
177
208
178
<button
209
179
class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center"
210
-
type="submit">
180
+
type="submit"
181
+
>
211
182
<span>add email</span>
212
183
<span id="add-email-spinner" class="group">
213
184
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
···
215
186
</button>
216
187
217
188
<div id="settings-emails-error" class="error dark:text-red-400"></div>
218
-
<div
219
-
id="settings-emails-success"
220
-
class="success dark:text-green-400"></div>
221
-
</form>
222
-
</section>
189
+
<div id="settings-emails-success" class="success dark:text-green-400"></div>
190
+
</form>
191
+
</section>
223
192
{{ end }}
+51
-51
appview/pages/templates/spindles/dashboard.html
+51
-51
appview/pages/templates/spindles/dashboard.html
···
1
-
{{ define "title" }}{{ .Spindle.Instance }} · spindles{{ end }}
1
+
{{ define "title" }}{{.Spindle.Instance}} · spindles{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<div class="px-6 py-4">
5
-
<div class="flex justify-between items-center">
6
-
<h1 class="text-xl font-bold dark:text-white">{{ .Spindle.Instance }}</h1>
7
-
<div id="right-side" class="flex gap-2">
8
-
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }}
9
-
{{ $isOwner := and .LoggedInUser (eq .LoggedInUser.Did .Spindle.Owner) }}
10
-
{{ if .Spindle.Verified }}
11
-
<span
12
-
class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{ $style }}">
13
-
{{ i "shield-check" "w-4 h-4" }} verified
14
-
</span>
15
-
{{ if $isOwner }}
16
-
{{ template "spindles/fragments/addMemberModal" .Spindle }}
17
-
{{ end }}
18
-
{{ else }}
19
-
<span
20
-
class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{ $style }}">
21
-
{{ i "shield-off" "w-4 h-4" }} unverified
22
-
</span>
23
-
{{ if $isOwner }}
24
-
{{ block "retryButton" .Spindle }}{{ end }}
25
-
{{ end }}
4
+
<div class="px-6 py-4">
5
+
<div class="flex justify-between items-center">
6
+
<h1 class="text-xl font-bold dark:text-white">{{ .Spindle.Instance }}</h1>
7
+
<div id="right-side" class="flex gap-2">
8
+
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }}
9
+
{{ $isOwner := and .LoggedInUser (eq .LoggedInUser.Did .Spindle.Owner) }}
10
+
{{ if .Spindle.Verified }}
11
+
<span class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{$style}}">{{ i "shield-check" "w-4 h-4" }} verified</span>
12
+
{{ if $isOwner }}
13
+
{{ template "spindles/fragments/addMemberModal" .Spindle }}
26
14
{{ end }}
27
-
15
+
{{ else }}
16
+
<span class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{$style}}">{{ i "shield-off" "w-4 h-4" }} unverified</span>
28
17
{{ if $isOwner }}
29
-
{{ block "deleteButton" .Spindle }}{{ end }}
18
+
{{ block "retryButton" .Spindle }} {{ end }}
30
19
{{ end }}
31
-
</div>
20
+
{{ end }}
21
+
22
+
{{ if $isOwner }}
23
+
{{ block "deleteButton" .Spindle }} {{ end }}
24
+
{{ end }}
32
25
</div>
33
-
<div id="operation-error" class="dark:text-red-400"></div>
34
26
</div>
27
+
<div id="operation-error" class="dark:text-red-400"></div>
28
+
</div>
35
29
36
-
{{ if .Members }}
37
-
<section
38
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
39
-
<div class="flex flex-col gap-2">
40
-
{{ block "member" . }}{{ end }}
41
-
</div>
42
-
</section>
43
-
{{ end }}
30
+
{{ if .Members }}
31
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
32
+
<div class="flex flex-col gap-2">
33
+
{{ block "member" . }} {{ end }}
34
+
</div>
35
+
</section>
36
+
{{ end }}
44
37
{{ end }}
38
+
45
39
46
40
{{ define "member" }}
47
41
{{ range .Members }}
···
51
45
{{ template "user/fragments/picHandleLink" . }}
52
46
</div>
53
47
{{ if ne $.LoggedInUser.Did . }}
54
-
{{ block "removeMemberButton" (list $ . ) }}{{ end }}
48
+
{{ block "removeMemberButton" (list $ . ) }} {{ end }}
55
49
{{ end }}
56
50
</div>
57
51
<div class="ml-2 pl-2 pt-2 border-l border-gray-200 dark:border-gray-700">
···
80
74
hx-delete="/spindles/{{ .Instance }}"
81
75
hx-swap="outerHTML"
82
76
hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?"
83
-
hx-headers='{"shouldRedirect": "true"}'>
77
+
hx-headers='{"shouldRedirect": "true"}'
78
+
>
84
79
{{ i "trash-2" "w-5 h-5" }}
85
-
<span class="hidden md:inline">delete</span>
80
+
<span class="hidden md:inline">delete</span>
86
81
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
87
82
</button>
88
83
{{ end }}
84
+
89
85
90
86
{{ define "retryButton" }}
91
87
<button
···
93
89
title="Retry spindle verification"
94
90
hx-post="/spindles/{{ .Instance }}/retry"
95
91
hx-swap="none"
96
-
hx-headers='{"shouldRefresh": "true"}'>
92
+
hx-headers='{"shouldRefresh": "true"}'
93
+
>
97
94
{{ i "rotate-ccw" "w-5 h-5" }}
98
-
<span class="hidden md:inline">retry</span>
95
+
<span class="hidden md:inline">retry</span>
99
96
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
100
97
</button>
101
98
{{ end }}
102
99
100
+
103
101
{{ define "removeMemberButton" }}
104
102
{{ $root := index . 0 }}
105
103
{{ $member := index . 1 }}
106
-
<button
107
-
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
108
-
title="Remove member"
109
-
hx-post="/spindles/{{ $root.Spindle.Instance }}/remove"
110
-
hx-swap="none"
111
-
hx-vals='{"member": "{{ $member }}" }'
112
-
hx-confirm="Are you sure you want to remove {{ resolve $member }} from this instance?">
113
-
{{ i "user-minus" "w-4 h-4" }}
114
-
remove
115
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
116
-
</button>
104
+
<button
105
+
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
106
+
title="Remove member"
107
+
hx-post="/spindles/{{ $root.Spindle.Instance }}/remove"
108
+
hx-swap="none"
109
+
hx-vals='{"member": "{{$member}}" }'
110
+
hx-confirm="Are you sure you want to remove {{ resolve $member }} from this instance?"
111
+
>
112
+
{{ i "user-minus" "w-4 h-4" }}
113
+
remove
114
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
115
+
</button>
117
116
{{ end }}
117
+
+39
-39
appview/pages/templates/spindles/fragments/addMemberModal.html
+39
-39
appview/pages/templates/spindles/fragments/addMemberModal.html
···
3
3
class="btn gap-2 group"
4
4
title="Add member to this spindle"
5
5
popovertarget="add-member-{{ .Instance }}"
6
-
popovertargetaction="toggle">
6
+
popovertargetaction="toggle"
7
+
>
7
8
{{ i "user-plus" "w-5 h-5" }}
8
-
<span class="hidden md:inline">add member</span>
9
+
<span class="hidden md:inline">add member</span>
9
10
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
10
11
</button>
11
12
···
13
14
id="add-member-{{ .Instance }}"
14
15
popover
15
16
class="bg-white w-full md:w-96 dark:bg-gray-800 p-4 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50">
16
-
{{ block "addMemberPopover" . }}{{ end }}
17
+
{{ block "addMemberPopover" . }} {{ end }}
17
18
</div>
18
19
{{ end }}
19
20
20
21
{{ define "addMemberPopover" }}
21
-
<form
22
-
hx-post="/spindles/{{ .Instance }}/add"
23
-
hx-indicator="#spinner"
24
-
hx-swap="none"
25
-
class="flex flex-col gap-2">
26
-
<label for="member-did-{{ .Id }}" class="uppercase p-0">ADD MEMBER</label>
27
-
<p class="text-sm text-gray-500 dark:text-gray-400">
28
-
Members can register repositories and run workflows on this spindle.
29
-
</p>
30
-
<input
31
-
type="text"
32
-
id="member-did-{{ .Id }}"
33
-
name="member"
34
-
required
35
-
placeholder="@foo.bsky.social" />
36
-
<div class="flex gap-2 pt-2">
37
-
<button
38
-
type="button"
39
-
popovertarget="add-member-{{ .Instance }}"
40
-
popovertargetaction="hide"
41
-
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
42
-
{{ i "x" "size-4" }} cancel
43
-
</button>
44
-
<button type="submit" class="btn w-1/2 flex items-center">
45
-
<span class="inline-flex gap-2 items-center">
46
-
{{ i "user-plus" "size-4" }} add
47
-
</span>
48
-
<span id="spinner" class="group">
49
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
50
-
</span>
51
-
</button>
52
-
</div>
53
-
<div
54
-
id="add-member-error-{{ .Id }}"
55
-
class="text-red-500 dark:text-red-400"></div>
56
-
</form>
22
+
<form
23
+
hx-post="/spindles/{{ .Instance }}/add"
24
+
hx-indicator="#spinner"
25
+
hx-swap="none"
26
+
class="flex flex-col gap-2"
27
+
>
28
+
<label for="member-did-{{ .Id }}" class="uppercase p-0">
29
+
ADD MEMBER
30
+
</label>
31
+
<p class="text-sm text-gray-500 dark:text-gray-400">Members can register repositories and run workflows on this spindle.</p>
32
+
<input
33
+
type="text"
34
+
id="member-did-{{ .Id }}"
35
+
name="member"
36
+
required
37
+
placeholder="@foo.bsky.social"
38
+
/>
39
+
<div class="flex gap-2 pt-2">
40
+
<button
41
+
type="button"
42
+
popovertarget="add-member-{{ .Instance }}"
43
+
popovertargetaction="hide"
44
+
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
45
+
>
46
+
{{ i "x" "size-4" }} cancel
47
+
</button>
48
+
<button type="submit" class="btn w-1/2 flex items-center">
49
+
<span class="inline-flex gap-2 items-center">{{ i "user-plus" "size-4" }} add</span>
50
+
<span id="spinner" class="group">
51
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
52
+
</span>
53
+
</button>
54
+
</div>
55
+
<div id="add-member-error-{{ .Id }}" class="text-red-500 dark:text-red-400"></div>
56
+
</form>
57
57
{{ end }}
+29
-36
appview/pages/templates/spindles/fragments/spindleListing.html
+29
-36
appview/pages/templates/spindles/fragments/spindleListing.html
···
1
1
{{ define "spindles/fragments/spindleListing" }}
2
-
<div
3
-
id="spindle-{{ .Id }}"
4
-
class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
5
-
{{ block "leftSide" . }}{{ end }}
6
-
{{ block "rightSide" . }}{{ end }}
2
+
<div id="spindle-{{.Id}}" class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
3
+
{{ block "leftSide" . }} {{ end }}
4
+
{{ block "rightSide" . }} {{ end }}
7
5
</div>
8
6
{{ end }}
9
7
10
8
{{ define "leftSide" }}
11
9
{{ if .Verified }}
12
-
<a
13
-
href="/spindles/{{ .Instance }}"
14
-
class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
15
-
{{ i "hard-drive" "w-4 h-4" }}
16
-
{{ .Instance }}
17
-
<span class="text-gray-500">
18
-
{{ template "repo/fragments/shortTimeAgo" .Created }}
19
-
</span>
20
-
</a>
10
+
<a href="/spindles/{{ .Instance }}" class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
11
+
{{ i "hard-drive" "w-4 h-4" }}
12
+
{{ .Instance }}
13
+
<span class="text-gray-500">
14
+
{{ template "repo/fragments/shortTimeAgo" .Created }}
15
+
</span>
16
+
</a>
21
17
{{ else }}
22
-
<div class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
23
-
{{ i "hard-drive" "w-4 h-4" }}
24
-
{{ .Instance }}
25
-
<span class="text-gray-500">
26
-
{{ template "repo/fragments/shortTimeAgo" .Created }}
27
-
</span>
28
-
</div>
18
+
<div class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
19
+
{{ i "hard-drive" "w-4 h-4" }}
20
+
{{ .Instance }}
21
+
<span class="text-gray-500">
22
+
{{ template "repo/fragments/shortTimeAgo" .Created }}
23
+
</span>
24
+
</div>
29
25
{{ end }}
30
26
{{ end }}
31
27
···
33
29
<div id="right-side" class="flex gap-2">
34
30
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2 text-sm" }}
35
31
{{ if .Verified }}
36
-
<span
37
-
class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{ $style }}">
38
-
{{ i "shield-check" "w-4 h-4" }} verified
39
-
</span>
32
+
<span class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 {{$style}}">{{ i "shield-check" "w-4 h-4" }} verified</span>
40
33
{{ template "spindles/fragments/addMemberModal" . }}
41
34
{{ else }}
42
-
<span
43
-
class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{ $style }}">
44
-
{{ i "shield-off" "w-4 h-4" }} unverified
45
-
</span>
46
-
{{ block "retryButton" . }}{{ end }}
35
+
<span class="bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200 {{$style}}">{{ i "shield-off" "w-4 h-4" }} unverified</span>
36
+
{{ block "retryButton" . }} {{ end }}
47
37
{{ end }}
48
-
{{ block "deleteButton" . }}{{ end }}
38
+
{{ block "deleteButton" . }} {{ end }}
49
39
</div>
50
40
{{ end }}
51
41
···
55
45
title="Delete spindle"
56
46
hx-delete="/spindles/{{ .Instance }}"
57
47
hx-swap="outerHTML"
58
-
hx-target="#spindle-{{ .Id }}"
59
-
hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?">
48
+
hx-target="#spindle-{{.Id}}"
49
+
hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?"
50
+
>
60
51
{{ i "trash-2" "w-5 h-5" }}
61
-
<span class="hidden md:inline">delete</span>
52
+
<span class="hidden md:inline">delete</span>
62
53
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
63
54
</button>
64
55
{{ end }}
56
+
65
57
66
58
{{ define "retryButton" }}
67
59
<button
···
69
61
title="Retry spindle verification"
70
62
hx-post="/spindles/{{ .Instance }}/retry"
71
63
hx-swap="none"
72
-
hx-target="#spindle-{{ .Id }}">
64
+
hx-target="#spindle-{{.Id}}"
65
+
>
73
66
{{ i "rotate-ccw" "w-5 h-5" }}
74
-
<span class="hidden md:inline">retry</span>
67
+
<span class="hidden md:inline">retry</span>
75
68
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
76
69
</button>
77
70
{{ end }}
+23
-29
appview/pages/templates/spindles/index.html
+23
-29
appview/pages/templates/spindles/index.html
···
1
1
{{ define "title" }}spindles{{ end }}
2
2
3
3
{{ define "content" }}
4
-
<div class="px-6 py-4">
5
-
<h1 class="text-xl font-bold dark:text-white">Spindles</h1>
6
-
</div>
4
+
<div class="px-6 py-4">
5
+
<h1 class="text-xl font-bold dark:text-white">Spindles</h1>
6
+
</div>
7
7
8
-
<section
9
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
10
-
<div class="flex flex-col gap-6">
11
-
{{ block "about" . }}{{ end }}
12
-
{{ block "list" . }}{{ end }}
13
-
{{ block "register" . }}{{ end }}
14
-
</div>
15
-
</section>
8
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
9
+
<div class="flex flex-col gap-6">
10
+
{{ block "about" . }} {{ end }}
11
+
{{ block "list" . }} {{ end }}
12
+
{{ block "register" . }} {{ end }}
13
+
</div>
14
+
</section>
16
15
{{ end }}
17
16
18
17
{{ define "about" }}
19
18
<section class="rounded flex flex-col gap-2">
20
19
<p class="dark:text-gray-300">
21
20
Spindles are small CI runners.
22
-
<a
23
-
href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
21
+
<a href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
24
22
Checkout the documentation if you're interested in self-hosting.
25
23
</a>
26
24
</p>
···
29
27
30
28
{{ define "list" }}
31
29
<section class="rounded w-full flex flex-col gap-2">
32
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
33
-
your spindles
34
-
</h2>
35
-
<div
36
-
class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
30
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">your spindles</h2>
31
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
37
32
{{ range $spindle := .Spindles }}
38
33
{{ template "spindles/fragments/spindleListing" . }}
39
34
{{ else }}
40
-
<div
41
-
class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
35
+
<div class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
42
36
no spindles registered yet
43
37
</div>
44
38
{{ end }}
···
49
43
50
44
{{ define "register" }}
51
45
<section class="rounded w-full lg:w-fit flex flex-col gap-2">
52
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
53
-
register a spindle
54
-
</h2>
55
-
<p class="mb-2 dark:text-gray-300">
56
-
Enter the hostname of your spindle to get started.
57
-
</p>
46
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a spindle</h2>
47
+
<p class="mb-2 dark:text-gray-300">Enter the hostname of your spindle to get started.</p>
58
48
<form
59
49
hx-post="/spindles/register"
60
50
class="max-w-2xl mb-2 space-y-4"
61
51
hx-indicator="#register-button"
62
-
hx-swap="none">
52
+
hx-swap="none"
53
+
>
63
54
<div class="flex gap-2">
64
55
<input
65
56
type="text"
···
67
58
name="instance"
68
59
placeholder="spindle.example.com"
69
60
required
70
-
class="flex-1 w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded" />
61
+
class="flex-1 w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded"
62
+
>
71
63
<button
72
64
type="submit"
73
65
id="register-button"
74
-
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group">
66
+
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group"
67
+
>
75
68
<span class="inline-flex items-center gap-2">
76
69
{{ i "plus" "w-4 h-4" }}
77
70
register
···
84
77
85
78
<div id="register-error" class="dark:text-red-400"></div>
86
79
</form>
80
+
87
81
</section>
88
82
{{ end }}
+14
-25
appview/pages/templates/strings/dashboard.html
+14
-25
appview/pages/templates/strings/dashboard.html
···
1
-
{{ define "title" }}strings by {{ or .Card.UserHandle .Card.UserDid }}{{ end }}
1
+
{{ define "title" }}strings by {{ or .Card.UserHandle .Card.UserDid }}{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
5
-
<meta property="og:type" content="profile" />
6
-
<meta
7
-
property="og:url"
8
-
content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
9
-
<meta
10
-
property="og:description"
11
-
content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
4
+
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
5
+
<meta property="og:type" content="profile" />
6
+
<meta property="og:url" content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
7
+
<meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
12
8
{{ end }}
9
+
13
10
14
11
{{ define "content" }}
15
-
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
12
+
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
16
13
<div class="md:col-span-3 order-1 md:order-1">
17
-
{{ template "user/fragments/profileCard" .Card }}
14
+
{{ template "user/fragments/profileCard" .Card }}
18
15
</div>
19
16
<div id="all-strings" class="md:col-span-8 order-2 md:order-2">
20
-
{{ block "allStrings" . }}{{ end }}
17
+
{{ block "allStrings" . }}{{ end }}
21
18
</div>
22
-
</div>
19
+
</div>
23
20
{{ end }}
24
21
25
22
{{ define "allStrings" }}
···
28
25
{{ range .Strings }}
29
26
{{ template "singleString" (list $ .) }}
30
27
{{ else }}
31
-
<p class="px-6 dark:text-white">
32
-
This user does not have any strings yet.
33
-
</p>
28
+
<p class="px-6 dark:text-white">This user does not have any strings yet.</p>
34
29
{{ end }}
35
30
</div>
36
31
{{ end }}
···
40
35
{{ $s := index . 1 }}
41
36
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800">
42
37
<div class="font-medium dark:text-white flex gap-2 items-center">
43
-
<a
44
-
href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">
45
-
{{ $s.Filename }}
46
-
</a>
38
+
<a href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a>
47
39
</div>
48
40
{{ with $s.Description }}
49
41
<div class="text-gray-600 dark:text-gray-300 text-sm">
50
-
{{ . }}
42
+
{{ . }}
51
43
</div>
52
44
{{ end }}
53
45
54
46
{{ $stat := $s.Stats }}
55
47
<div class="text-gray-400 pt-4 text-sm font-mono inline-flex gap-2 mt-auto">
56
-
<span>
57
-
{{ $stat.LineCount }}
58
-
line{{ if ne $stat.LineCount 1 }}s{{ end }}
59
-
</span>
48
+
<span>{{ $stat.LineCount }} line{{if ne $stat.LineCount 1}}s{{end}}</span>
60
49
<span class="select-none [&:before]:content-['·']"></span>
61
50
{{ with $s.Edited }}
62
51
<span>edited {{ template "repo/fragments/shortTimeAgo" . }}</span>
+20
-20
appview/pages/templates/strings/fragments/form.html
+20
-20
appview/pages/templates/strings/fragments/form.html
···
3
3
{{ if eq .Action "new" }}
4
4
hx-post="/strings/new"
5
5
{{ else }}
6
-
hx-post="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit"
6
+
hx-post="/strings/{{.String.Did}}/{{.String.Rkey}}/edit"
7
7
{{ end }}
8
8
hx-indicator="#new-button"
9
9
class="p-6 pb-4 dark:text-white flex flex-col gap-2 bg-white dark:bg-gray-800 drop-shadow-sm rounded"
···
16
16
placeholder="Filename with extension"
17
17
required
18
18
value="{{ .String.Filename }}"
19
-
class="md:max-w-64 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded" />
19
+
class="md:max-w-64 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded"
20
+
>
20
21
<input
21
22
type="text"
22
23
id="description"
23
24
name="description"
24
25
value="{{ .String.Description }}"
25
26
placeholder="Description ..."
26
-
class="flex-1 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded" />
27
+
class="flex-1 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded"
28
+
>
27
29
</div>
28
30
<textarea
29
-
name="content"
31
+
name="content"
30
32
id="content-textarea"
31
33
wrap="off"
32
34
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"
33
35
rows="20"
34
36
placeholder="Paste your string here!"
35
-
required>
36
-
{{ .String.Contents }}</textarea
37
-
>
37
+
required>{{ .String.Contents }}</textarea>
38
38
<div class="flex justify-between items-center">
39
39
<div id="content-stats" class="text-sm text-gray-500 dark:text-gray-400">
40
40
<span id="line-count">0 lines</span>
···
43
43
</div>
44
44
<div id="actions" class="flex gap-2 items-center">
45
45
{{ if eq .Action "edit" }}
46
-
<a
47
-
class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 "
48
-
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}">
46
+
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 "
47
+
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}">
49
48
{{ i "x" "size-4" }}
50
49
<span class="hidden md:inline">cancel</span>
51
50
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
···
54
53
<button
55
54
type="submit"
56
55
id="new-button"
57
-
class="w-fit btn-create rounded flex items-center py-0 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group">
56
+
class="w-fit btn-create rounded flex items-center py-0 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group"
57
+
>
58
58
<span class="inline-flex items-center gap-2">
59
59
{{ i "arrow-up" "w-4 h-4" }}
60
60
publish
···
66
66
</div>
67
67
</div>
68
68
<script>
69
-
(function () {
70
-
const textarea = document.getElementById("content-textarea");
71
-
const lineCount = document.getElementById("line-count");
72
-
const byteCount = document.getElementById("byte-count");
69
+
(function() {
70
+
const textarea = document.getElementById('content-textarea');
71
+
const lineCount = document.getElementById('line-count');
72
+
const byteCount = document.getElementById('byte-count');
73
73
function updateStats() {
74
74
const content = textarea.value;
75
-
const lines = content === "" ? 0 : content.split("\n").length;
75
+
const lines = content === '' ? 0 : content.split('\n').length;
76
76
const bytes = new TextEncoder().encode(content).length;
77
-
lineCount.textContent = `${lines} line${lines !== 1 ? "s" : ""}`;
78
-
byteCount.textContent = `${bytes} byte${bytes !== 1 ? "s" : ""}`;
77
+
lineCount.textContent = `${lines} line${lines !== 1 ? 's' : ''}`;
78
+
byteCount.textContent = `${bytes} byte${bytes !== 1 ? 's' : ''}`;
79
79
}
80
-
textarea.addEventListener("input", updateStats);
81
-
textarea.addEventListener("paste", () => {
80
+
textarea.addEventListener('input', updateStats);
81
+
textarea.addEventListener('paste', () => {
82
82
setTimeout(updateStats, 0);
83
83
});
84
84
updateStats();
+21
-40
appview/pages/templates/strings/string.html
+21
-40
appview/pages/templates/strings/string.html
···
1
-
{{ define "title" }}
2
-
{{ .String.Filename }} · by
3
-
{{ didOrHandle .Owner.DID.String .Owner.Handle.String }}
4
-
{{ end }}
1
+
{{ define "title" }}{{ .String.Filename }} · by {{ didOrHandle .Owner.DID.String .Owner.Handle.String }}{{ end }}
5
2
6
3
{{ define "extrameta" }}
7
4
{{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }}
8
-
<meta
9
-
property="og:title"
10
-
content="{{ .String.Filename }} · by {{ $ownerId }}" />
5
+
<meta property="og:title" content="{{ .String.Filename }} · by {{ $ownerId }}" />
11
6
<meta property="og:type" content="object" />
12
-
<meta
13
-
property="og:url"
14
-
content="https://tangled.sh/strings/{{ $ownerId }}/{{ .String.Rkey }}" />
7
+
<meta property="og:url" content="https://tangled.sh/strings/{{ $ownerId }}/{{ .String.Rkey }}" />
15
8
<meta property="og:description" content="{{ .String.Description }}" />
16
9
{{ end }}
17
10
···
20
13
{{ end }}
21
14
22
15
{{ define "content" }}
23
-
{{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }}
16
+
{{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }}
24
17
<section id="string-header" class="mb-4 py-2 px-6 dark:text-white">
25
18
<div class="text-lg flex items-center justify-between">
26
19
<div>
27
20
<a href="/strings/{{ $ownerId }}">{{ $ownerId }}</a>
28
21
<span class="select-none">/</span>
29
-
<a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}" class="font-bold">
30
-
{{ .String.Filename }}
31
-
</a>
22
+
<a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}" class="font-bold">{{ .String.Filename }}</a>
32
23
</div>
33
24
{{ if and .LoggedInUser (eq .LoggedInUser.Did .String.Did) }}
34
25
<div class="flex gap-2 text-base">
35
-
<a
36
-
class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
37
-
hx-boost="true"
38
-
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit">
26
+
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
27
+
hx-boost="true"
28
+
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit">
39
29
{{ i "pencil" "size-4" }}
40
-
<span class="hidden md:inline">edit</span>
30
+
<span class="hidden md:inline">edit</span>
41
31
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
42
32
</a>
43
33
<button
···
45
35
title="Delete string"
46
36
hx-delete="/strings/{{ .String.Did }}/{{ .String.Rkey }}/"
47
37
hx-swap="none"
48
-
hx-confirm="Are you sure you want to delete the gist `{{ .String.Filename }}`?">
38
+
hx-confirm="Are you sure you want to delete the gist `{{ .String.Filename }}`?"
39
+
>
49
40
{{ i "trash-2" "size-4" }}
50
-
<span class="hidden md:inline">delete</span>
41
+
<span class="hidden md:inline">delete</span>
51
42
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
52
43
</button>
53
44
</div>
···
59
50
{{ end }}
60
51
</span>
61
52
</section>
62
-
<section
63
-
class="bg-white dark:bg-gray-800 px-6 py-4 rounded relative w-full dark:text-white">
64
-
<div
65
-
class="flex justify-between items-center text-gray-500 dark:text-gray-400 text-sm md:text-base pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
53
+
<section class="bg-white dark:bg-gray-800 px-6 py-4 rounded relative w-full dark:text-white">
54
+
<div class="flex justify-between items-center text-gray-500 dark:text-gray-400 text-sm md:text-base pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
66
55
<span>
67
56
{{ .String.Filename }}
68
57
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
69
58
<span>
70
59
{{ with .String.Edited }}
71
-
edited
72
-
{{ template "repo/fragments/shortTimeAgo" . }}
60
+
edited {{ template "repo/fragments/shortTimeAgo" . }}
73
61
{{ else }}
74
62
{{ template "repo/fragments/shortTimeAgo" .String.Created }}
75
63
{{ end }}
···
82
70
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
83
71
<a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}/raw">view raw</a>
84
72
{{ if .RenderToggle }}
85
-
<span
86
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
87
-
<a href="?code={{ .ShowRendered }}" hx-boost="true">
88
-
view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}
89
-
</a>
73
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
74
+
<a href="?code={{ .ShowRendered }}" hx-boost="true">
75
+
view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}
76
+
</a>
90
77
{{ end }}
91
78
</div>
92
79
</div>
93
80
<div class="overflow-auto relative">
94
81
{{ if .ShowRendered }}
95
-
<div id="blob-contents" class="prose dark:prose-invert">
96
-
{{ .RenderedContents }}
97
-
</div>
82
+
<div id="blob-contents" class="prose dark:prose-invert">{{ .RenderedContents }}</div>
98
83
{{ else }}
99
-
<div
100
-
id="blob-contents"
101
-
class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">
102
-
{{ .String.Contents | escapeHtml }}
103
-
</div>
84
+
<div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ .String.Contents | escapeHtml }}</div>
104
85
{{ end }}
105
86
</div>
106
87
</section>
+84
-119
appview/pages/templates/timeline.html
+84
-119
appview/pages/templates/timeline.html
···
1
1
{{ define "title" }}timeline{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
<meta property="og:title" content="timeline · tangled" />
5
-
<meta property="og:type" content="object" />
6
-
<meta property="og:url" content="https://tangled.sh" />
7
-
<meta property="og:description" content="see what's tangling" />
4
+
<meta property="og:title" content="timeline · tangled" />
5
+
<meta property="og:type" content="object" />
6
+
<meta property="og:url" content="https://tangled.sh" />
7
+
<meta property="og:description" content="see what's tangling" />
8
8
{{ end }}
9
9
10
10
{{ define "topbar" }}
···
12
12
{{ end }}
13
13
14
14
{{ define "content" }}
15
-
{{ with .LoggedInUser }}
16
-
{{ block "timeline" $ }}{{ end }}
17
-
{{ else }}
18
-
{{ block "hero" $ }}{{ end }}
19
-
{{ block "timeline" $ }}{{ end }}
20
-
{{ end }}
15
+
{{ with .LoggedInUser }}
16
+
{{ block "timeline" $ }}{{ end }}
17
+
{{ else }}
18
+
{{ block "hero" $ }}{{ end }}
19
+
{{ block "timeline" $ }}{{ end }}
20
+
{{ end }}
21
21
{{ end }}
22
22
23
23
{{ define "hero" }}
24
-
<div class="flex flex-col text-black dark:text-white p-6 gap-6 max-w-xl">
25
-
<div class="font-bold text-4xl">
26
-
tightly-knit
27
-
<br />
28
-
social coding.
29
-
</div>
24
+
<div class="flex flex-col text-black dark:text-white p-6 gap-6 max-w-xl">
25
+
<div class="font-bold text-4xl">tightly-knit<br>social coding.</div>
30
26
31
-
<p class="text-lg">
32
-
tangled is new social-enabled git collaboration platform built on
33
-
<a class="underline" href="https://atproto.com/">atproto</a>
34
-
.
35
-
</p>
36
-
<p class="text-lg">
37
-
we envision a place where developers have complete ownership of their
38
-
code, open source communities can freely self-govern and most importantly,
39
-
coding can be social and fun again.
40
-
</p>
27
+
<p class="text-lg">
28
+
tangled is new social-enabled git collaboration platform built on <a class="underline" href="https://atproto.com/">atproto</a>.
29
+
</p>
30
+
<p class="text-lg">
31
+
we envision a place where developers have complete ownership of their
32
+
code, open source communities can freely self-govern and most
33
+
importantly, coding can be social and fun again.
34
+
</p>
41
35
42
-
<div class="flex gap-6 items-center">
43
-
<a href="/signup" class="no-underline hover:no-underline ">
44
-
<button class="btn-create flex gap-2 px-4 items-center">
45
-
join now
46
-
{{ i "arrow-right" "size-4" }}
47
-
</button>
48
-
</a>
36
+
<div class="flex gap-6 items-center">
37
+
<a href="/signup" class="no-underline hover:no-underline ">
38
+
<button class="btn-create flex gap-2 px-4 items-center">
39
+
join now {{ i "arrow-right" "size-4" }}
40
+
</button>
41
+
</a>
42
+
</div>
49
43
</div>
50
-
</div>
51
44
{{ end }}
52
45
53
46
{{ define "timeline" }}
54
-
<div>
55
-
<div class="p-6">
56
-
<p class="text-xl font-bold dark:text-white">Timeline</p>
57
-
</div>
47
+
<div>
48
+
<div class="p-6">
49
+
<p class="text-xl font-bold dark:text-white">Timeline</p>
50
+
</div>
58
51
59
-
<div class="flex flex-col gap-4">
60
-
{{ range $i, $e := .Timeline }}
61
-
<div class="relative">
62
-
{{ if ne $i 0 }}
63
-
<div
64
-
class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
65
-
{{ end }}
66
-
{{ with $e }}
67
-
<div
68
-
class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
69
-
{{ if .Repo }}
70
-
{{ block "repoEvent" (list $ .Repo .Source) }}{{ end }}
71
-
{{ else if .Star }}
72
-
{{ block "starEvent" (list $ .Star) }}{{ end }}
73
-
{{ else if .Follow }}
74
-
{{ block "followEvent" (list $ .Follow .Profile .FollowStats) }}
75
-
{{ end }}
52
+
<div class="flex flex-col gap-4">
53
+
{{ range $i, $e := .Timeline }}
54
+
<div class="relative">
55
+
{{ if ne $i 0 }}
56
+
<div class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
57
+
{{ end }}
58
+
{{ with $e }}
59
+
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
60
+
{{ if .Repo }}
61
+
{{ block "repoEvent" (list $ .Repo .Source) }} {{ end }}
62
+
{{ else if .Star }}
63
+
{{ block "starEvent" (list $ .Star) }} {{ end }}
64
+
{{ else if .Follow }}
65
+
{{ block "followEvent" (list $ .Follow .Profile .FollowStats) }} {{ end }}
66
+
{{ end }}
67
+
</div>
76
68
{{ end }}
77
69
</div>
78
70
{{ end }}
79
71
</div>
80
-
{{ end }}
81
72
</div>
82
-
</div>
83
73
{{ end }}
84
74
85
75
{{ define "repoEvent" }}
···
87
77
{{ $repo := index . 1 }}
88
78
{{ $source := index . 2 }}
89
79
{{ $userHandle := resolve $repo.Did }}
90
-
<div
91
-
class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
92
-
{{ template "user/fragments/picHandleLink" $repo.Did }}
93
-
{{ with $source }}
94
-
{{ $sourceDid := resolve .Did }}
95
-
forked
96
-
<a
97
-
href="/{{ $sourceDid }}/{{ .Name }}"
98
-
class="no-underline hover:underline">
99
-
{{ $sourceDid }}/{{ .Name }}
100
-
</a>
101
-
to
102
-
<a
103
-
href="/{{ $userHandle }}/{{ $repo.Name }}"
104
-
class="no-underline hover:underline">
105
-
{{ $repo.Name }}
106
-
</a>
107
-
{{ else }}
108
-
created
109
-
<a
110
-
href="/{{ $userHandle }}/{{ $repo.Name }}"
111
-
class="no-underline hover:underline">
112
-
{{ $repo.Name }}
113
-
</a>
114
-
{{ end }}
115
-
<span class="text-gray-700 dark:text-gray-400 text-xs">
116
-
{{ template "repo/fragments/time" $repo.Created }}
117
-
</span>
118
-
</div>
80
+
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
81
+
{{ template "user/fragments/picHandleLink" $repo.Did }}
82
+
{{ with $source }}
83
+
{{ $sourceDid := resolve .Did }}
84
+
forked
85
+
<a href="/{{ $sourceDid }}/{{ .Name }}"class="no-underline hover:underline">
86
+
{{ $sourceDid }}/{{ .Name }}
87
+
</a>
88
+
to
89
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">{{ $repo.Name }}</a>
90
+
{{ else }}
91
+
created
92
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">
93
+
{{ $repo.Name }}
94
+
</a>
95
+
{{ end }}
96
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $repo.Created }}</span>
97
+
</div>
119
98
{{ with $repo }}
120
99
{{ template "user/fragments/repoCard" (list $root . true) }}
121
100
{{ end }}
···
127
106
{{ with $star }}
128
107
{{ $starrerHandle := resolve .StarredByDid }}
129
108
{{ $repoOwnerHandle := resolve .Repo.Did }}
130
-
<div
131
-
class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
132
-
{{ template "user/fragments/picHandleLink" $starrerHandle }}
133
-
starred
134
-
<a
135
-
href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}"
136
-
class="no-underline hover:underline">
137
-
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
138
-
</a>
139
-
<span class="text-gray-700 dark:text-gray-400 text-xs">
140
-
{{ template "repo/fragments/time" .Created }}
141
-
</span>
109
+
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
110
+
{{ template "user/fragments/picHandleLink" $starrerHandle }}
111
+
starred
112
+
<a href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">
113
+
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
114
+
</a>
115
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" .Created }}</span>
142
116
</div>
143
117
{{ with .Repo }}
144
118
{{ template "user/fragments/repoCard" (list $root . true) }}
145
119
{{ end }}
146
120
{{ end }}
147
121
{{ end }}
122
+
148
123
149
124
{{ define "followEvent" }}
150
125
{{ $root := index . 0 }}
···
154
129
155
130
{{ $userHandle := resolve $follow.UserDid }}
156
131
{{ $subjectHandle := resolve $follow.SubjectDid }}
157
-
<div
158
-
class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
159
-
{{ template "user/fragments/picHandleLink" $userHandle }}
160
-
followed
161
-
{{ template "user/fragments/picHandleLink" $subjectHandle }}
162
-
<span class="text-gray-700 dark:text-gray-400 text-xs">
163
-
{{ template "repo/fragments/time" $follow.FollowedAt }}
164
-
</span>
132
+
<div class="pl-6 py-2 bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300 flex flex-wrap items-center gap-2 text-sm">
133
+
{{ template "user/fragments/picHandleLink" $userHandle }}
134
+
followed
135
+
{{ template "user/fragments/picHandleLink" $subjectHandle }}
136
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $follow.FollowedAt }}</span>
165
137
</div>
166
-
<div
167
-
class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
138
+
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
168
139
<div class="flex-shrink-0 max-h-full w-24 h-24">
169
-
<img
170
-
class="object-cover rounded-full p-2"
171
-
src="{{ fullAvatar $subjectHandle }}" />
140
+
<img class="object-cover rounded-full p-2" src="{{ fullAvatar $subjectHandle }}" />
172
141
</div>
173
142
174
143
<div class="flex-1 min-h-0 justify-around flex flex-col">
175
144
<a href="/{{ $subjectHandle }}">
176
-
<span
177
-
class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
178
-
{{ $subjectHandle | truncateAt30 }}
179
-
</span>
145
+
<span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $subjectHandle | truncateAt30 }}</span>
180
146
</a>
181
147
{{ with $profile }}
182
148
{{ with .Description }}
183
-
<p class="text-sm pb-2 md:pb-2">{{ . }}</p>
149
+
<p class="text-sm pb-2 md:pb-2">{{.}}</p>
184
150
{{ end }}
185
151
{{ end }}
186
152
{{ with $stat }}
187
-
<div
188
-
class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
153
+
<div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
189
154
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
190
155
<span id="followers">{{ .Followers }} followers</span>
191
156
<span class="select-none after:content-['·']"></span>
192
-
<span id="following">{{ .Following }} following</span>
157
+
<span id="following">{{ .Following }} following</span>
193
158
</div>
194
159
{{ end }}
195
160
</div>
+99
-83
appview/pages/templates/user/completeSignup.html
+99
-83
appview/pages/templates/user/completeSignup.html
···
1
1
{{ define "user/completeSignup" }}
2
-
<!doctype html>
3
-
<html lang="en" class="dark:bg-gray-900">
4
-
<head>
5
-
<meta charset="UTF-8" />
6
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
-
<meta property="og:title" content="complete signup · tangled" />
8
-
<meta property="og:url" content="https://tangled.sh/complete-signup" />
9
-
<meta
10
-
property="og:description"
11
-
content="complete your signup for tangled" />
12
-
<script src="/static/htmx.min.js"></script>
13
-
<link
14
-
rel="stylesheet"
15
-
href="/static/tw.css?{{ cssContentHash }}"
16
-
type="text/css" />
17
-
<title>complete signup · tangled</title>
18
-
</head>
19
-
<body class="flex items-center justify-center min-h-screen">
20
-
<main class="max-w-md px-6 -mt-4">
21
-
<h1 class="text-center text-2xl font-semibold italic dark:text-white">
22
-
tangled
23
-
</h1>
24
-
<h2 class="text-center text-xl italic dark:text-white">
25
-
tightly-knit social coding.
26
-
</h2>
27
-
<form
28
-
class="mt-4 max-w-sm mx-auto flex flex-col gap-4"
29
-
hx-post="/signup/complete"
30
-
hx-swap="none"
31
-
hx-disabled-elt="#complete-signup-button">
32
-
<div class="flex flex-col">
33
-
<label for="code">verification code</label>
34
-
<input
35
-
type="text"
36
-
id="code"
37
-
name="code"
38
-
tabindex="1"
39
-
required
40
-
placeholder="tngl-sh-foo-bar" />
41
-
<span class="text-sm text-gray-500 mt-1">
42
-
Enter the code sent to your email.
43
-
</span>
44
-
</div>
2
+
<!doctype html>
3
+
<html lang="en" class="dark:bg-gray-900">
4
+
<head>
5
+
<meta charset="UTF-8" />
6
+
<meta
7
+
name="viewport"
8
+
content="width=device-width, initial-scale=1.0"
9
+
/>
10
+
<meta
11
+
property="og:title"
12
+
content="complete signup · tangled"
13
+
/>
14
+
<meta
15
+
property="og:url"
16
+
content="https://tangled.sh/complete-signup"
17
+
/>
18
+
<meta
19
+
property="og:description"
20
+
content="complete your signup for tangled"
21
+
/>
22
+
<script src="/static/htmx.min.js"></script>
23
+
<link
24
+
rel="stylesheet"
25
+
href="/static/tw.css?{{ cssContentHash }}"
26
+
type="text/css"
27
+
/>
28
+
<title>complete signup · tangled</title>
29
+
</head>
30
+
<body class="flex items-center justify-center min-h-screen">
31
+
<main class="max-w-md px-6 -mt-4">
32
+
<h1
33
+
class="text-center text-2xl font-semibold italic dark:text-white"
34
+
>
35
+
tangled
36
+
</h1>
37
+
<h2 class="text-center text-xl italic dark:text-white">
38
+
tightly-knit social coding.
39
+
</h2>
40
+
<form
41
+
class="mt-4 max-w-sm mx-auto flex flex-col gap-4"
42
+
hx-post="/signup/complete"
43
+
hx-swap="none"
44
+
hx-disabled-elt="#complete-signup-button"
45
+
>
46
+
<div class="flex flex-col">
47
+
<label for="code">verification code</label>
48
+
<input
49
+
type="text"
50
+
id="code"
51
+
name="code"
52
+
tabindex="1"
53
+
required
54
+
placeholder="tngl-sh-foo-bar"
55
+
/>
56
+
<span class="text-sm text-gray-500 mt-1">
57
+
Enter the code sent to your email.
58
+
</span>
59
+
</div>
45
60
46
-
<div class="flex flex-col">
47
-
<label for="username">username</label>
48
-
<input
49
-
type="text"
50
-
id="username"
51
-
name="username"
52
-
tabindex="2"
53
-
required
54
-
placeholder="jason" />
55
-
<span class="text-sm text-gray-500 mt-1">
56
-
Your complete handle will be of the form
57
-
<code>user.tngl.sh</code>
58
-
.
59
-
</span>
60
-
</div>
61
+
<div class="flex flex-col">
62
+
<label for="username">username</label>
63
+
<input
64
+
type="text"
65
+
id="username"
66
+
name="username"
67
+
tabindex="2"
68
+
required
69
+
placeholder="jason"
70
+
/>
71
+
<span class="text-sm text-gray-500 mt-1">
72
+
Your complete handle will be of the form <code>user.tngl.sh</code>.
73
+
</span>
74
+
</div>
61
75
62
-
<div class="flex flex-col">
63
-
<label for="password">password</label>
64
-
<input
65
-
type="password"
66
-
id="password"
67
-
name="password"
68
-
tabindex="3"
69
-
required />
70
-
<span class="text-sm text-gray-500 mt-1">
71
-
Choose a strong password for your account.
72
-
</span>
73
-
</div>
76
+
<div class="flex flex-col">
77
+
<label for="password">password</label>
78
+
<input
79
+
type="password"
80
+
id="password"
81
+
name="password"
82
+
tabindex="3"
83
+
required
84
+
/>
85
+
<span class="text-sm text-gray-500 mt-1">
86
+
Choose a strong password for your account.
87
+
</span>
88
+
</div>
74
89
75
-
<button
76
-
class="btn-create w-full my-2 mt-6 text-base"
77
-
type="submit"
78
-
id="complete-signup-button"
79
-
tabindex="4">
80
-
<span>complete signup</span>
81
-
</button>
82
-
</form>
83
-
<p id="signup-error" class="error w-full"></p>
84
-
<p id="signup-msg" class="dark:text-white w-full"></p>
85
-
</main>
86
-
</body>
87
-
</html>
90
+
<button
91
+
class="btn-create w-full my-2 mt-6 text-base"
92
+
type="submit"
93
+
id="complete-signup-button"
94
+
tabindex="4"
95
+
>
96
+
<span>complete signup</span>
97
+
</button>
98
+
</form>
99
+
<p id="signup-error" class="error w-full"></p>
100
+
<p id="signup-msg" class="dark:text-white w-full"></p>
101
+
</main>
102
+
</body>
103
+
</html>
88
104
{{ end }}
+4
-12
appview/pages/templates/user/fragments/bluesky.html
+4
-12
appview/pages/templates/user/fragments/bluesky.html
···
1
1
{{ define "user/fragments/bluesky" }}
2
-
<svg
3
-
class="{{ . }}"
4
-
xmlns="http://www.w3.org/2000/svg"
5
-
role="img"
6
-
viewBox="-3 -3 30 30">
7
-
<title>Bluesky</title>
8
-
<path
9
-
fill="none"
10
-
stroke="currentColor"
11
-
d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z"
12
-
stroke-width="2.25" />
13
-
</svg>
2
+
<svg class="{{.}}" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="-3 -3 30 30">
3
+
<title>Bluesky</title>
4
+
<path fill="none" stroke="currentColor" d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z" stroke-width="2.25"/>
5
+
</svg>
14
6
{{ end }}
+29
-61
appview/pages/templates/user/fragments/editBio.html
+29
-61
appview/pages/templates/user/fragments/editBio.html
···
11
11
{{ $description = .Profile.Description }}
12
12
{{ end }}
13
13
<label class="m-0 p-0" for="description">bio</label>
14
-
<textarea
15
-
type="text"
16
-
class="py-1 px-1 w-full"
17
-
name="description"
14
+
<textarea
15
+
type="text"
16
+
class="py-1 px-1 w-full"
17
+
name="description"
18
18
rows="3"
19
-
placeholder="write a bio">
20
-
{{ $description }}</textarea
21
-
>
19
+
placeholder="write a bio">{{ $description }}</textarea>
22
20
</div>
23
21
24
22
<div class="flex flex-col gap-1">
···
29
27
{{ $location = .Profile.Location }}
30
28
{{ end }}
31
29
<span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span>
32
-
<input
33
-
type="text"
34
-
class="py-1 px-1 w-full"
35
-
name="location"
36
-
value="{{ $location }}" />
30
+
<input type="text" class="py-1 px-1 w-full" name="location" value="{{ $location }}">
37
31
</div>
38
32
</div>
39
33
···
44
38
{{ if and .Profile .Profile.IncludeBluesky }}
45
39
{{ $includeBsky = true }}
46
40
{{ end }}
47
-
<input
48
-
type="checkbox"
49
-
id="includeBluesky"
50
-
name="includeBluesky"
51
-
value="on"
52
-
{{ if $includeBsky }}checked{{ end }} />
53
-
<label for="includeBluesky" class="my-0 py-0 normal-case font-normal">
54
-
Link to Bluesky account
55
-
</label>
41
+
<input type="checkbox" id="includeBluesky" name="includeBluesky" value="on" {{if $includeBsky}}checked{{end}}>
42
+
<label for="includeBluesky" class="my-0 py-0 normal-case font-normal">Link to Bluesky account</label>
56
43
</div>
57
44
58
45
{{ $profile := .Profile }}
···
64
51
{{ end }}
65
52
{{ end }}
66
53
67
-
68
54
<div class="flex items-center gap-2 w-full">
69
55
<span class="flex-shrink-0">{{ i "link" "size-4" }}</span>
70
-
<input
71
-
type="text"
72
-
class="py-1 px-1 w-full"
73
-
name="link{{ $idx }}"
74
-
value="{{ $link }}"
75
-
placeholder="social link {{ add $idx 1 }}" />
56
+
<input type="text" class="py-1 px-1 w-full" name="link{{$idx}}" value="{{ $link }}" placeholder="social link {{add $idx 1}}">
76
57
</div>
77
58
{{ end }}
78
59
</div>
···
80
61
<div class="flex flex-col gap-1">
81
62
<label class="m-0 p-0">vanity stats</label>
82
63
{{ range $idx, $s := (sequence 2) }}
83
-
{{ $stat := "" }}
84
-
{{ if and $profile $profile.Stats }}
85
-
{{ if lt $idx (len $profile.Stats) }}
86
-
{{ $s := index $profile.Stats $idx }}
87
-
{{ $stat = $s.Kind }}
64
+
{{ $stat := "" }}
65
+
{{ if and $profile $profile.Stats }}
66
+
{{ if lt $idx (len $profile.Stats) }}
67
+
{{ $s := index $profile.Stats $idx }}
68
+
{{ $stat = $s.Kind }}
69
+
{{ end }}
88
70
{{ end }}
89
-
{{ end }}
90
71
91
-
{{ block "stat" (list $idx $stat) }}{{ end }}
72
+
{{ block "stat" (list $idx $stat) }} {{ end }}
92
73
{{ end }}
93
74
</div>
94
75
95
76
<div class="flex items-center gap-2 justify-between">
96
-
<button
97
-
id="save-btn"
98
-
type="submit"
99
-
class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
77
+
<button id="save-btn" type="submit" class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
100
78
{{ i "check" "size-4" }} save
101
79
<span id="spinner" class="group">
102
80
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
103
81
</span>
104
82
</button>
105
-
<a
106
-
href="/{{ .LoggedInUser.Did }}"
107
-
class="w-full no-underline hover:no-underline">
108
-
<button
109
-
id="cancel-btn"
110
-
type="button"
111
-
class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
83
+
<a href="/{{.LoggedInUser.Did}}" class="w-full no-underline hover:no-underline">
84
+
<button id="cancel-btn" type="button" class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
112
85
{{ i "x" "size-4" }} cancel
113
86
</button>
114
87
</a>
···
119
92
{{ define "stat" }}
120
93
{{ $id := index . 0 }}
121
94
{{ $stat := index . 1 }}
122
-
<select
123
-
class="stat-group w-full p-1 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700 text-sm"
124
-
id="stat{{ $id }}"
125
-
name="stat{{ $id }}">
95
+
<select class="stat-group w-full p-1 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700 text-sm" id="stat{{$id}}" name="stat{{$id}}">
126
96
<option value="">choose stat</option>
127
97
{{ $stats := assoc
128
-
"merged-pull-request-count" "Merged PR Count"
129
-
"closed-pull-request-count" "Closed PR Count"
130
-
"open-pull-request-count" "Open PR Count"
131
-
"open-issue-count" "Open Issue Count"
132
-
"closed-issue-count" "Closed Issue Count"
133
-
"repository-count" "Repository Count"
98
+
"merged-pull-request-count" "Merged PR Count"
99
+
"closed-pull-request-count" "Closed PR Count"
100
+
"open-pull-request-count" "Open PR Count"
101
+
"open-issue-count" "Open Issue Count"
102
+
"closed-issue-count" "Closed Issue Count"
103
+
"repository-count" "Repository Count"
134
104
}}
135
105
{{ range $s := $stats }}
136
-
{{ $value := index $s 0 }}
137
-
{{ $label := index $s 1 }}
138
-
<option value="{{ $value }}" {{ if eq $stat $value }}selected{{ end }}>
139
-
{{ $label }}
140
-
</option>
106
+
{{ $value := index $s 0 }}
107
+
{{ $label := index $s 1 }}
108
+
<option value="{{ $value }}"{{ if eq $stat $value }} selected{{ end }}>{{ $label }}</option>
141
109
{{ end }}
142
110
</select>
143
111
{{ end }}
+29
-48
appview/pages/templates/user/fragments/editPins.html
+29
-48
appview/pages/templates/user/fragments/editPins.html
···
1
1
{{ define "user/fragments/editPins" }}
2
2
{{ $profile := .Profile }}
3
-
<form
4
-
hx-post="/profile/pins"
5
-
hx-disabled-elt="#save-btn,#cancel-btn"
6
-
hx-swap="none"
7
-
hx-indicator="#spinner">
8
-
<div class="flex items-center justify-between mb-2">
9
-
<p class="text-sm font-bold p-2 dark:text-white">SELECT PINNED REPOS</p>
10
-
<div class="flex items-center gap-2">
11
-
<button
12
-
id="save-btn"
13
-
type="submit"
14
-
class="btn px-2 flex items-center gap-2 no-underline text-sm">
15
-
{{ i "check" "w-3 h-3" }} save
16
-
<span id="spinner" class="group">
17
-
{{ i "loader-circle" "w-3 h-3 animate-spin hidden group-[.htmx-request]:inline" }}
18
-
</span>
19
-
</button>
20
-
<a
21
-
href="/{{ .LoggedInUser.Did }}"
22
-
class="w-full no-underline hover:no-underline">
23
-
<button
24
-
id="cancel-btn"
25
-
type="button"
26
-
class="btn px-2 w-full flex items-center gap-2 no-underline text-sm">
27
-
{{ i "x" "w-3 h-3" }} cancel
3
+
<form
4
+
hx-post="/profile/pins"
5
+
hx-disabled-elt="#save-btn,#cancel-btn"
6
+
hx-swap="none"
7
+
hx-indicator="#spinner">
8
+
<div class="flex items-center justify-between mb-2">
9
+
<p class="text-sm font-bold p-2 dark:text-white">SELECT PINNED REPOS</p>
10
+
<div class="flex items-center gap-2">
11
+
<button id="save-btn" type="submit" class="btn px-2 flex items-center gap-2 no-underline text-sm">
12
+
{{ i "check" "w-3 h-3" }} save
13
+
<span id="spinner" class="group">
14
+
{{ i "loader-circle" "w-3 h-3 animate-spin hidden group-[.htmx-request]:inline" }}
15
+
</span>
28
16
</button>
29
-
</a>
17
+
<a href="/{{.LoggedInUser.Did}}" class="w-full no-underline hover:no-underline">
18
+
<button id="cancel-btn" type="button" class="btn px-2 w-full flex items-center gap-2 no-underline text-sm">
19
+
{{ i "x" "w-3 h-3" }} cancel
20
+
</button>
21
+
</a>
22
+
</div>
30
23
</div>
31
-
</div>
32
-
<div
33
-
id="repos"
34
-
class="grid grid-cols-1 gap-1 mb-6 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700">
35
-
{{ range $idx, $r := .AllRepos }}
36
-
<div
37
-
class="flex items-center gap-2 text-base p-2 border-b border-gray-200 dark:border-gray-700">
38
-
<input
39
-
type="checkbox"
40
-
id="repo-{{ $idx }}"
41
-
name="pinnedRepo{{ $idx }}"
42
-
value="{{ .RepoAt }}"
43
-
{{ if .IsPinned }}checked{{ end }} />
44
-
<label
45
-
for="repo-{{ $idx }}"
46
-
class="my-0 py-0 normal-case font-normal w-full">
24
+
<div id="repos" class="grid grid-cols-1 gap-1 mb-6 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700">
25
+
{{ range $idx, $r := .AllRepos }}
26
+
<div class="flex items-center gap-2 text-base p-2 border-b border-gray-200 dark:border-gray-700">
27
+
<input type="checkbox" id="repo-{{$idx}}" name="pinnedRepo{{$idx}}" value="{{.RepoAt}}" {{if .IsPinned}}checked{{end}}>
28
+
<label for="repo-{{$idx}}" class="my-0 py-0 normal-case font-normal w-full">
47
29
<div class="flex justify-between items-center w-full">
48
-
<span class="flex-shrink-0 overflow-hidden text-ellipsis ">
49
-
{{ resolve .Did }}/{{ .Name }}
50
-
</span>
30
+
<span class="flex-shrink-0 overflow-hidden text-ellipsis ">{{ resolve .Did }}/{{.Name}}</span>
51
31
<div class="flex gap-1 items-center">
52
32
{{ i "star" "size-4 fill-current" }}
53
33
<span>{{ .RepoStats.StarCount }}</span>
···
55
35
</div>
56
36
</label>
57
37
</div>
58
-
{{ end }}
59
-
</div>
60
-
</form>
38
+
{{ end }}
39
+
</div>
40
+
41
+
</form>
61
42
{{ end }}
+7
-10
appview/pages/templates/user/fragments/follow.html
+7
-10
appview/pages/templates/user/fragments/follow.html
···
1
1
{{ define "user/fragments/follow" }}
2
-
<button
3
-
id="followBtn"
2
+
<button id="followBtn"
4
3
class="btn mt-2 w-full flex gap-2 items-center group"
4
+
5
5
{{ if eq .FollowStatus.String "IsNotFollowing" }}
6
-
hx-post="/follow?subject={{ .UserDid }}"
6
+
hx-post="/follow?subject={{.UserDid}}"
7
7
{{ else }}
8
-
hx-delete="/follow?subject={{ .UserDid }}"
8
+
hx-delete="/follow?subject={{.UserDid}}"
9
9
{{ end }}
10
10
11
11
hx-trigger="click"
12
12
hx-target="#followBtn"
13
-
hx-swap="outerHTML">
14
-
{{ if eq .FollowStatus.String "IsNotFollowing" }}
15
-
Follow
16
-
{{ else }}
17
-
Unfollow
18
-
{{ end }}
13
+
hx-swap="outerHTML"
14
+
>
15
+
{{ if eq .FollowStatus.String "IsNotFollowing" }}Follow{{ else }}Unfollow{{ end }}
19
16
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
20
17
</button>
21
18
{{ end }}
+4
-3
appview/pages/templates/user/fragments/picHandle.html
+4
-3
appview/pages/templates/user/fragments/picHandle.html
···
1
1
{{ define "user/fragments/picHandle" }}
2
-
<img
2
+
<img
3
3
src="{{ tinyAvatar . }}"
4
4
alt="{{ . }}"
5
-
class="rounded-full h-6 w-6 mr-1 border border-gray-300 dark:border-gray-700" />
6
-
{{ . | truncateAt30 }}
5
+
class="rounded-full h-6 w-6 mr-1 border border-gray-300 dark:border-gray-700"
6
+
/>
7
+
{{ . | truncateAt30 }}
7
8
{{ end }}
+3
-3
appview/pages/templates/user/fragments/picHandleLink.html
+3
-3
appview/pages/templates/user/fragments/picHandleLink.html
···
1
1
{{ define "user/fragments/picHandleLink" }}
2
-
{{ $resolved := resolve . }}
3
-
<a href="/{{ $resolved }}" class="flex items-center">
2
+
{{ $resolved := resolve . }}
3
+
<a href="/{{ $resolved }}" class="flex items-center">
4
4
{{ template "user/fragments/picHandle" $resolved }}
5
-
</a>
5
+
</a>
6
6
{{ end }}
+44
-59
appview/pages/templates/user/fragments/profileCard.html
+44
-59
appview/pages/templates/user/fragments/profileCard.html
···
1
1
{{ define "user/fragments/profileCard" }}
2
-
<div
3
-
class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm max-h-fit">
2
+
<div class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm max-h-fit">
4
3
<div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center">
5
4
<div id="avatar" class="col-span-1 flex justify-center items-center">
6
5
<div class="w-3/4 aspect-square relative">
7
-
<img
8
-
class="absolute inset-0 w-full h-full object-cover rounded-full p-2"
9
-
src="{{ fullAvatar .UserDid }}" />
6
+
<img class="absolute inset-0 w-full h-full object-cover rounded-full p-2" src="{{ fullAvatar .UserDid }}" />
10
7
</div>
11
8
</div>
12
9
<div class="col-span-2">
13
10
<div class="flex items-center flex-row flex-nowrap gap-2">
14
-
<p
15
-
title="{{ didOrHandle .UserDid .UserHandle }}"
16
-
class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap">
11
+
<p title="{{ didOrHandle .UserDid .UserHandle }}"
12
+
class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap">
17
13
{{ didOrHandle .UserDid .UserHandle }}
18
14
</p>
19
-
<a href="/{{ didOrHandle .UserDid .UserHandle }}/feed.atom">
20
-
{{ i "rss" "size-4" }}
21
-
</a>
15
+
<a href="/{{ didOrHandle .UserDid .UserHandle }}/feed.atom">{{ i "rss" "size-4" }}</a>
22
16
</div>
23
17
24
18
<div class="md:hidden">
25
-
{{ block "followerFollowing" (list .Followers .Following) }}{{ end }}
19
+
{{ block "followerFollowing" (list .Followers .Following) }} {{ end }}
26
20
</div>
27
21
</div>
28
22
<div class="col-span-3 md:col-span-full">
29
23
<div id="profile-bio" class="text-sm">
30
24
{{ $profile := .Profile }}
31
25
{{ with .Profile }}
32
-
{{ if .Description }}
33
-
<p class="text-base pb-4 md:pb-2">{{ .Description }}</p>
34
-
{{ end }}
35
26
27
+
{{ if .Description }}
28
+
<p class="text-base pb-4 md:pb-2">{{ .Description }}</p>
29
+
{{ end }}
36
30
37
-
<div class="hidden md:block">
38
-
{{ block "followerFollowing" (list $.Followers $.Following) }}
39
-
{{ end }}
31
+
<div class="hidden md:block">
32
+
{{ block "followerFollowing" (list $.Followers $.Following) }} {{ end }}
33
+
</div>
34
+
35
+
<div class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
36
+
{{ if .Location }}
37
+
<div class="flex items-center gap-2">
38
+
<span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span>
39
+
<span>{{ .Location }}</span>
40
40
</div>
41
-
42
-
<div
43
-
class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
44
-
{{ if .Location }}
45
-
<div class="flex items-center gap-2">
46
-
<span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span>
47
-
<span>{{ .Location }}</span>
48
-
</div>
41
+
{{ end }}
42
+
{{ if .IncludeBluesky }}
43
+
<div class="flex items-center gap-2">
44
+
<span class="flex-shrink-0">{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" }}</span>
45
+
<a id="bluesky-link" href="https://bsky.app/profile/{{ $.UserDid }}">{{ didOrHandle $.UserDid $.UserHandle }}</a>
46
+
</div>
47
+
{{ end }}
48
+
{{ range $link := .Links }}
49
+
{{ if $link }}
50
+
<div class="flex items-center gap-2">
51
+
<span class="flex-shrink-0">{{ i "link" "size-4" }}</span>
52
+
<a href="{{ $link }}">{{ $link }}</a>
53
+
</div>
49
54
{{ end }}
50
-
{{ if .IncludeBluesky }}
51
-
<div class="flex items-center gap-2">
52
-
<span class="flex-shrink-0">
53
-
{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" }}
54
-
</span>
55
-
<a
56
-
id="bluesky-link"
57
-
href="https://bsky.app/profile/{{ $.UserDid }}">
58
-
{{ didOrHandle $.UserDid $.UserHandle }}
59
-
</a>
60
-
</div>
61
-
{{ end }}
62
-
{{ range $link := .Links }}
63
-
{{ if $link }}
64
-
<div class="flex items-center gap-2">
65
-
<span class="flex-shrink-0">{{ i "link" "size-4" }}</span>
66
-
<a href="{{ $link }}">{{ $link }}</a>
55
+
{{ end }}
56
+
{{ if not $profile.IsStatsEmpty }}
57
+
<div class="flex items-center justify-evenly gap-2 py-2">
58
+
{{ range $stat := .Stats }}
59
+
{{ if $stat.Kind }}
60
+
<div class="flex flex-col items-center gap-2">
61
+
<span class="text-xl font-bold">{{ $stat.Value }}</span>
62
+
<span>{{ $stat.Kind.String }}</span>
67
63
</div>
68
64
{{ end }}
69
65
{{ end }}
70
-
{{ if not $profile.IsStatsEmpty }}
71
-
<div class="flex items-center justify-evenly gap-2 py-2">
72
-
{{ range $stat := .Stats }}
73
-
{{ if $stat.Kind }}
74
-
<div class="flex flex-col items-center gap-2">
75
-
<span class="text-xl font-bold">{{ $stat.Value }}</span>
76
-
<span>{{ $stat.Kind.String }}</span>
77
-
</div>
78
-
{{ end }}
79
-
{{ end }}
80
-
</div>
81
-
{{ end }}
82
66
</div>
67
+
{{ end }}
68
+
</div>
83
69
{{ end }}
84
70
{{ if ne .FollowStatus.String "IsSelf" }}
85
71
{{ template "user/fragments/follow" . }}
86
72
{{ else }}
87
-
<button
88
-
id="editBtn"
73
+
<button id="editBtn"
89
74
class="btn mt-2 w-full flex items-center gap-2 group"
90
75
hx-target="#profile-bio"
91
76
hx-get="/profile/edit-bio"
···
105
90
{{ define "followerFollowing" }}
106
91
{{ $followers := index . 0 }}
107
92
{{ $following := index . 1 }}
108
-
<div
109
-
class="flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
93
+
<div class="flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
110
94
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
111
95
<span id="followers">{{ $followers }} followers</span>
112
96
<span class="select-none after:content-['·']"></span>
113
97
<span id="following">{{ $following }} following</span>
114
98
</div>
115
99
{{ end }}
100
+
+3
-7
appview/pages/templates/user/fragments/repoCard.html
+3
-7
appview/pages/templates/user/fragments/repoCard.html
···
4
4
{{ $fullName := index . 2 }}
5
5
6
6
{{ with $repo }}
7
-
<div
8
-
class="py-4 px-6 gap-2 flex flex-col drop-shadow-sm rounded bg-white dark:bg-gray-800">
7
+
<div class="py-4 px-6 gap-2 flex flex-col drop-shadow-sm rounded bg-white dark:bg-gray-800">
9
8
<div class="font-medium dark:text-white flex items-center">
10
9
{{ if .Source }}
11
10
{{ i "git-fork" "w-4 h-4 mr-1.5 shrink-0" }}
···
15
14
16
15
{{ $repoOwner := resolve .Did }}
17
16
{{- if $fullName -}}
18
-
<a href="/{{ $repoOwner }}/{{ .Name }}">
19
-
{{ $repoOwner }}/{{ .Name }}
20
-
</a>
17
+
<a href="/{{ $repoOwner }}/{{ .Name }}">{{ $repoOwner }}/{{ .Name }}</a>
21
18
{{- else -}}
22
19
<a href="/{{ $repoOwner }}/{{ .Name }}">{{ .Name }}</a>
23
20
{{- end -}}
···
39
36
<div class="text-gray-400 text-sm font-mono inline-flex gap-4 mt-auto">
40
37
{{ with .Language }}
41
38
<div class="flex gap-2 items-center text-sm">
42
-
<div
43
-
class="size-2 rounded-full"
39
+
<div class="size-2 rounded-full"
44
40
style="background: radial-gradient(circle at 35% 35%, color-mix(in srgb, {{ langColor . }} 70%, white), {{ langColor . }} 30%, color-mix(in srgb, {{ langColor . }} 85%, black));"></div>
45
41
<span>{{ . }}</span>
46
42
</div>
+59
-67
appview/pages/templates/user/login.html
+59
-67
appview/pages/templates/user/login.html
···
1
1
{{ define "user/login" }}
2
-
<!doctype html>
3
-
<html lang="en" class="dark:bg-gray-900">
4
-
<head>
5
-
<meta charset="UTF-8" />
6
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
-
<meta property="og:title" content="login · tangled" />
8
-
<meta property="og:url" content="https://tangled.sh/login" />
9
-
<meta property="og:description" content="login to for tangled" />
10
-
<script src="/static/htmx.min.js"></script>
11
-
<link
12
-
rel="stylesheet"
13
-
href="/static/tw.css?{{ cssContentHash }}"
14
-
type="text/css" />
15
-
<title>login · tangled</title>
16
-
</head>
17
-
<body class="flex items-center justify-center min-h-screen">
18
-
<main class="max-w-md px-6 -mt-4">
19
-
<h1 class="text-center text-2xl font-semibold italic dark:text-white">
20
-
tangled
21
-
</h1>
22
-
<h2 class="text-center text-xl italic dark:text-white">
23
-
tightly-knit social coding.
24
-
</h2>
25
-
<form
26
-
class="mt-4 max-w-sm mx-auto"
27
-
hx-post="/login"
28
-
hx-swap="none"
29
-
hx-disabled-elt="#login-button">
30
-
<div class="flex flex-col">
31
-
<label for="handle">handle</label>
32
-
<input
33
-
type="text"
34
-
id="handle"
35
-
name="handle"
36
-
tabindex="1"
37
-
required
38
-
placeholder="akshay.tngl.sh" />
39
-
<span class="text-sm text-gray-500 mt-1">
40
-
Use your
41
-
<a href="https://atproto.com">ATProto</a>
42
-
handle to log in. If you're unsure, this is likely your Tangled (
43
-
<code>.tngl.sh</code>
44
-
) or
45
-
<a href="https://bsky.app">Bluesky</a>
46
-
(
47
-
<code>.bsky.social</code>
48
-
) account.
49
-
</span>
50
-
</div>
51
-
<input type="hidden" name="return_url" value="{{ .ReturnUrl }}" />
2
+
<!doctype html>
3
+
<html lang="en" class="dark:bg-gray-900">
4
+
<head>
5
+
<meta charset="UTF-8" />
6
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+
<meta property="og:title" content="login · tangled" />
8
+
<meta property="og:url" content="https://tangled.sh/login" />
9
+
<meta property="og:description" content="login to for tangled" />
10
+
<script src="/static/htmx.min.js"></script>
11
+
<link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" />
12
+
<title>login · tangled</title>
13
+
</head>
14
+
<body class="flex items-center justify-center min-h-screen">
15
+
<main class="max-w-md px-6 -mt-4">
16
+
<h1 class="text-center text-2xl font-semibold italic dark:text-white" >
17
+
tangled
18
+
</h1>
19
+
<h2 class="text-center text-xl italic dark:text-white">
20
+
tightly-knit social coding.
21
+
</h2>
22
+
<form
23
+
class="mt-4 max-w-sm mx-auto"
24
+
hx-post="/login"
25
+
hx-swap="none"
26
+
hx-disabled-elt="#login-button"
27
+
>
28
+
<div class="flex flex-col">
29
+
<label for="handle">handle</label>
30
+
<input
31
+
type="text"
32
+
id="handle"
33
+
name="handle"
34
+
tabindex="1"
35
+
required
36
+
placeholder="akshay.tngl.sh"
37
+
/>
38
+
<span class="text-sm text-gray-500 mt-1">
39
+
Use your <a href="https://atproto.com">ATProto</a>
40
+
handle to log in. If you're unsure, this is likely
41
+
your Tangled (<code>.tngl.sh</code>) or <a href="https://bsky.app">Bluesky</a> (<code>.bsky.social</code>) account.
42
+
</span>
43
+
</div>
44
+
<input type="hidden" name="return_url" value="{{ .ReturnUrl }}">
52
45
53
-
<button
54
-
class="btn w-full my-2 mt-6 text-base "
55
-
type="submit"
56
-
id="login-button"
57
-
tabindex="3">
58
-
<span>login</span>
59
-
</button>
60
-
</form>
61
-
<p class="text-sm text-gray-500">
62
-
Don't have an account?
63
-
<a href="/signup" class="underline">Create an account</a>
64
-
on Tangled now!
65
-
</p>
46
+
<button
47
+
class="btn w-full my-2 mt-6 text-base "
48
+
type="submit"
49
+
id="login-button"
50
+
tabindex="3"
51
+
>
52
+
<span>login</span>
53
+
</button>
54
+
</form>
55
+
<p class="text-sm text-gray-500">
56
+
Don't have an account? <a href="/signup" class="underline">Create an account</a> on Tangled now!
57
+
</p>
66
58
67
-
<p id="login-msg" class="error w-full"></p>
68
-
</main>
69
-
</body>
70
-
</html>
59
+
<p id="login-msg" class="error w-full"></p>
60
+
</main>
61
+
</body>
62
+
</html>
71
63
{{ end }}
+66
-112
appview/pages/templates/user/profile.html
+66
-112
appview/pages/templates/user/profile.html
···
1
1
{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
5
-
<meta property="og:type" content="profile" />
6
-
<meta
7
-
property="og:url"
8
-
content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
9
-
<meta
10
-
property="og:description"
11
-
content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
4
+
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
5
+
<meta property="og:type" content="profile" />
6
+
<meta property="og:url" content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
7
+
<meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
12
8
{{ end }}
13
9
14
10
{{ define "content" }}
15
-
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
11
+
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
16
12
<div class="md:col-span-3 order-1 md:order-1">
17
13
<div class="grid grid-cols-1 gap-4">
18
14
{{ template "user/fragments/profileCard" .Card }}
19
-
{{ block "punchcard" .Punchcard }}{{ end }}
15
+
{{ block "punchcard" .Punchcard }} {{ end }}
20
16
</div>
21
17
</div>
22
18
<div id="all-repos" class="md:col-span-4 order-2 md:order-2">
···
26
22
</div>
27
23
</div>
28
24
<div class="md:col-span-4 order-3 md:order-3">
29
-
{{ block "profileTimeline" . }}{{ end }}
25
+
{{ block "profileTimeline" . }}{{ end }}
30
26
</div>
31
-
</div>
27
+
</div>
32
28
{{ end }}
33
29
34
30
{{ define "profileTimeline" }}
···
37
33
{{ with .ProfileTimeline }}
38
34
{{ range $idx, $byMonth := .ByMonth }}
39
35
{{ with $byMonth }}
40
-
<div
41
-
class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm">
42
-
{{ if eq $idx 0 }}
36
+
<div class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm">
37
+
{{ if eq $idx 0 }}
43
38
44
-
{{ else }}
45
-
{{ $s := "s" }}
46
-
{{ if eq $idx 1 }}
47
-
{{ $s = "" }}
48
-
{{ end }}
49
-
<p class="text-sm font-bold dark:text-white mb-2">
50
-
{{ $idx }} month{{ $s }} ago
51
-
</p>
39
+
{{ else }}
40
+
{{ $s := "s" }}
41
+
{{ if eq $idx 1 }}
42
+
{{ $s = "" }}
52
43
{{ end }}
44
+
<p class="text-sm font-bold dark:text-white mb-2">{{$idx}} month{{$s}} ago</p>
45
+
{{ end }}
53
46
54
-
{{ if .IsEmpty }}
55
-
<div class="text-gray-500 dark:text-gray-400">
56
-
No activity for this month
57
-
</div>
58
-
{{ else }}
59
-
<div class="flex flex-col gap-1">
60
-
{{ block "repoEvents" .RepoEvents }}{{ end }}
61
-
{{ block "issueEvents" .IssueEvents }}{{ end }}
62
-
{{ block "pullEvents" .PullEvents }}{{ end }}
63
-
</div>
64
-
{{ end }}
65
-
</div>
47
+
{{ if .IsEmpty }}
48
+
<div class="text-gray-500 dark:text-gray-400">
49
+
No activity for this month
50
+
</div>
51
+
{{ else }}
52
+
<div class="flex flex-col gap-1">
53
+
{{ block "repoEvents" .RepoEvents }} {{ end }}
54
+
{{ block "issueEvents" .IssueEvents }} {{ end }}
55
+
{{ block "pullEvents" .PullEvents }} {{ end }}
56
+
</div>
57
+
{{ end }}
58
+
</div>
59
+
66
60
{{ end }}
67
61
{{ else }}
68
62
<p class="dark:text-white">This user does not have any activity yet.</p>
···
74
68
{{ define "repoEvents" }}
75
69
{{ if gt (len .) 0 }}
76
70
<details>
77
-
<summary
78
-
class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
71
+
<summary class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
79
72
<div class="flex flex-wrap items-center gap-2">
80
73
{{ i "book-plus" "w-4 h-4" }}
81
-
created
82
-
{{ len . }}
83
-
{{ if eq (len .) 1 }}repository{{ else }}repositories{{ end }}
74
+
created {{ len . }} {{if eq (len .) 1 }}repository{{else}}repositories{{end}}
84
75
</div>
85
76
</summary>
86
77
<div class="py-2 text-sm flex flex-col gap-3 mb-2">
···
93
84
{{ i "book-plus" "w-4 h-4" }}
94
85
{{ end }}
95
86
</span>
96
-
<a
97
-
href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}"
98
-
class="no-underline hover:underline">
87
+
<a href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}" class="no-underline hover:underline">
99
88
{{- .Repo.Name -}}
100
89
</a>
101
90
</div>
···
111
100
112
101
{{ if gt (len $items) 0 }}
113
102
<details>
114
-
<summary
115
-
class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
103
+
<summary class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
116
104
<div class="flex flex-wrap items-center gap-2">
117
105
{{ i "circle-dot" "w-4 h-4" }}
118
106
119
-
120
107
<div>
121
-
created
122
-
{{ len $items }}
123
-
{{ if eq (len $items) 1 }}issue{{ else }}issues{{ end }}
108
+
created {{ len $items }} {{if eq (len $items) 1 }}issue{{else}}issues{{end}}
124
109
</div>
125
110
126
111
{{ if gt $stats.Open 0 }}
127
-
<span
128
-
class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
129
-
{{ $stats.Open }} open
112
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
113
+
{{$stats.Open}} open
130
114
</span>
131
115
{{ end }}
132
116
133
117
{{ if gt $stats.Closed 0 }}
134
-
<span
135
-
class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
136
-
{{ $stats.Closed }} closed
137
-
</span>
118
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
119
+
{{$stats.Closed}} closed
120
+
</span>
138
121
{{ end }}
139
122
140
123
</div>
···
145
128
{{ $repoName := .Metadata.Repo.Name }}
146
129
{{ $repoUrl := printf "%s/%s" $repoOwner $repoName }}
147
130
148
-
149
131
<div class="flex gap-2 text-gray-600 dark:text-gray-300">
150
132
{{ if .Open }}
151
133
<span class="text-green-600 dark:text-green-500">
···
157
139
</span>
158
140
{{ end }}
159
141
<div class="flex-none min-w-8 text-right">
160
-
<span class="text-gray-500 dark:text-gray-400">
161
-
#{{ .IssueId }}
162
-
</span>
142
+
<span class="text-gray-500 dark:text-gray-400">#{{ .IssueId }}</span>
163
143
</div>
164
144
<div class="break-words max-w-full">
165
-
<a
166
-
href="/{{ $repoUrl }}/issues/{{ .IssueId }}"
167
-
class="no-underline hover:underline">
145
+
<a href="/{{$repoUrl}}/issues/{{ .IssueId }}" class="no-underline hover:underline">
168
146
{{ .Title -}}
169
147
</a>
170
148
on
171
-
<a
172
-
href="/{{ $repoUrl }}"
173
-
class="no-underline hover:underline whitespace-nowrap">
174
-
{{ $repoUrl }}
149
+
<a href="/{{$repoUrl}}" class="no-underline hover:underline whitespace-nowrap">
150
+
{{$repoUrl}}
175
151
</a>
176
152
</div>
177
153
</div>
···
186
162
{{ $stats := .Stats }}
187
163
{{ if gt (len $items) 0 }}
188
164
<details>
189
-
<summary
190
-
class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
165
+
<summary class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
191
166
<div class="flex flex-wrap items-center gap-2">
192
167
{{ i "git-pull-request" "w-4 h-4" }}
193
-
194
168
195
169
<div>
196
-
created
197
-
{{ len $items }}
198
-
{{ if eq (len $items) 1 }}
199
-
pull request
200
-
{{ else }}
201
-
pull requests
202
-
{{ end }}
170
+
created {{ len $items }} {{if eq (len $items) 1 }}pull request{{else}}pull requests{{end}}
203
171
</div>
204
172
205
173
{{ if gt $stats.Open 0 }}
206
-
<span
207
-
class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
208
-
{{ $stats.Open }} open
174
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
175
+
{{$stats.Open}} open
209
176
</span>
210
177
{{ end }}
211
178
212
179
{{ if gt $stats.Merged 0 }}
213
-
<span
214
-
class="px-2 py-1/2 text-sm rounded text-white bg-purple-600 dark:bg-purple-700">
215
-
{{ $stats.Merged }} merged
180
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-purple-600 dark:bg-purple-700">
181
+
{{$stats.Merged}} merged
216
182
</span>
217
183
{{ end }}
218
184
185
+
219
186
{{ if gt $stats.Closed 0 }}
220
-
<span
221
-
class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
222
-
{{ $stats.Closed }} closed
223
-
</span>
187
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
188
+
{{$stats.Closed}} closed
189
+
</span>
224
190
{{ end }}
225
191
226
192
</div>
···
231
197
{{ $repoName := .Repo.Name }}
232
198
{{ $repoUrl := printf "%s/%s" $repoOwner $repoName }}
233
199
234
-
235
200
<div class="flex gap-2 text-gray-600 dark:text-gray-300">
236
201
{{ if .State.IsOpen }}
237
202
<span class="text-green-600 dark:text-green-500">
···
247
212
</span>
248
213
{{ end }}
249
214
<div class="flex-none min-w-8 text-right">
250
-
<span class="text-gray-500 dark:text-gray-400">
251
-
#{{ .PullId }}
252
-
</span>
215
+
<span class="text-gray-500 dark:text-gray-400">#{{ .PullId }}</span>
253
216
</div>
254
217
<div class="break-words max-w-full">
255
-
<a
256
-
href="/{{ $repoUrl }}/pulls/{{ .PullId }}"
257
-
class="no-underline hover:underline">
218
+
<a href="/{{$repoUrl}}/pulls/{{ .PullId }}" class="no-underline hover:underline">
258
219
{{ .Title -}}
259
220
</a>
260
221
on
261
-
<a
262
-
href="/{{ $repoUrl }}"
263
-
class="no-underline hover:underline whitespace-nowrap">
264
-
{{ $repoUrl }}
222
+
<a href="/{{$repoUrl}}" class="no-underline hover:underline whitespace-nowrap">
223
+
{{$repoUrl}}
265
224
</a>
266
225
</div>
267
226
</div>
···
273
232
274
233
{{ define "ownRepos" }}
275
234
<div>
276
-
<div
277
-
class="text-sm font-bold p-2 pr-0 dark:text-white flex items-center justify-between gap-2">
278
-
<a
279
-
href="/@{{ or $.Card.UserHandle $.Card.UserDid }}?tab=repos"
235
+
<div class="text-sm font-bold p-2 pr-0 dark:text-white flex items-center justify-between gap-2">
236
+
<a href="/@{{ or $.Card.UserHandle $.Card.UserDid }}?tab=repos"
280
237
class="flex text-black dark:text-white items-center gap-2 no-underline hover:no-underline group">
281
238
<span>PINNED REPOS</span>
282
-
<span
283
-
class="flex gap-1 items-center font-normal text-sm text-gray-500 dark:text-gray-400 ">
284
-
view all
285
-
{{ i "chevron-right" "w-4 h-4" }}
239
+
<span class="flex gap-1 items-center font-normal text-sm text-gray-500 dark:text-gray-400 ">
240
+
view all {{ i "chevron-right" "w-4 h-4" }}
286
241
</span>
287
242
</a>
288
243
{{ if and .LoggedInUser (eq .LoggedInUser.Did .Card.UserDid) }}
289
-
<button
244
+
<button
290
245
hx-get="profile/edit-pins"
291
246
hx-target="#all-repos"
292
247
class="btn py-0 font-normal text-sm flex gap-2 items-center group">
···
300
255
{{ range .Repos }}
301
256
{{ template "user/fragments/repoCard" (list $ . false) }}
302
257
{{ else }}
303
-
<p class="px-6 dark:text-white">
304
-
This user does not have any repos yet.
305
-
</p>
258
+
<p class="px-6 dark:text-white">This user does not have any repos yet.</p>
306
259
{{ end }}
307
260
</div>
308
261
</div>
···
316
269
{{ range .CollaboratingRepos }}
317
270
{{ template "user/fragments/repoCard" (list $ . true) }}
318
271
{{ else }}
319
-
<p class="px-6 dark:text-white">This user is not collaborating.</p>
272
+
<p class="px-6 dark:text-white">This user is not collaborating.</p>
320
273
{{ end }}
321
274
</div>
322
275
</div>
···
355
308
<div class="w-full h-full flex justify-center items-center">
356
309
<div
357
310
class="aspect-square rounded-full transition-all duration-300 {{ $theme }} max-w-full max-h-full"
358
-
title="{{ .Date.Format "2006-01-02" }}: {{ .Count }} commits"></div>
311
+
title="{{ .Date.Format "2006-01-02" }}: {{ .Count }} commits">
312
+
</div>
359
313
</div>
360
314
{{ end }}
361
315
</div>
+11
-17
appview/pages/templates/user/repos.html
+11
-17
appview/pages/templates/user/repos.html
···
1
-
{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos{{ end }}
1
+
{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos {{ end }}
2
2
3
3
{{ define "extrameta" }}
4
-
<meta
5
-
property="og:title"
6
-
content="{{ or .Card.UserHandle .Card.UserDid }}'s repos" />
7
-
<meta property="og:type" content="object" />
8
-
<meta
9
-
property="og:url"
10
-
content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}/repos" />
11
-
<meta
12
-
property="og:description"
13
-
content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
4
+
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}'s repos" />
5
+
<meta property="og:type" content="object" />
6
+
<meta property="og:url" content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}/repos" />
7
+
<meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
14
8
{{ end }}
15
9
16
10
{{ define "content" }}
17
-
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
11
+
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
18
12
<div class="md:col-span-3 order-1 md:order-1">
19
-
{{ template "user/fragments/profileCard" .Card }}
13
+
{{ template "user/fragments/profileCard" .Card }}
20
14
</div>
21
15
<div id="all-repos" class="md:col-span-8 order-2 md:order-2">
22
-
{{ block "ownRepos" . }}{{ end }}
16
+
{{ block "ownRepos" . }}{{ end }}
23
17
</div>
24
-
</div>
18
+
</div>
25
19
{{ end }}
26
20
27
21
{{ define "ownRepos" }}
28
22
<p class="text-sm font-bold p-2 dark:text-white">ALL REPOSITORIES</p>
29
23
<div id="repos" class="grid grid-cols-1 gap-4 mb-6">
30
24
{{ range .Repos }}
31
-
{{ template "user/fragments/repoCard" (list $ . false) }}
25
+
{{ template "user/fragments/repoCard" (list $ . false) }}
32
26
{{ else }}
33
-
<p class="px-6 dark:text-white">This user does not have any repos yet.</p>
27
+
<p class="px-6 dark:text-white">This user does not have any repos yet.</p>
34
28
{{ end }}
35
29
</div>
36
30
{{ end }}
+50
-60
appview/pages/templates/user/signup.html
+50
-60
appview/pages/templates/user/signup.html
···
1
1
{{ define "user/signup" }}
2
-
<!doctype html>
3
-
<html lang="en" class="dark:bg-gray-900">
4
-
<head>
5
-
<meta charset="UTF-8" />
6
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
-
<meta property="og:title" content="signup · tangled" />
8
-
<meta property="og:url" content="https://tangled.sh/signup" />
9
-
<meta property="og:description" content="sign up for tangled" />
10
-
<script src="/static/htmx.min.js"></script>
11
-
<link
12
-
rel="stylesheet"
13
-
href="/static/tw.css?{{ cssContentHash }}"
14
-
type="text/css" />
15
-
<title>sign up · tangled</title>
16
-
</head>
17
-
<body class="flex items-center justify-center min-h-screen">
18
-
<main class="max-w-md px-6 -mt-4">
19
-
<h1 class="text-center text-2xl font-semibold italic dark:text-white">
20
-
tangled
21
-
</h1>
22
-
<h2 class="text-center text-xl italic dark:text-white">
23
-
tightly-knit social coding.
24
-
</h2>
25
-
<form
26
-
class="mt-4 max-w-sm mx-auto"
27
-
hx-post="/signup"
28
-
hx-swap="none"
29
-
hx-disabled-elt="#signup-button">
30
-
<div class="flex flex-col mt-2">
31
-
<label for="email">email</label>
32
-
<input
33
-
type="email"
34
-
id="email"
35
-
name="email"
36
-
tabindex="4"
37
-
required
38
-
placeholder="jason@bourne.co" />
39
-
</div>
40
-
<span class="text-sm text-gray-500 mt-1">
41
-
You will receive an email with an invite code. Enter your invite
42
-
code, desired username, and password in the next page to complete
43
-
your registration.
44
-
</span>
45
-
<button
46
-
class="btn text-base w-full my-2 mt-6"
47
-
type="submit"
48
-
id="signup-button"
49
-
tabindex="7">
50
-
<span>join now</span>
51
-
</button>
52
-
</form>
53
-
<p class="text-sm text-gray-500">
54
-
Already have an ATProto account?
55
-
<a href="/login" class="underline">Login to Tangled</a>
56
-
.
57
-
</p>
2
+
<!doctype html>
3
+
<html lang="en" class="dark:bg-gray-900">
4
+
<head>
5
+
<meta charset="UTF-8" />
6
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+
<meta property="og:title" content="signup · tangled" />
8
+
<meta property="og:url" content="https://tangled.sh/signup" />
9
+
<meta property="og:description" content="sign up for tangled" />
10
+
<script src="/static/htmx.min.js"></script>
11
+
<link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" />
12
+
<title>sign up · tangled</title>
13
+
</head>
14
+
<body class="flex items-center justify-center min-h-screen">
15
+
<main class="max-w-md px-6 -mt-4">
16
+
<h1 class="text-center text-2xl font-semibold italic dark:text-white" >tangled</h1>
17
+
<h2 class="text-center text-xl italic dark:text-white">tightly-knit social coding.</h2>
18
+
<form
19
+
class="mt-4 max-w-sm mx-auto"
20
+
hx-post="/signup"
21
+
hx-swap="none"
22
+
hx-disabled-elt="#signup-button"
23
+
>
24
+
<div class="flex flex-col mt-2">
25
+
<label for="email">email</label>
26
+
<input
27
+
type="email"
28
+
id="email"
29
+
name="email"
30
+
tabindex="4"
31
+
required
32
+
placeholder="jason@bourne.co"
33
+
/>
34
+
</div>
35
+
<span class="text-sm text-gray-500 mt-1">
36
+
You will receive an email with an invite code. Enter your
37
+
invite code, desired username, and password in the next
38
+
page to complete your registration.
39
+
</span>
40
+
<button class="btn text-base w-full my-2 mt-6" type="submit" id="signup-button" tabindex="7" >
41
+
<span>join now</span>
42
+
</button>
43
+
</form>
44
+
<p class="text-sm text-gray-500">
45
+
Already have an ATProto account? <a href="/login" class="underline">Login to Tangled</a>.
46
+
</p>
58
47
59
-
<p id="signup-msg" class="error w-full"></p>
60
-
</main>
61
-
</body>
62
-
</html>
48
+
<p id="signup-msg" class="error w-full"></p>
49
+
</main>
50
+
</body>
51
+
</html>
63
52
{{ end }}
53
+