forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

Revert "*.html: format with prettier"

This reverts commits 1931b62baa4452616203ccbb356da72688bc4587 and 86d0b4060de074759eff40666b90be86c244ab23.

Signed-off-by: Winter <winter@winter.cafe>

Changed files
+3945 -5198
appview
pages
templates
errors
knots
layouts
legal
repo
spindles
strings
user
+4 -2
appview/pages/templates/errors/404.html
···
{{ define "title" }}404 &middot; tangled{{ end }}
{{ define "content" }}
-
<h1>404 &mdash; nothing like that here!</h1>
-
<p>It seems we couldn't find what you were looking for. Sorry about that!</p>
+
<h1>404 &mdash; nothing like that here!</h1>
+
<p>
+
It seems we couldn't find what you were looking for. Sorry about that!
+
</p>
{{ end }}
+2 -2
appview/pages/templates/errors/500.html
···
{{ define "title" }}500 &middot; tangled{{ end }}
{{ define "content" }}
-
<h1>500 &mdash; something broke!</h1>
-
<p>We're working on getting service back up. Hang tight!</p>
+
<h1>500 &mdash; something broke!</h1>
+
<p>We're working on getting service back up. Hang tight!</p>
{{ end }}
+5 -4
appview/pages/templates/errors/503.html
···
{{ define "title" }}503 &middot; tangled{{ end }}
{{ define "content" }}
-
<h1>503 &mdash; unable to reach knot</h1>
-
<p>
-
We were unable to reach the knot hosting this repository. Try again later.
-
</p>
+
<h1>503 &mdash; unable to reach knot</h1>
+
<p>
+
We were unable to reach the knot hosting this repository. Try again
+
later.
+
</p>
{{ end }}
+20 -24
appview/pages/templates/favicon.html
···
{{ define "favicon" }}
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
-
<style>
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
+
<style>
+
.favicon-text {
+
fill: #000000;
+
stroke: none;
+
}
+
+
@media (prefers-color-scheme: dark) {
.favicon-text {
-
fill: #000000;
+
fill: #ffffff;
stroke: none;
}
-
-
@media (prefers-color-scheme: dark) {
-
.favicon-text {
-
fill: #ffffff;
-
stroke: none;
-
}
-
}
-
</style>
+
}
+
</style>
-
<g style="display:inline">
-
<path
-
d="M0-2.117h62.177v25.135H0z"
-
style="display:inline;fill:none;fill-opacity:1;stroke-width:.396875"
-
transform="translate(11.01 6.9)" />
-
<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"
-
aria-label="tangled.sh"
-
class="favicon-text"
-
style="font-size:16.2278px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono, Normal';display:inline;fill-opacity:1"
-
transform="translate(11.01 6.9)" />
-
</g>
-
</svg>
+
<g style="display:inline">
+
<path d="M0-2.117h62.177v25.135H0z" style="display:inline;fill:none;fill-opacity:1;stroke-width:.396875" transform="translate(11.01 6.9)"/>
+
<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"
+
aria-label="tangled.sh"
+
class="favicon-text"
+
style="font-size:16.2278px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono, Normal';display:inline;fill-opacity:1"
+
transform="translate(11.01 6.9)"/>
+
</g>
+
</svg>
{{ end }}
+5 -12
appview/pages/templates/knots/dashboard.html
···
<div id="right-side" class="flex gap-2">
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }}
{{ if .Registration.Registered }}
-
<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>
+
<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>
{{ template "knots/fragments/addMemberModal" .Registration }}
{{ else }}
-
<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>
+
<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>
{{ end }}
</div>
</div>
···
</div>
{{ if .Members }}
-
<section
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
<div class="flex flex-col gap-2">
-
{{ block "knotMember" . }}{{ end }}
+
{{ block "knotMember" . }} {{ end }}
</div>
</section>
{{ end }}
···
<div class="flex justify-between items-center">
<div class="flex items-center gap-2">
{{ template "user/fragments/picHandleLink" . }}
-
<span class="ml-2 font-mono text-gray-500">{{ . }}</span>
+
<span class="ml-2 font-mono text-gray-500">{{.}}</span>
</div>
</div>
<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
···
class="btn gap-2 group"
title="Add member to this spindle"
popovertarget="add-member-{{ .Id }}"
-
popovertargetaction="toggle">
+
popovertargetaction="toggle"
+
>
{{ i "user-plus" "w-5 h-5" }}
-
<span class="hidden md:inline">add member</span>
+
<span class="hidden md:inline">add member</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
···
id="add-member-{{ .Id }}"
popover
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">
-
{{ block "addKnotMemberPopover" . }}{{ end }}
+
{{ block "addKnotMemberPopover" . }} {{ end }}
</div>
{{ end }}
{{ define "addKnotMemberPopover" }}
-
<form
-
hx-put="/knots/{{ .Domain }}/member"
-
hx-indicator="#spinner"
-
hx-swap="none"
-
class="flex flex-col gap-2">
-
<label for="member-did-{{ .Id }}" class="uppercase p-0">ADD MEMBER</label>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
-
Members can create repositories on this knot.
-
</p>
-
<input
-
type="text"
-
id="member-did-{{ .Id }}"
-
name="subject"
-
required
-
placeholder="@foo.bsky.social" />
-
<div class="flex gap-2 pt-2">
-
<button
-
type="button"
-
popovertarget="add-member-{{ .Id }}"
-
popovertargetaction="hide"
-
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">
-
{{ i "x" "size-4" }} cancel
-
</button>
-
<button type="submit" class="btn w-1/2 flex items-center">
-
<span class="inline-flex gap-2 items-center">
-
{{ i "user-plus" "size-4" }} add
-
</span>
-
<span id="spinner" class="group">
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</div>
-
<div
-
id="add-member-error-{{ .Id }}"
-
class="text-red-500 dark:text-red-400"></div>
-
</form>
+
<form
+
hx-put="/knots/{{ .Domain }}/member"
+
hx-indicator="#spinner"
+
hx-swap="none"
+
class="flex flex-col gap-2"
+
>
+
<label for="member-did-{{ .Id }}" class="uppercase p-0">
+
ADD MEMBER
+
</label>
+
<p class="text-sm text-gray-500 dark:text-gray-400">Members can create repositories on this knot.</p>
+
<input
+
type="text"
+
id="member-did-{{ .Id }}"
+
name="subject"
+
required
+
placeholder="@foo.bsky.social"
+
/>
+
<div class="flex gap-2 pt-2">
+
<button
+
type="button"
+
popovertarget="add-member-{{ .Id }}"
+
popovertargetaction="hide"
+
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"
+
>
+
{{ i "x" "size-4" }} cancel
+
</button>
+
<button type="submit" class="btn w-1/2 flex items-center">
+
<span class="inline-flex gap-2 items-center">{{ i "user-plus" "size-4" }} add</span>
+
<span id="spinner" class="group">
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</div>
+
<div id="add-member-error-{{ .Id }}" class="text-red-500 dark:text-red-400"></div>
+
</form>
{{ end }}
+
+10 -14
appview/pages/templates/knots/fragments/knotListing.html
···
{{ define "knots/fragments/knotListing" }}
-
<div
-
id="knot-{{ .Id }}"
+
<div
+
id="knot-{{.Id}}"
hx-swap-oob="true"
class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
-
{{ block "listLeftSide" . }}{{ end }}
-
{{ block "listRightSide" . }}{{ end }}
+
{{ block "listLeftSide" . }} {{ end }}
+
{{ block "listRightSide" . }} {{ end }}
</div>
{{ end }}
···
<div id="right-side" class="flex gap-2">
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2 text-sm" }}
{{ if .Registered }}
-
<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>
+
<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>
{{ template "knots/fragments/addMemberModal" . }}
{{ else }}
-
<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>
-
{{ block "initializeButton" . }}{{ end }}
+
<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>
+
{{ block "initializeButton" . }} {{ end }}
{{ end }}
</div>
{{ end }}
···
<button
class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center group"
hx-post="/knots/{{ .Domain }}/init"
-
hx-swap="none">
+
hx-swap="none"
+
>
{{ i "square-play" "w-5 h-5" }}
<span class="hidden md:inline">initialize</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
{{ end }}
+
+16 -20
appview/pages/templates/knots/fragments/knotListingFull.html
···
{{ define "knots/fragments/knotListingFull" }}
-
<section
-
id="knot-listing-full"
-
hx-swap-oob="true"
-
class="rounded w-full flex flex-col gap-2">
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
-
your knots
-
</h2>
-
<div
-
class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
-
{{ range $knot := .Registrations }}
-
{{ template "knots/fragments/knotListing" . }}
-
{{ else }}
-
<div
-
class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
-
no knots registered yet
-
</div>
-
{{ end }}
-
</div>
-
<div id="operation-error" class="text-red-500 dark:text-red-400"></div>
-
</section>
+
<section
+
id="knot-listing-full"
+
hx-swap-oob="true"
+
class="rounded w-full flex flex-col gap-2">
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">your knots</h2>
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
+
{{ range $knot := .Registrations }}
+
{{ template "knots/fragments/knotListing" . }}
+
{{ else }}
+
<div class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
+
no knots registered yet
+
</div>
+
{{ end }}
+
</div>
+
<div id="operation-error" class="text-red-500 dark:text-red-400"></div>
+
</section>
{{ end }}
+2 -6
appview/pages/templates/knots/fragments/secret.html
···
id="secret"
hx-swap-oob="true"
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">
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
-
generated secret
-
</h2>
-
<p class="pb-2">
-
Configure your knot to use this secret, and then hit initialize.
-
</p>
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">generated secret</h2>
+
<p class="pb-2">Configure your knot to use this secret, and then hit initialize.</p>
<span class="font-mono overflow-x">{{ .Secret }}</span>
</div>
{{ end }}
+22 -27
appview/pages/templates/knots/index.html
···
{{ define "title" }}knots{{ end }}
{{ define "content" }}
-
<div class="px-6 py-4">
-
<h1 class="text-xl font-bold dark:text-white">Knots</h1>
+
<div class="px-6 py-4">
+
<h1 class="text-xl font-bold dark:text-white">Knots</h1>
+
</div>
+
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
+
<div class="flex flex-col gap-6">
+
{{ block "about" . }} {{ end }}
+
{{ template "knots/fragments/knotListingFull" . }}
+
{{ block "register" . }} {{ end }}
</div>
-
-
<section
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
-
<div class="flex flex-col gap-6">
-
{{ block "about" . }}{{ end }}
-
{{ template "knots/fragments/knotListingFull" . }}
-
{{ block "register" . }}{{ end }}
-
</div>
-
</section>
+
</section>
{{ end }}
{{ define "about" }}
<section class="rounded flex flex-col gap-2">
<p class="dark:text-gray-300">
-
Knots are lightweight headless servers that enable users to host Git
-
repositories with ease. 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. When creating a repository, you can
-
choose a knot to store it on.
-
<a
-
href="https://tangled.sh/@tangled.sh/core/blob/master/docs/knot-hosting.md">
+
Knots are lightweight headless servers that enable users to host Git repositories with ease.
+
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.
+
When creating a repository, you can choose a knot to store it on.
+
<a href="https://tangled.sh/@tangled.sh/core/blob/master/docs/knot-hosting.md">
Checkout the documentation if you're interested in self-hosting.
</a>
</p>
···
{{ define "register" }}
<section class="rounded max-w-2xl flex flex-col gap-2">
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
-
register a knot
-
</h2>
-
<p class="mb-2 dark:text-gray-300">
-
Enter the hostname of your knot to generate a key.
-
</p>
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a knot</h2>
+
<p class="mb-2 dark:text-gray-300">Enter the hostname of your knot to generate a key.</p>
<form
hx-post="/knots/key"
class="space-y-4"
hx-indicator="#register-button"
-
hx-swap="none">
+
hx-swap="none"
+
>
<div class="flex gap-2">
<input
type="text"
···
name="domain"
placeholder="knot.example.com"
required
-
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" />
+
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"
+
>
<button
type="submit"
id="register-button"
-
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group">
+
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group"
+
>
<span class="inline-flex items-center gap-2">
{{ i "plus" "w-4 h-4" }}
generate
+52 -56
appview/pages/templates/layouts/base.html
···
{{ define "layouts/base" }}
-
<!doctype html>
-
<html lang="en" class="dark:bg-gray-900">
-
<head>
-
<meta charset="UTF-8" />
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-
<meta name="htmx-config" content='{"includeIndicatorStyles": false}' />
-
<script src="/static/htmx.min.js"></script>
-
<script src="/static/htmx-ext-ws.min.js"></script>
-
<link
-
rel="stylesheet"
-
href="/static/tw.css?{{ cssContentHash }}"
-
type="text/css" />
-
<title>{{ block "title" . }}{{ end }} · tangled</title>
-
{{ block "extrameta" . }}{{ end }}
-
</head>
-
<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">
-
{{ block "topbarLayout" . }}
-
<header
-
class="px-1 col-span-1 md:col-start-3 md:col-span-8"
-
style="z-index: 20;">
-
{{ template "layouts/topbar" . }}
-
</header>
-
{{ end }}
-
-
{{ block "mainLayout" . }}
-
<div
-
class="px-1 col-span-1 md:col-start-3 md:col-span-8 flex flex-col gap-4">
-
{{ block "contentLayout" . }}
-
<div class="col-span-1 md:col-span-2">
-
{{ block "contentLeft" . }}{{ end }}
-
</div>
-
<main class="col-span-1 md:col-span-8">
-
{{ block "content" . }}{{ end }}
-
</main>
-
<div class="col-span-1 md:col-span-2">
-
{{ block "contentRight" . }}{{ end }}
-
</div>
+
<!doctype html>
+
<html lang="en" class="dark:bg-gray-900">
+
<head>
+
<meta charset="UTF-8" />
+
<meta
+
name="viewport"
+
content="width=device-width, initial-scale=1.0"
+
/>
+
<meta name="htmx-config" content='{"includeIndicatorStyles": false}'>
+
<script src="/static/htmx.min.js"></script>
+
<script src="/static/htmx-ext-ws.min.js"></script>
+
<link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" />
+
<title>{{ block "title" . }}{{ end }} · tangled</title>
+
{{ block "extrameta" . }}{{ end }}
+
</head>
+
<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">
+
{{ block "topbarLayout" . }}
+
<header class="px-1 col-span-1 md:col-start-3 md:col-span-8" style="z-index: 20;">
+
{{ template "layouts/topbar" . }}
+
</header>
{{ end }}
-
{{ block "contentAfterLayout" . }}
-
<div class="col-span-1 md:col-span-2">
-
{{ block "contentAfterLeft" . }}{{ end }}
-
</div>
-
<main class="col-span-1 md:col-span-8">
-
{{ block "contentAfter" . }}{{ end }}
-
</main>
-
<div class="col-span-1 md:col-span-2">
-
{{ block "contentAfterRight" . }}{{ end }}
+
{{ block "mainLayout" . }}
+
<div class="px-1 col-span-1 md:col-start-3 md:col-span-8 flex flex-col gap-4">
+
{{ block "contentLayout" . }}
+
<div class="col-span-1 md:col-span-2">
+
{{ block "contentLeft" . }} {{ end }}
+
</div>
+
<main class="col-span-1 md:col-span-8">
+
{{ block "content" . }}{{ end }}
+
</main>
+
<div class="col-span-1 md:col-span-2">
+
{{ block "contentRight" . }} {{ end }}
+
</div>
+
{{ end }}
+
+
{{ block "contentAfterLayout" . }}
+
<div class="col-span-1 md:col-span-2">
+
{{ block "contentAfterLeft" . }} {{ end }}
+
</div>
+
<main class="col-span-1 md:col-span-8">
+
{{ block "contentAfter" . }}{{ end }}
+
</main>
+
<div class="col-span-1 md:col-span-2">
+
{{ block "contentAfterRight" . }} {{ end }}
+
</div>
+
{{ end }}
</div>
{{ end }}
-
</div>
-
{{ end }}
-
{{ block "footerLayout" . }}
-
<footer class="px-1 col-span-1 md:col-start-3 md:col-span-8 mt-12">
-
{{ template "layouts/footer" . }}
-
</footer>
-
{{ end }}
-
</body>
-
</html>
+
{{ block "footerLayout" . }}
+
<footer class="px-1 col-span-1 md:col-start-3 md:col-span-8 mt-12">
+
{{ template "layouts/footer" . }}
+
</footer>
+
{{ end }}
+
</body>
+
</html>
{{ end }}
+37 -83
appview/pages/templates/layouts/footer.html
···
{{ define "layouts/footer" }}
-
<div
-
class="w-full p-4 md:p-8 bg-white dark:bg-gray-800 rounded-t drop-shadow-sm">
-
<div class="container mx-auto max-w-7xl px-4">
-
<div
-
class="flex flex-col lg:flex-row justify-between items-start text-gray-600 dark:text-gray-400 text-sm gap-8">
-
<div class="mb-4 md:mb-0">
-
<a href="/" hx-boost="true" class="flex gap-2 font-semibold italic">
-
tangled
-
<sub>alpha</sub>
-
</a>
-
</div>
-
-
{{ $headerStyle := "text-gray-900 dark:text-gray-200 font-bold text-xs uppercase tracking-wide mb-1" }}
-
{{ $linkStyle := "text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:underline inline-flex gap-1 items-center" }}
-
{{ $iconStyle := "w-4 h-4 flex-shrink-0" }}
-
<div
-
class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-4 sm:gap-6 md:gap-2 gap-6 flex-1">
-
<div class="flex flex-col gap-1">
-
<div class="{{ $headerStyle }}">legal</div>
-
<a href="/terms" class="{{ $linkStyle }}">
-
{{ i "file-text" $iconStyle }} terms of service
-
</a>
-
<a href="/privacy" class="{{ $linkStyle }}">
-
{{ i "shield" $iconStyle }} privacy policy
-
</a>
-
</div>
+
<div class="w-full p-4 md:p-8 bg-white dark:bg-gray-800 rounded-t drop-shadow-sm">
+
<div class="container mx-auto max-w-7xl px-4">
+
<div class="flex flex-col lg:flex-row justify-between items-start text-gray-600 dark:text-gray-400 text-sm gap-8">
+
<div class="mb-4 md:mb-0">
+
<a href="/" hx-boost="true" class="flex gap-2 font-semibold italic">
+
tangled<sub>alpha</sub>
+
</a>
+
</div>
-
<div class="flex flex-col gap-1">
-
<div class="{{ $headerStyle }}">resources</div>
-
<a
-
href="https://blog.tangled.sh"
-
class="{{ $linkStyle }}"
-
target="_blank"
-
rel="noopener noreferrer">
-
{{ i "book-open" $iconStyle }} blog
-
</a>
-
<a
-
href="https://tangled.sh/@tangled.sh/core/tree/master/docs"
-
class="{{ $linkStyle }}">
-
{{ i "book" $iconStyle }} docs
-
</a>
-
<a
-
href="https://tangled.sh/@tangled.sh/core"
-
class="{{ $linkStyle }}">
-
{{ i "code" $iconStyle }} source
-
</a>
-
</div>
+
{{ $headerStyle := "text-gray-900 dark:text-gray-200 font-bold text-xs uppercase tracking-wide mb-1" }}
+
{{ $linkStyle := "text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:underline inline-flex gap-1 items-center" }}
+
{{ $iconStyle := "w-4 h-4 flex-shrink-0" }}
+
<div class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-4 sm:gap-6 md:gap-2 gap-6 flex-1">
+
<div class="flex flex-col gap-1">
+
<div class="{{ $headerStyle }}">legal</div>
+
<a href="/terms" class="{{ $linkStyle }}">{{ i "file-text" $iconStyle }} terms of service</a>
+
<a href="/privacy" class="{{ $linkStyle }}">{{ i "shield" $iconStyle }} privacy policy</a>
+
</div>
-
<div class="flex flex-col gap-1">
-
<div class="{{ $headerStyle }}">social</div>
-
<a
-
href="https://chat.tangled.sh"
-
class="{{ $linkStyle }}"
-
target="_blank"
-
rel="noopener noreferrer">
-
{{ i "message-circle" $iconStyle }} discord
-
</a>
-
<a
-
href="https://web.libera.chat/#tangled"
-
class="{{ $linkStyle }}"
-
target="_blank"
-
rel="noopener noreferrer">
-
{{ i "hash" $iconStyle }} irc
-
</a>
-
<a
-
href="https://bsky.app/profile/tangled.sh"
-
class="{{ $linkStyle }}"
-
target="_blank"
-
rel="noopener noreferrer">
-
{{ template "user/fragments/bluesky" $iconStyle }} bluesky
-
</a>
-
</div>
+
<div class="flex flex-col gap-1">
+
<div class="{{ $headerStyle }}">resources</div>
+
<a href="https://blog.tangled.sh" class="{{ $linkStyle }}" target="_blank" rel="noopener noreferrer">{{ i "book-open" $iconStyle }} blog</a>
+
<a href="https://tangled.sh/@tangled.sh/core/tree/master/docs" class="{{ $linkStyle }}">{{ i "book" $iconStyle }} docs</a>
+
<a href="https://tangled.sh/@tangled.sh/core" class="{{ $linkStyle }}">{{ i "code" $iconStyle }} source</a>
+
</div>
-
<div class="flex flex-col gap-1">
-
<div class="{{ $headerStyle }}">contact</div>
-
<a href="mailto:team@tangled.sh" class="{{ $linkStyle }}">
-
{{ i "mail" "w-4 h-4 flex-shrink-0" }} team@tangled.sh
-
</a>
-
<a href="mailto:security@tangled.sh" class="{{ $linkStyle }}">
-
{{ i "shield-check" "w-4 h-4 flex-shrink-0" }} security@tangled.sh
-
</a>
-
</div>
+
<div class="flex flex-col gap-1">
+
<div class="{{ $headerStyle }}">social</div>
+
<a href="https://chat.tangled.sh" class="{{ $linkStyle }}" target="_blank" rel="noopener noreferrer">{{ i "message-circle" $iconStyle }} discord</a>
+
<a href="https://web.libera.chat/#tangled" class="{{ $linkStyle }}" target="_blank" rel="noopener noreferrer">{{ i "hash" $iconStyle }} irc</a>
+
<a href="https://bsky.app/profile/tangled.sh" class="{{ $linkStyle }}" target="_blank" rel="noopener noreferrer">{{ template "user/fragments/bluesky" $iconStyle }} bluesky</a>
</div>
-
<div class="text-center lg:text-right flex-shrink-0">
-
<div class="text-xs">
-
&copy; 2025 Tangled Labs Oy. All rights reserved.
-
</div>
+
<div class="flex flex-col gap-1">
+
<div class="{{ $headerStyle }}">contact</div>
+
<a href="mailto:team@tangled.sh" class="{{ $linkStyle }}">{{ i "mail" "w-4 h-4 flex-shrink-0" }} team@tangled.sh</a>
+
<a href="mailto:security@tangled.sh" class="{{ $linkStyle }}">{{ i "shield-check" "w-4 h-4 flex-shrink-0" }} security@tangled.sh</a>
</div>
</div>
+
+
<div class="text-center lg:text-right flex-shrink-0">
+
<div class="text-xs">&copy; 2025 Tangled Labs Oy. All rights reserved.</div>
+
</div>
</div>
</div>
+
</div>
{{ end }}
+61 -66
appview/pages/templates/layouts/topbar.html
···
{{ define "layouts/topbar" }}
-
<nav
-
class="space-x-4 px-6 py-2 rounded bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm">
-
<div class="flex justify-between p-0 items-center">
-
<div id="left-items">
-
<a href="/" hx-boost="true" class="flex gap-2 font-bold italic">
-
tangled
-
<sub>alpha</sub>
-
</a>
-
</div>
+
<nav class="space-x-4 px-6 py-2 rounded bg-white dark:bg-gray-800 dark:text-white drop-shadow-sm">
+
<div class="flex justify-between p-0 items-center">
+
<div id="left-items">
+
<a href="/" hx-boost="true" class="flex gap-2 font-bold italic">
+
tangled<sub>alpha</sub>
+
</a>
+
</div>
-
<div id="right-items" class="flex items-center gap-2">
-
{{ with .LoggedInUser }}
-
{{ block "newButton" . }}{{ end }}
-
{{ block "dropDown" . }}{{ end }}
-
{{ else }}
-
<a href="/login">login</a>
-
<span class="text-gray-500 dark:text-gray-400">or</span>
-
<a
-
href="/signup"
-
class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
-
join now
-
{{ i "arrow-right" "size-4" }}
-
</a>
-
{{ end }}
-
</div>
-
</div>
-
</nav>
+
<div id="right-items" class="flex items-center gap-2">
+
{{ with .LoggedInUser }}
+
{{ block "newButton" . }} {{ end }}
+
{{ block "dropDown" . }} {{ end }}
+
{{ else }}
+
<a href="/login">login</a>
+
<span class="text-gray-500 dark:text-gray-400">or</span>
+
<a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
+
join now {{ i "arrow-right" "size-4" }}
+
</a>
+
{{ end }}
+
</div>
+
</div>
+
</nav>
{{ end }}
{{ define "newButton" }}
-
<details class="relative inline-block text-left nav-dropdown">
-
<summary
-
class="btn-create py-0 cursor-pointer list-none flex items-center gap-2">
+
<details class="relative inline-block text-left nav-dropdown">
+
<summary class="btn-create py-0 cursor-pointer list-none flex items-center gap-2">
{{ i "plus" "w-4 h-4" }} new
</summary>
-
<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">
-
<a href="/repo/new" class="flex items-center gap-2">
-
{{ i "book-plus" "w-4 h-4" }}
-
new repository
-
</a>
-
<a href="/strings/new" class="flex items-center gap-2">
-
{{ i "line-squiggle" "w-4 h-4" }}
-
new string
-
</a>
+
<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">
+
<a href="/repo/new" class="flex items-center gap-2">
+
{{ i "book-plus" "w-4 h-4" }}
+
new repository
+
</a>
+
<a href="/strings/new" class="flex items-center gap-2">
+
{{ i "line-squiggle" "w-4 h-4" }}
+
new string
+
</a>
</div>
-
</details>
+
</details>
{{ end }}
{{ define "dropDown" }}
-
<details class="relative inline-block text-left nav-dropdown">
-
<summary class="cursor-pointer list-none flex items-center">
-
{{ $user := didOrHandle .Did .Handle }}
-
{{ template "user/fragments/picHandle" $user }}
+
<details class="relative inline-block text-left nav-dropdown">
+
<summary
+
class="cursor-pointer list-none flex items-center"
+
>
+
{{ $user := didOrHandle .Did .Handle }}
+
{{ template "user/fragments/picHandle" $user }}
</summary>
<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">
-
<a href="/{{ $user }}">profile</a>
-
<a href="/{{ $user }}?tab=repos">repositories</a>
-
<a href="/strings/{{ $user }}">strings</a>
-
<a href="/knots">knots</a>
-
<a href="/spindles">spindles</a>
-
<a href="/settings">settings</a>
-
<a
-
href="#"
-
hx-post="/logout"
-
hx-swap="none"
-
class="text-red-400 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
-
logout
-
</a>
+
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"
+
>
+
<a href="/{{ $user }}">profile</a>
+
<a href="/{{ $user }}?tab=repos">repositories</a>
+
<a href="/strings/{{ $user }}">strings</a>
+
<a href="/knots">knots</a>
+
<a href="/spindles">spindles</a>
+
<a href="/settings">settings</a>
+
<a href="#"
+
hx-post="/logout"
+
hx-swap="none"
+
class="text-red-400 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300">
+
logout
+
</a>
</div>
-
</details>
+
</details>
-
<script>
-
document.addEventListener("click", function (event) {
-
const dropdowns = document.querySelectorAll(".nav-dropdown");
-
dropdowns.forEach(function (dropdown) {
+
<script>
+
document.addEventListener('click', function(event) {
+
const dropdowns = document.querySelectorAll('.nav-dropdown');
+
dropdowns.forEach(function(dropdown) {
if (!dropdown.contains(event.target)) {
-
dropdown.removeAttribute("open");
+
dropdown.removeAttribute('open');
}
-
});
});
-
</script>
+
});
+
</script>
{{ end }}
+65 -155
appview/pages/templates/legal/privacy.html
···
-
{{ define "title" }}privacy policy{{ end }}
+
{{ define "title" }} privacy policy {{ end }}
{{ define "content" }}
-
<div class="max-w-4xl mx-auto px-4 py-8">
+
<div class="max-w-4xl mx-auto px-4 py-8">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-8">
-
<div class="prose prose-gray dark:prose-invert max-w-none">
+
<div class="prose prose-gray dark:prose-invert max-w-none">
<h1>Privacy Policy</h1>
-
<p>
-
<strong>Last updated:</strong>
-
{{ now.Format "January 2, 2006" }}
-
</p>
+
<p><strong>Last updated:</strong> {{ now.Format "January 2, 2006" }}</p>
-
<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>
+
<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>
<h2>1. Information We Collect</h2>
<h3>Account Information</h3>
<p>When you create an account, we collect:</p>
<ul>
-
<li>Your chosen username</li>
-
<li>Email address</li>
-
<li>Profile information you choose to provide</li>
-
<li>Authentication data</li>
+
<li>Your chosen username</li>
+
<li>Email address</li>
+
<li>Profile information you choose to provide</li>
+
<li>Authentication data</li>
</ul>
<h3>Content and Activity</h3>
<p>We store:</p>
<ul>
-
<li>Code repositories and associated metadata</li>
-
<li>Issues, pull requests, and comments</li>
-
<li>Activity logs and usage patterns</li>
-
<li>Public keys for authentication</li>
+
<li>Code repositories and associated metadata</li>
+
<li>Issues, pull requests, and comments</li>
+
<li>Activity logs and usage patterns</li>
+
<li>Public keys for authentication</li>
</ul>
<h2>2. Data Location and Hosting</h2>
-
<div
-
class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 my-6">
-
<h3 class="text-blue-800 dark:text-blue-200 font-semibold mb-2">
-
EU Data Hosting
-
</h3>
-
<p class="text-blue-700 dark:text-blue-300">
-
<strong>
-
All Tangled service data is hosted within the European Union.
-
</strong>
-
Specifically:
-
</p>
-
<ul class="text-blue-700 dark:text-blue-300 mt-2">
-
<li>
-
<strong>Personal Data Servers (PDS):</strong>
-
Accounts hosted on Tangled PDS (*.tngl.sh) are located in Finland
-
</li>
-
<li>
-
<strong>Application Data:</strong>
-
All other service data is stored on EU-based servers
-
</li>
-
<li>
-
<strong>Data Processing:</strong>
-
All data processing occurs within EU jurisdiction
-
</li>
-
</ul>
+
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4 my-6">
+
<h3 class="text-blue-800 dark:text-blue-200 font-semibold mb-2">EU Data Hosting</h3>
+
<p class="text-blue-700 dark:text-blue-300">
+
<strong>All Tangled service data is hosted within the European Union.</strong> Specifically:
+
</p>
+
<ul class="text-blue-700 dark:text-blue-300 mt-2">
+
<li><strong>Personal Data Servers (PDS):</strong> Accounts hosted on Tangled PDS (*.tngl.sh) are located in Finland</li>
+
<li><strong>Application Data:</strong> All other service data is stored on EU-based servers</li>
+
<li><strong>Data Processing:</strong> All data processing occurs within EU jurisdiction</li>
+
</ul>
</div>
-
<div
-
class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4 my-6">
-
<h3 class="text-yellow-800 dark:text-yellow-200 font-semibold mb-2">
-
External PDS Notice
-
</h3>
-
<p class="text-yellow-700 dark:text-yellow-300">
-
<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.
-
</p>
+
<div class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4 my-6">
+
<h3 class="text-yellow-800 dark:text-yellow-200 font-semibold mb-2">External PDS Notice</h3>
+
<p class="text-yellow-700 dark:text-yellow-300">
+
<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.
+
</p>
</div>
<h2>3. Third-Party Data Processors</h2>
-
<p>
-
We only share your data with the following third-party processors:
-
</p>
+
<p>We only share your data with the following third-party processors:</p>
<h3>Resend (Email Services)</h3>
<ul>
-
<li>
-
<strong>Purpose:</strong>
-
Sending transactional emails (account verification, notifications)
-
</li>
-
<li>
-
<strong>Data Shared:</strong>
-
Email address and necessary message content
-
</li>
-
<li>
-
<strong>Location:</strong>
-
EU-compliant email delivery service
-
</li>
+
<li><strong>Purpose:</strong> Sending transactional emails (account verification, notifications)</li>
+
<li><strong>Data Shared:</strong> Email address and necessary message content</li>
+
<li><strong>Location:</strong> EU-compliant email delivery service</li>
</ul>
<h3>Cloudflare (Image Caching)</h3>
<ul>
-
<li>
-
<strong>Purpose:</strong>
-
Caching and optimizing image delivery
-
</li>
-
<li>
-
<strong>Data Shared:</strong>
-
Public images and associated metadata for caching purposes
-
</li>
-
<li>
-
<strong>Location:</strong>
-
Global CDN with EU data protection compliance
-
</li>
+
<li><strong>Purpose:</strong> Caching and optimizing image delivery</li>
+
<li><strong>Data Shared:</strong> Public images and associated metadata for caching purposes</li>
+
<li><strong>Location:</strong> Global CDN with EU data protection compliance</li>
</ul>
<h2>4. How We Use Your Information</h2>
<p>We use your information to:</p>
<ul>
-
<li>Provide and maintain the Service</li>
-
<li>Process your transactions and requests</li>
-
<li>Send you technical notices and support messages</li>
-
<li>Improve and develop new features</li>
-
<li>Ensure security and prevent fraud</li>
-
<li>Comply with legal obligations</li>
+
<li>Provide and maintain the Service</li>
+
<li>Process your transactions and requests</li>
+
<li>Send you technical notices and support messages</li>
+
<li>Improve and develop new features</li>
+
<li>Ensure security and prevent fraud</li>
+
<li>Comply with legal obligations</li>
</ul>
<h2>5. Data Sharing and Disclosure</h2>
-
<p>
-
We do not sell, trade, or rent your personal information. We may share
-
your information only in the following circumstances:
-
</p>
+
<p>We do not sell, trade, or rent your personal information. We may share your information only in the following circumstances:</p>
<ul>
-
<li>With the third-party processors listed above</li>
-
<li>When required by law or legal process</li>
-
<li>
-
To protect our rights, property, or safety, or that of our users
-
</li>
-
<li>
-
In connection with a merger, acquisition, or sale of assets (with
-
appropriate protections)
-
</li>
+
<li>With the third-party processors listed above</li>
+
<li>When required by law or legal process</li>
+
<li>To protect our rights, property, or safety, or that of our users</li>
+
<li>In connection with a merger, acquisition, or sale of assets (with appropriate protections)</li>
</ul>
<h2>6. Data Security</h2>
-
<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>
+
<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>
<h2>7. Data Retention</h2>
-
<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>
+
<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>
<h2>8. Your Rights</h2>
<p>Under applicable data protection laws, you have the right to:</p>
<ul>
-
<li>Access your personal information</li>
-
<li>Correct inaccurate information</li>
-
<li>Request deletion of your information</li>
-
<li>Object to processing of your information</li>
-
<li>Data portability</li>
-
<li>Withdraw consent (where applicable)</li>
+
<li>Access your personal information</li>
+
<li>Correct inaccurate information</li>
+
<li>Request deletion of your information</li>
+
<li>Object to processing of your information</li>
+
<li>Data portability</li>
+
<li>Withdraw consent (where applicable)</li>
</ul>
<h2>9. Cookies and Tracking</h2>
<p>We use cookies and similar technologies to:</p>
<ul>
-
<li>Maintain your login session</li>
-
<li>Remember your preferences</li>
-
<li>Analyze usage patterns to improve the Service</li>
+
<li>Maintain your login session</li>
+
<li>Remember your preferences</li>
+
<li>Analyze usage patterns to improve the Service</li>
</ul>
<p>You can control cookie settings through your browser preferences.</p>
<h2>10. Children's Privacy</h2>
-
<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>
+
<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>
<h2>11. International Data Transfers</h2>
-
<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>
+
<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>
<h2>12. Changes to This Privacy Policy</h2>
-
<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>
+
<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>
<h2>13. Contact Information</h2>
-
<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>
+
<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>
-
<div
-
class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
-
<p>
-
This Privacy Policy complies with the EU General Data Protection
-
Regulation (GDPR) and other applicable data protection laws.
-
</p>
+
<div class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
+
<p>This Privacy Policy complies with the EU General Data Protection Regulation (GDPR) and other applicable data protection laws.</p>
+
</div>
</div>
-
</div>
</div>
-
</div>
+
</div>
{{ end }}
+32 -118
appview/pages/templates/legal/terms.html
···
{{ define "title" }}terms of service{{ end }}
{{ define "content" }}
-
<div class="max-w-4xl mx-auto px-4 py-8">
+
<div class="max-w-4xl mx-auto px-4 py-8">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-8">
-
<div class="prose prose-gray dark:prose-invert max-w-none">
+
<div class="prose prose-gray dark:prose-invert max-w-none">
<h1>Terms of Service</h1>
-
<p>
-
<strong>Last updated:</strong>
-
{{ now.Format "January 2, 2006" }}
-
</p>
+
<p><strong>Last updated:</strong> {{ now.Format "January 2, 2006" }}</p>
-
<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>
+
<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>
<h2>1. Acceptance of Terms</h2>
-
<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>
+
<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>
<h2>2. Account Registration</h2>
-
<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>
+
<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>
<h2>3. Account Termination</h2>
-
<div
-
class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 my-6">
-
<h3 class="text-red-800 dark:text-red-200 font-semibold mb-2">
-
Important Notice
-
</h3>
-
<p class="text-red-700 dark:text-red-300">
-
<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.
-
</p>
-
<p class="text-red-700 dark:text-red-300 mt-2">
-
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.
-
</p>
+
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 my-6">
+
<h3 class="text-red-800 dark:text-red-200 font-semibold mb-2">Important Notice</h3>
+
<p class="text-red-700 dark:text-red-300">
+
<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.
+
</p>
+
<p class="text-red-700 dark:text-red-300 mt-2">
+
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.
+
</p>
</div>
<h2>4. Acceptable Use</h2>
<p>You agree not to use the Service to:</p>
<ul>
-
<li>Violate any applicable laws or regulations</li>
-
<li>Infringe upon the rights of others</li>
-
<li>
-
Upload, store, or share content that is illegal, harmful,
-
threatening, abusive, harassing, defamatory, vulgar, obscene, or
-
otherwise objectionable
-
</li>
-
<li>Engage in spam, phishing, or other deceptive practices</li>
-
<li>
-
Attempt to gain unauthorized access to the Service or other users'
-
accounts
-
</li>
-
<li>
-
Interfere with or disrupt the Service or servers connected to the
-
Service
-
</li>
+
<li>Violate any applicable laws or regulations</li>
+
<li>Infringe upon the rights of others</li>
+
<li>Upload, store, or share content that is illegal, harmful, threatening, abusive, harassing, defamatory, vulgar, obscene, or otherwise objectionable</li>
+
<li>Engage in spam, phishing, or other deceptive practices</li>
+
<li>Attempt to gain unauthorized access to the Service or other users' accounts</li>
+
<li>Interfere with or disrupt the Service or servers connected to the Service</li>
</ul>
<h2>5. Content and Intellectual Property</h2>
-
<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>
+
<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>
<h2>6. Privacy</h2>
-
<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>
+
<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>
<h2>7. Disclaimers</h2>
-
<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>
+
<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>
<h2>8. Limitation of Liability</h2>
-
<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>
+
<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>
<h2>9. Indemnification</h2>
-
<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>
+
<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>
<h2>10. Governing Law</h2>
-
<p>
-
These Terms shall be interpreted and governed by the laws of Finland,
-
without regard to its conflict of law provisions.
-
</p>
+
<p>These Terms shall be interpreted and governed by the laws of Finland, without regard to its conflict of law provisions.</p>
<h2>11. Changes to Terms</h2>
-
<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>
+
<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>
<h2>12. Contact Information</h2>
-
<p>
-
If you have any questions about these Terms of Service, please contact
-
us through our platform or via email.
-
</p>
+
<p>If you have any questions about these Terms of Service, please contact us through our platform or via email.</p>
-
<div
-
class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
-
<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>
+
<div class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-600 dark:text-gray-400">
+
<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>
+
</div>
</div>
-
</div>
</div>
-
</div>
+
</div>
{{ end }}
+70 -93
appview/pages/templates/repo/blob.html
···
-
{{ define "title" }}
-
{{ .Path }} at {{ .Ref }} &middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title" }}{{ .Path }} at {{ .Ref }} &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "extrameta" }}
-
{{ template "repo/fragments/meta" . }}
+
{{ template "repo/fragments/meta" . }}
+
+
{{ $title := printf "%s at %s &middot; %s" .Path .Ref .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/blob/%s/%s" .RepoInfo.FullName .Ref .Path }}
-
{{ $title := printf "%s at %s &middot; %s" .Path .Ref .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/blob/%s/%s" .RepoInfo.FullName .Ref .Path }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
{{ $lines := split .Contents }}
-
{{ $tot_lines := len $lines }}
-
{{ $tot_chars := len (printf "%d" $tot_lines) }}
-
{{ $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" }}
-
{{ $linkstyle := "no-underline hover:underline" }}
-
<div
-
class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
-
<div class="flex flex-col md:flex-row md:justify-between gap-2">
-
<div
-
id="breadcrumbs"
-
class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
-
{{ range $idx, $value := .BreadCrumbs }}
-
{{ if ne $idx (sub (len $.BreadCrumbs) 1) }}
-
<a
-
href="{{ index . 1 }}"
-
class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}">
-
{{ pathUnescape (index . 0) }}
-
</a>
-
/
-
{{ else }}
-
<span class="text-bold text-black dark:text-white">
-
{{ pathUnescape (index . 0) }}
-
</span>
-
{{ end }}
-
{{ end }}
-
</div>
-
<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">
-
<span>
-
at
-
<a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a>
-
</span>
-
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<span>{{ .Lines }} lines</span>
-
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<span>{{ byteFmt .SizeHint }}</span>
-
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">
-
view raw
-
</a>
-
{{ if .RenderToggle }}
-
<span
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<a
-
href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}"
-
hx-boost="true">
-
view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}
-
</a>
-
{{ end }}
-
</div>
+
{{ $lines := split .Contents }}
+
{{ $tot_lines := len $lines }}
+
{{ $tot_chars := len (printf "%d" $tot_lines) }}
+
{{ $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" }}
+
{{ $linkstyle := "no-underline hover:underline" }}
+
<div class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
+
<div class="flex flex-col md:flex-row md:justify-between gap-2">
+
<div id="breadcrumbs" class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
+
{{ range $idx, $value := .BreadCrumbs }}
+
{{ if ne $idx (sub (len $.BreadCrumbs) 1) }}
+
<a
+
href="{{ index . 1 }}"
+
class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}"
+
>{{ pathUnescape (index . 0) }}</a
+
>
+
/
+
{{ else }}
+
<span class="text-bold text-black dark:text-white"
+
>{{ pathUnescape (index . 0) }}</span
+
>
+
{{ end }}
+
{{ end }}
+
</div>
+
<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">
+
<span>at <a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a></span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ .Lines }} lines</span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ byteFmt .SizeHint }}</span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">view raw</a>
+
{{ if .RenderToggle }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<a
+
href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}"
+
hx-boost="true"
+
>view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}</a>
+
{{ end }}
+
</div>
+
</div>
</div>
-
</div>
-
{{ if and .IsBinary .Unsupported }}
-
<p class="text-center text-gray-400 dark:text-gray-500">
-
Previews are not supported for this file type.
-
</p>
-
{{ else if .IsBinary }}
-
<div class="text-center">
-
{{ if .IsImage }}
-
<img
-
src="{{ .ContentSrc }}"
-
alt="{{ .Path }}"
-
class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" />
-
{{ else if .IsVideo }}
-
<video
-
controls
-
class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded">
-
<source src="{{ .ContentSrc }}" />
-
Your browser does not support the video tag.
-
</video>
-
{{ end }}
-
</div>
-
{{ else }}
+
{{ if and .IsBinary .Unsupported }}
+
<p class="text-center text-gray-400 dark:text-gray-500">
+
Previews are not supported for this file type.
+
</p>
+
{{ else if .IsBinary }}
+
<div class="text-center">
+
{{ if .IsImage }}
+
<img src="{{ .ContentSrc }}"
+
alt="{{ .Path }}"
+
class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" />
+
{{ else if .IsVideo }}
+
<video controls class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded">
+
<source src="{{ .ContentSrc }}">
+
Your browser does not support the video tag.
+
</video>
+
{{ end }}
+
</div>
+
{{ else }}
<div class="overflow-auto relative">
-
{{ if .ShowRendered }}
-
<div id="blob-contents" class="prose dark:prose-invert">
-
{{ .RenderedContents }}
-
</div>
-
{{ else }}
-
<div
-
id="blob-contents"
-
class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">
-
{{ $.Contents | escapeHtml }}
-
</div>
-
{{ end }}
+
{{ if .ShowRendered }}
+
<div id="blob-contents" class="prose dark:prose-invert">{{ .RenderedContents }}</div>
+
{{ else }}
+
<div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ $.Contents | escapeHtml }}</div>
+
{{ end }}
</div>
-
{{ end }}
+
{{ end }}
{{ end }}
+83 -116
appview/pages/templates/repo/branches.html
···
{{ define "title" }}
-
branches &middot;
-
{{ .RepoInfo.FullName }}
+
branches &middot; {{ .RepoInfo.FullName }}
{{ end }}
{{ define "extrameta" }}
-
{{ $title := printf "branches &middot; %s" .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/branches" .RepoInfo.FullName }}
-
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ $title := printf "branches &middot; %s" .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/branches" .RepoInfo.FullName }}
+
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
<section id="branches-table" class="overflow-x-auto">
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">Branches</h2>
+
<section id="branches-table" class="overflow-x-auto">
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
+
Branches
+
</h2>
-
<!-- desktop view (hidden on small screens) -->
-
<table class="w-full border-collapse hidden md:table">
-
<thead>
-
<tr>
-
<th
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
-
Name
-
</th>
-
<th
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
-
Commit
-
</th>
-
<th
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
-
Message
-
</th>
-
<th
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">
-
Date
-
</th>
-
</tr>
-
</thead>
-
<tbody>
-
{{ range $index, $branch := .Branches }}
-
<tr
-
class="{{ if ne $index (sub (len $.Branches) 1) }}
-
border-b border-gray-200 dark:border-gray-700
-
{{ end }}">
-
<td class="py-3 whitespace-nowrap">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}"
-
class="no-underline hover:underline flex items-center gap-2">
-
<span class="dark:text-white">
-
{{ .Name }}
-
</span>
-
{{ if .IsDefault }}
-
<span
-
class="
+
<!-- desktop view (hidden on small screens) -->
+
<table class="w-full border-collapse hidden md:table">
+
<thead>
+
<tr>
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Name</th>
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Commit</th>
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Message</th>
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Date</th>
+
</tr>
+
</thead>
+
<tbody>
+
{{ range $index, $branch := .Branches }}
+
<tr class="{{ if ne $index (sub (len $.Branches) 1) }}border-b border-gray-200 dark:border-gray-700{{ end }}">
+
<td class="py-3 whitespace-nowrap">
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}" class="no-underline hover:underline flex items-center gap-2">
+
<span class="dark:text-white">
+
{{ .Name }}
+
</span>
+
{{ if .IsDefault }}
+
<span class="
text-sm rounded
bg-gray-100 dark:bg-gray-700 text-black dark:text-white
font-mono
px-2 mx-1/2
inline-flex items-center
">
-
default
-
</span>
-
{{ end }}
-
</a>
-
</td>
-
<td class="py-3 whitespace-nowrap">
-
{{ if .Commit }}
-
<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>
-
{{ end }}
-
</td>
-
<td class="py-3 whitespace-nowrap">
-
{{ if .Commit }}
-
{{ $messageParts := splitN .Commit.Message "\n\n" 2 }}
-
<span class="text-gray-700 dark:text-gray-300">
-
{{ index $messageParts 0 }}
-
</span>
-
{{ end }}
-
</td>
-
<td class="py-3 whitespace-nowrap text-gray-500 dark:text-gray-400">
-
{{ if .Commit }}
-
{{ template "repo/fragments/time" .Commit.Committer.When }}
-
{{ end }}
-
</td>
-
</tr>
-
{{ end }}
-
</tbody>
-
</table>
+
default
+
</span>
+
{{ end }}
+
</a>
+
</td>
+
<td class="py-3 whitespace-nowrap">
+
{{ if .Commit }}
+
<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>
+
{{ end }}
+
</td>
+
<td class="py-3 whitespace-nowrap">
+
{{ if .Commit }}
+
{{ $messageParts := splitN .Commit.Message "\n\n" 2 }}
+
<span class="text-gray-700 dark:text-gray-300">{{ index $messageParts 0 }}</span>
+
{{ end }}
+
</td>
+
<td class="py-3 whitespace-nowrap text-gray-500 dark:text-gray-400">
+
{{ if .Commit }}
+
{{ template "repo/fragments/time" .Commit.Committer.When }}
+
{{ end }}
+
</td>
+
</tr>
+
{{ end }}
+
</tbody>
+
</table>
-
<!-- mobile view (visible only on small screens) -->
-
<div class="md:hidden">
-
{{ range $index, $branch := .Branches }}
-
<div
-
class="relative p-2 {{ if ne $index (sub (len $.Branches) 1) }}
-
border-b border-gray-200 dark:border-gray-700
-
{{ end }}">
-
<div class="flex items-center justify-between">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}"
-
class="no-underline hover:underline flex items-center gap-2">
-
<span class="dark:text-white font-medium">
-
{{ .Name }}
-
</span>
-
{{ if .IsDefault }}
-
<span
-
class="
+
<!-- mobile view (visible only on small screens) -->
+
<div class="md:hidden">
+
{{ range $index, $branch := .Branches }}
+
<div class="relative p-2 {{ if ne $index (sub (len $.Branches) 1) }}border-b border-gray-200 dark:border-gray-700{{ end }}">
+
<div class="flex items-center justify-between">
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Name | urlquery }}" class="no-underline hover:underline flex items-center gap-2">
+
<span class="dark:text-white font-medium">
+
{{ .Name }}
+
</span>
+
{{ if .IsDefault }}
+
<span class="
text-xs rounded
bg-gray-100 dark:bg-gray-700 text-black dark:text-white
font-mono
px-2
inline-flex items-center
">
-
default
-
</span>
-
{{ end }}
-
</a>
-
</div>
+
default
+
</span>
+
{{ end }}
+
</a>
+
</div>
-
{{ if .Commit }}
-
<div
-
class="text-xs text-gray-500 dark:text-gray-400 mt-1 flex items-center">
-
<span class="font-mono">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commits/{{ .Name | urlquery }}"
-
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
-
{{ slice .Commit.Hash.String 0 8 }}
-
</a>
-
</span>
-
<div
-
class="inline-block px-1 select-none after:content-['·']"></div>
-
{{ template "repo/fragments/time" .Commit.Committer.When }}
-
</div>
-
{{ end }}
-
</div>
+
{{ if .Commit }}
+
<div class="text-xs text-gray-500 dark:text-gray-400 mt-1 flex items-center">
+
<span class="font-mono">
+
<a href="/{{ $.RepoInfo.FullName }}/commits/{{ .Name | urlquery }}" class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
+
{{ slice .Commit.Hash.String 0 8 }}
+
</a>
+
</span>
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
+
{{ template "repo/fragments/time" .Commit.Committer.When }}
+
</div>
{{ end }}
</div>
-
</section>
+
{{ end }}
+
</div>
+
</section>
{{ end }}
+59 -92
appview/pages/templates/repo/commit.html
···
-
{{ define "title" }}
-
commit {{ .Diff.Commit.This }} &middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title" }} commit {{ .Diff.Commit.This }} &middot; {{ .RepoInfo.FullName }} {{ end }}
{{ define "extrameta" }}
-
{{ $title := printf "commit %s &middot; %s" .Diff.Commit.This .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/commit/%s" .RepoInfo.FullName .Diff.Commit.This }}
+
{{ $title := printf "commit %s &middot; %s" .Diff.Commit.This .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/commit/%s" .RepoInfo.FullName .Diff.Commit.This }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
+
{{ define "repoContent" }}
-
{{ $repo := .RepoInfo.FullName }}
-
{{ $commit := .Diff.Commit }}
+
{{ $repo := .RepoInfo.FullName }}
+
{{ $commit := .Diff.Commit }}
-
-
<section class="commit dark:text-white">
-
<div id="commit-message">
-
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
-
<div>
-
<p class="pb-2">{{ index $messageParts 0 }}</p>
-
{{ if gt (len $messageParts) 1 }}
-
<p class="mt-1 cursor-text pb-2 text-sm">
-
{{ nl2br (index $messageParts 1) }}
-
</p>
-
{{ end }}
-
</div>
+
<section class="commit dark:text-white">
+
<div id="commit-message">
+
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
+
<div>
+
<p class="pb-2">{{ index $messageParts 0 }}</p>
+
{{ if gt (len $messageParts) 1 }}
+
<p class="mt-1 cursor-text pb-2 text-sm">{{ nl2br (index $messageParts 1) }}</p>
+
{{ end }}
</div>
+
</div>
-
<div class="flex items-center space-x-2">
+
<div class="flex items-center space-x-2">
<p class="text-sm text-gray-500 dark:text-gray-300">
-
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
+
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
-
{{ if $didOrHandle }}
-
<a
-
href="/{{ $didOrHandle }}"
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
-
{{ $didOrHandle }}
-
</a>
-
{{ else }}
-
<a
-
href="mailto:{{ $commit.Author.Email }}"
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
-
{{ $commit.Author.Name }}
-
</a>
-
{{ end }}
-
<span class="px-1 select-none before:content-['\00B7']"></span>
-
{{ template "repo/fragments/time" $commit.Author.When }}
-
<span class="px-1 select-none before:content-['\00B7']"></span>
+
{{ if $didOrHandle }}
+
<a href="/{{ $didOrHandle }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ $didOrHandle }}</a>
+
{{ else }}
+
<a href="mailto:{{ $commit.Author.Email }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ $commit.Author.Name }}</a>
+
{{ end }}
+
<span class="px-1 select-none before:content-['\00B7']"></span>
+
{{ template "repo/fragments/time" $commit.Author.When }}
+
<span class="px-1 select-none before:content-['\00B7']"></span>
</p>
<p class="flex items-center text-sm text-gray-500 dark:text-gray-300">
-
<a
-
href="/{{ $repo }}/commit/{{ $commit.This }}"
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
-
{{ slice $commit.This 0 8 }}
-
</a>
-
{{ if $commit.Parent }}
+
<a href="/{{ $repo }}/commit/{{ $commit.This }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ slice $commit.This 0 8 }}</a>
+
{{ if $commit.Parent }}
{{ i "arrow-left" "w-3 h-3 mx-1" }}
-
<a
-
href="/{{ $repo }}/commit/{{ $commit.Parent }}"
-
class="no-underline hover:underline text-gray-500 dark:text-gray-300">
-
{{ slice $commit.Parent 0 8 }}
-
</a>
-
{{ end }}
+
<a href="/{{ $repo }}/commit/{{ $commit.Parent }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ slice $commit.Parent 0 8 }}</a>
+
{{ end }}
</p>
{{ if .VerifiedCommit.IsVerified $commit.This }}
-
<div class="group relative inline-block text-sm">
-
<div
-
class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 rounded cursor-pointer">
-
<div class="flex items-center gap-2">
-
{{ i "shield-check" "w-4 h-4" }}
-
verified
-
</div>
+
<div class="group relative inline-block text-sm">
+
<div class="bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 rounded cursor-pointer">
+
<div class="flex items-center gap-2">
+
{{ i "shield-check" "w-4 h-4" }}
+
verified
+
</div>
</div>
-
<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">
-
<div class="mb-1">
-
This commit was signed with the committer's
-
<span class="text-green-600 font-semibold">known signature</span>
-
.
-
</div>
-
<div class="flex items-center gap-2 my-2">
-
{{ i "user" "w-4 h-4" }}
-
{{ $committerDidOrHandle := index $.EmailToDidOrHandle $commit.Committer.Email }}
-
<a href="/{{ $committerDidOrHandle }}">
-
{{ template "user/fragments/picHandleLink" $committerDidOrHandle }}
-
</a>
-
</div>
-
<div class="my-1 pt-2 text-xs border-t">
-
<div class="text-gray-600 dark:text-gray-300">
-
SSH Key Fingerprint:
+
<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">
+
<div class="mb-1">This commit was signed with the committer's <span class="text-green-600 font-semibold">known signature</span>.</div>
+
<div class="flex items-center gap-2 my-2">
+
{{ i "user" "w-4 h-4" }}
+
{{ $committerDidOrHandle := index $.EmailToDidOrHandle $commit.Committer.Email }}
+
<a href="/{{ $committerDidOrHandle }}">{{ template "user/fragments/picHandleLink" $committerDidOrHandle }}</a>
</div>
-
<div class="break-all">
-
{{ .VerifiedCommit.Fingerprint $commit.This }}
+
<div class="my-1 pt-2 text-xs border-t">
+
<div class="text-gray-600 dark:text-gray-300">SSH Key Fingerprint:</div>
+
<div class="break-all">{{ .VerifiedCommit.Fingerprint $commit.This }}</div>
</div>
-
</div>
</div>
-
</div>
+
</div>
{{ end }}
-
<div class="text-sm">
{{ if $.Pipeline }}
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $.Pipeline "RepoInfo" $.RepoInfo) }}
{{ end }}
</div>
-
</div>
-
</section>
-
{{ end }}
+
</div>
+
+
</section>
+
{{end}}
{{ define "topbarLayout" }}
<header class="px-1 col-span-full" style="z-index: 20;">
···
{{ end }}
{{ block "contentAfterLayout" . }}
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
-
{{ block "contentAfterLeft" . }}{{ end }}
-
</div>
-
<main class="col-span-1 md:col-span-10">
-
{{ block "contentAfter" . }}{{ end }}
-
</main>
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
+
{{ block "contentAfterLeft" . }} {{ end }}
</div>
+
<main class="col-span-1 md:col-span-10">
+
{{ block "contentAfter" . }}{{ end }}
+
</main>
+
</div>
{{ end }}
</div>
{{ end }}
···
{{ define "contentAfter" }}
{{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }}
-
{{ end }}
+
{{end}}
{{ define "contentAfterLeft" }}
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
<div class="sticky top-0 flex-grow max-h-screen">
{{ template "repo/fragments/diffChangedFiles" .Diff }}
</div>
-
{{ end }}
+
{{end}}
+10 -11
appview/pages/templates/repo/compare/compare.html
···
{{ define "title" }}
-
comparing {{ .Base }} and {{ .Head }} on
-
{{ .RepoInfo.FullName }}
+
comparing {{ .Base }} and {{ .Head }} on {{ .RepoInfo.FullName }}
{{ end }}
{{ define "repoContent" }}
···
{{ end }}
{{ block "contentAfterLayout" . }}
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
-
{{ block "contentAfterLeft" . }}{{ end }}
-
</div>
-
<main class="col-span-1 md:col-span-10">
-
{{ block "contentAfter" . }}{{ end }}
-
</main>
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
+
{{ block "contentAfterLeft" . }} {{ end }}
</div>
+
<main class="col-span-1 md:col-span-10">
+
{{ block "contentAfter" . }}{{ end }}
+
</main>
+
</div>
{{ end }}
</div>
{{ end }}
···
{{ define "contentAfter" }}
{{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }}
-
{{ end }}
+
{{end}}
{{ define "contentAfterLeft" }}
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
<div class="sticky top-0 flex-grow max-h-screen">
{{ template "repo/fragments/diffChangedFiles" .Diff }}
</div>
-
{{ end }}
+
{{end}}
+9 -16
appview/pages/templates/repo/compare/new.html
···
{{ define "title" }}
-
compare refs on
-
{{ .RepoInfo.FullName }}
+
compare refs on {{ .RepoInfo.FullName }}
{{ end }}
{{ define "repoContent" }}
···
{{ define "repoAfter" }}
{{ $brs := take .Branches 5 }}
{{ if $brs }}
-
<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">
+
<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">
<div class="flex flex-col items-center">
<p class="text-center text-black dark:text-white">
-
Recently updated branches in this repository:
+
Recently updated branches in this repository:
</p>
-
<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">
-
{{ range $br := $brs }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/compare?head={{ $br.Name | urlquery }}"
-
class="no-underline hover:no-underline">
+
<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">
+
{{ range $br := $brs }}
+
<a href="/{{ $.RepoInfo.FullName }}/compare?head={{ $br.Name | urlquery }}" class="no-underline hover:no-underline">
<div class="flex items-center justify-between p-2">
{{ $br.Name }}
-
<span class="text-gray-500 dark:text-gray-400">
-
{{ template "repo/fragments/time" $br.Commit.Committer.When }}
-
</span>
+
<span class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" $br.Commit.Committer.When }}</span>
</div>
</a>
-
{{ end }}
-
</div>
+
{{ end }}
+
</div>
</div>
</section>
{{ end }}
+17 -48
appview/pages/templates/repo/empty.html
···
{{ define "title" }}{{ .RepoInfo.FullName }}{{ end }}
{{ define "extrameta" }}
-
{{ template "repo/fragments/meta" . }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
+
{{ template "repo/fragments/meta" . }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
{{ end }}
{{ define "repoContent" }}
···
{{ if gt (len .BranchesTrunc) 0 }}
<div class="flex flex-col items-center">
<p class="text-center pt-5 text-gray-400 dark:text-gray-500">
-
This branch is empty. Other branches in this repository are populated:
+
This branch is empty. Other branches in this repository are populated:
</p>
-
<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">
+
<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">
{{ range $br := .BranchesTrunc }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ $br.Name | urlquery }}"
-
class="no-underline hover:no-underline">
-
<div class="flex items-center justify-between p-2">
-
{{ $br.Name }}
-
<span class="text-gray-500 dark:text-gray-400">
-
{{ template "repo/fragments/time" $br.Commit.Committer.When }}
-
</span>
-
</div>
-
</a>
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{$br.Name | urlquery }}" class="no-underline hover:no-underline">
+
<div class="flex items-center justify-between p-2">
+
{{ $br.Name }}
+
<span class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" $br.Commit.Committer.When }}</span>
+
</div>
+
</a>
{{ end }}
</div>
</div>
{{ else if (and .LoggedInUser (eq .LoggedInUser.Did .RepoInfo.OwnerDid)) }}
{{ $knot := .RepoInfo.Knot }}
{{ if eq $knot "knot1.tangled.sh" }}
-
{{ $knot = "tangled.sh" }}
+
{{ $knot = "tangled.sh" }}
{{ end }}
<div class="w-full flex place-content-center">
<div class="py-6 w-fit flex flex-col gap-4">
<p>This is an empty repository. To get started:</p>
{{ $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" }}
-
-
<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>
-
<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>
-
<p>
-
<span class="{{ $bullet }}">3</span>
-
Configure your remote to
-
<code>
-
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}
-
</code>
-
</p>
-
<p>
-
<span class="{{ $bullet }}">4</span>
-
Push!
-
</p>
+
<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>
+
<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>
+
<p><span class="{{$bullet}}">3</span>Configure your remote to <code>git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code></p>
+
<p><span class="{{$bullet}}">4</span>Push!</p>
</div>
</div>
{{ else }}
-
<p class="text-gray-400 dark:text-gray-500 py-6 text-center">
-
This is an empty repository.
-
</p>
+
<p class="text-gray-400 dark:text-gray-500 py-6 text-center">This is an empty repository.</p>
{{ end }}
</main>
{{ end }}
{{ define "repoAfter" }}
-
{{ template "repo/fragments/cloneInstructions" . }}
+
{{ template "repo/fragments/cloneInstructions" . }}
{{ end }}
+31 -41
appview/pages/templates/repo/fork.html
···
{{ define "title" }}fork &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "content" }}
-
<div class="p-6">
-
<p class="text-xl font-bold dark:text-white">
-
Fork
-
{{ .RepoInfo.FullName }}
-
</p>
-
</div>
-
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
-
<form
-
hx-post="/{{ .RepoInfo.FullName }}/fork"
-
class="space-y-12"
-
hx-swap="none">
-
<fieldset class="space-y-3">
-
<legend class="dark:text-white">Select a knot to fork into</legend>
-
<div class="space-y-2">
-
<div class="flex flex-col">
-
{{ range .Knots }}
-
<div class="flex items-center">
-
<input
-
type="radio"
-
name="knot"
-
value="{{ . }}"
-
class="mr-2"
-
id="domain-{{ . }}" />
-
<span class="dark:text-white">{{ . }}</span>
-
</div>
-
{{ else }}
-
<p class="dark:text-white">No knots available.</p>
-
{{ end }}
+
<div class="p-6">
+
<p class="text-xl font-bold dark:text-white">Fork {{ .RepoInfo.FullName }}</p>
+
</div>
+
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
+
<form hx-post="/{{ .RepoInfo.FullName }}/fork" class="space-y-12" hx-swap="none">
+
<fieldset class="space-y-3">
+
<legend class="dark:text-white">Select a knot to fork into</legend>
+
<div class="space-y-2">
+
<div class="flex flex-col">
+
{{ range .Knots }}
+
<div class="flex items-center">
+
<input
+
type="radio"
+
name="knot"
+
value="{{ . }}"
+
class="mr-2"
+
id="domain-{{ . }}"
+
/>
+
<span class="dark:text-white">{{ . }}</span>
</div>
+
{{ else }}
+
<p class="dark:text-white">No knots available.</p>
+
{{ end }}
</div>
-
<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>
-
</fieldset>
-
-
<div class="space-y-2">
-
<button type="submit" class="btn">fork repo</button>
-
<div id="repo" class="error"></div>
</div>
-
</form>
-
</div>
+
<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>
+
</fieldset>
+
+
<div class="space-y-2">
+
<button type="submit" class="btn">fork repo</button>
+
<div id="repo" class="error"></div>
+
</div>
+
</form>
+
</div>
{{ end }}
+13 -27
appview/pages/templates/repo/fragments/artifact.html
···
{{ define "repo/fragments/artifact" }}
-
{{ $unique := .Artifact.BlobCid.String }}
-
<div
-
id="artifact-{{ $unique }}"
-
class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
-
<div id="left-side" class="flex items-center gap-2 min-w-0 max-w-[60%]">
-
{{ i "box" "w-4 h-4" }}
-
<a
-
href="/{{ .RepoInfo.FullName }}/tags/{{ .Artifact.Tag.String }}/download/{{ .Artifact.Name | urlquery }}"
-
class="no-underline hover:no-underline">
-
{{ .Artifact.Name }}
-
</a>
-
<span class="text-gray-500 dark:text-gray-400 pl-2 text-sm">
-
{{ byteFmt .Artifact.Size }}
-
</span>
-
</div>
+
{{ $unique := .Artifact.BlobCid.String }}
+
<div id="artifact-{{ $unique }}" class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
+
<div id="left-side" class="flex items-center gap-2 min-w-0 max-w-[60%]">
+
{{ i "box" "w-4 h-4" }}
+
<a href="/{{ .RepoInfo.FullName }}/tags/{{ .Artifact.Tag.String }}/download/{{ .Artifact.Name | urlquery }}" class="no-underline hover:no-underline">
+
{{ .Artifact.Name }}
+
</a>
+
<span class="text-gray-500 dark:text-gray-400 pl-2 text-sm">{{ byteFmt .Artifact.Size }}</span>
+
</div>
-
<div
-
id="right-side"
-
class="text-gray-500 dark:text-gray-400 flex items-center flex-shrink-0 gap-2 text-sm">
-
<span class="hidden md:inline">
-
{{ template "repo/fragments/time" .Artifact.CreatedAt }}
-
</span>
-
<span class=" md:hidden">
-
{{ template "repo/fragments/shortTime" .Artifact.CreatedAt }}
-
</span>
+
<div id="right-side" class="text-gray-500 dark:text-gray-400 flex items-center flex-shrink-0 gap-2 text-sm">
+
<span class="hidden md:inline">{{ template "repo/fragments/time" .Artifact.CreatedAt }}</span>
+
<span class=" md:hidden">{{ template "repo/fragments/shortTime" .Artifact.CreatedAt }}</span>
<span class="select-none after:content-['·'] hidden md:inline"></span>
-
<span class="truncate max-w-[100px] hidden md:inline">
-
{{ .Artifact.MimeType }}
-
</span>
+
<span class="truncate max-w-[100px] hidden md:inline">{{ .Artifact.MimeType }}</span>
{{ if and .LoggedInUser (eq .LoggedInUser.Did .Artifact.Did) }}
<button
+49 -48
appview/pages/templates/repo/fragments/cloneInstructions.html
···
{{ define "repo/fragments/cloneInstructions" }}
-
{{ $knot := .RepoInfo.Knot }}
-
{{ if eq $knot "knot1.tangled.sh" }}
-
{{ $knot = "tangled.sh" }}
-
{{ end }}
-
<section
-
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">
-
<div class="flex flex-col gap-2">
-
<strong>push</strong>
-
<div class="md:pl-4 overflow-x-auto whitespace-nowrap">
-
<code class="dark:text-gray-100">
-
git remote add origin
-
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}
-
</code>
-
</div>
-
</div>
+
{{ $knot := .RepoInfo.Knot }}
+
{{ if eq $knot "knot1.tangled.sh" }}
+
{{ $knot = "tangled.sh" }}
+
{{ end }}
+
<section
+
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"
+
>
+
<div class="flex flex-col gap-2">
+
<strong>push</strong>
+
<div class="md:pl-4 overflow-x-auto whitespace-nowrap">
+
<code class="dark:text-gray-100"
+
>git remote add origin
+
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code
+
>
+
</div>
+
</div>
-
<div class="flex flex-col gap-2">
-
<strong>clone</strong>
-
<div class="md:pl-4 flex flex-col gap-2">
-
<div class="flex items-center gap-3">
-
<span
-
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white">
-
HTTP
-
</span>
-
<div class="overflow-x-auto whitespace-nowrap flex-1">
-
<code class="dark:text-gray-100">
-
git clone
-
https://tangled.sh/{{ .RepoInfo.OwnerWithAt }}/{{ .RepoInfo.Name }}
-
</code>
-
</div>
-
</div>
+
<div class="flex flex-col gap-2">
+
<strong>clone</strong>
+
<div class="md:pl-4 flex flex-col gap-2">
+
<div class="flex items-center gap-3">
+
<span
+
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white"
+
>HTTP</span
+
>
+
<div class="overflow-x-auto whitespace-nowrap flex-1">
+
<code class="dark:text-gray-100"
+
>git clone
+
https://tangled.sh/{{ .RepoInfo.OwnerWithAt }}/{{ .RepoInfo.Name }}</code
+
>
+
</div>
+
</div>
-
<div class="flex items-center gap-3">
-
<span
-
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white">
-
SSH
-
</span>
-
<div class="overflow-x-auto whitespace-nowrap flex-1">
-
<code class="dark:text-gray-100">
-
git clone
-
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}
-
</code>
-
</div>
+
<div class="flex items-center gap-3">
+
<span
+
class="bg-gray-100 dark:bg-gray-700 p-1 mr-1 font-mono text-sm rounded select-none dark:text-white"
+
>SSH</span
+
>
+
<div class="overflow-x-auto whitespace-nowrap flex-1">
+
<code class="dark:text-gray-100"
+
>git clone
+
git@{{ $knot }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code
+
>
+
</div>
+
</div>
+
</div>
</div>
-
</div>
-
</div>
-
<p class="py-2 text-gray-500 dark:text-gray-400">
-
Note that for self-hosted knots, clone URLs may be different based on your
-
setup.
-
</p>
-
</section>
+
<p class="py-2 text-gray-500 dark:text-gray-400">
+
Note that for self-hosted knots, clone URLs may be different based
+
on your setup.
+
</p>
+
</section>
{{ end }}
+22 -20
appview/pages/templates/repo/fragments/compareAllowPull.html
···
{{ define "repo/fragments/compareAllowPull" }}
-
<div
-
class="flex items-baseline justify-normal gap-4"
-
id="allow-pull"
-
hx-oob-swap="true">
-
<p>
-
This comparison can be turned into a pull request to be reviewed and
-
discussed.
-
</p>
+
<div
+
class="flex items-baseline justify-normal gap-4"
+
id="allow-pull"
+
hx-oob-swap="true"
+
>
+
<p>
+
This comparison can be turned into a pull request to be reviewed and
+
discussed.
+
</p>
-
{{ $newPullUrl := printf "/%s/pulls/new?strategy=branch&targetBranch=%s&sourceBranch=%s" .RepoInfo.FullName .Base .Head }}
+
{{ $newPullUrl := printf "/%s/pulls/new?strategy=branch&targetBranch=%s&sourceBranch=%s" .RepoInfo.FullName .Base .Head }}
-
<div class="flex justify-start items-center gap-2 mt-2">
-
<a
-
href="{{ $newPullUrl }}"
-
class="btn flex items-center gap-2 no-underline hover:no-underline">
-
{{ i "git-pull-request-create" "w-4 h-4" }}
-
create pull
-
<span id="create-pull-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</a>
+
<div class="flex justify-start items-center gap-2 mt-2">
+
<a
+
href="{{ $newPullUrl }}"
+
class="btn flex items-center gap-2 no-underline hover:no-underline"
+
>
+
{{ i "git-pull-request-create" "w-4 h-4" }}
+
create pull
+
<span id="create-pull-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</a>
+
</div>
</div>
-
</div>
{{ end }}
+54 -63
appview/pages/templates/repo/fragments/compareForm.html
···
{{ define "repo/fragments/compareForm" }}
-
<div id="compare-select">
-
<h2 class="font-bold text-sm mb-2 uppercase dark:text-white">
-
Compare changes
-
</h2>
-
<p>Choose any two refs to compare.</p>
+
<div id="compare-select">
+
<h2 class="font-bold text-sm mb-2 uppercase dark:text-white">
+
Compare changes
+
</h2>
+
<p>Choose any two refs to compare.</p>
-
<form id="compare-form" class="flex items-center gap-2 py-4">
-
<div>
-
<span class="hidden md:inline">base:</span>
-
{{ block "dropdown" (list $ "base" $.Base) }}{{ end }}
-
</div>
-
<span class="flex-shrink-0">
-
{{ i "arrow-left" "w-4 h-4" }}
-
</span>
-
<div>
-
<span class="hidden md:inline">compare:</span>
-
{{ block "dropdown" (list $ "head" $.Head) }}{{ end }}
-
</div>
-
<button
-
id="compare-button"
-
class="btn disabled:opacity-50 disabled:cursor-not-allowed"
-
type="button"
-
hx-boost="true"
-
onclick="
+
<form id="compare-form" class="flex items-center gap-2 py-4">
+
<div>
+
<span class="hidden md:inline">base:</span>
+
{{ block "dropdown" (list $ "base" $.Base) }} {{ end }}
+
</div>
+
<span class="flex-shrink-0">
+
{{ i "arrow-left" "w-4 h-4" }}
+
</span>
+
<div>
+
<span class="hidden md:inline">compare:</span>
+
{{ block "dropdown" (list $ "head" $.Head) }} {{ end }}
+
</div>
+
<button
+
id="compare-button"
+
class="btn disabled:opacity-50 disabled:cursor-not-allowed"
+
type="button"
+
hx-boost="true"
+
onclick="
const base = document.getElementById('base-select').value;
const head = document.getElementById('head-select').value;
-
window.location.href = `/{{ $.RepoInfo.FullName }}/compare/${encodeURIComponent(base)}...${encodeURIComponent(head)}`;
+
window.location.href = `/{{$.RepoInfo.FullName}}/compare/${encodeURIComponent(base)}...${encodeURIComponent(head)}`;
">
-
go
-
</button>
-
</form>
-
</div>
-
<script>
-
const baseSelect = document.getElementById("base-select");
-
const headSelect = document.getElementById("head-select");
-
const compareButton = document.getElementById("compare-button");
+
go
+
</button>
+
</form>
+
</div>
+
<script>
+
const baseSelect = document.getElementById('base-select');
+
const headSelect = document.getElementById('head-select');
+
const compareButton = document.getElementById('compare-button');
-
function toggleButtonState() {
-
compareButton.disabled = baseSelect.value === headSelect.value;
-
}
+
function toggleButtonState() {
+
compareButton.disabled = baseSelect.value === headSelect.value;
+
}
-
baseSelect.addEventListener("change", toggleButtonState);
-
headSelect.addEventListener("change", toggleButtonState);
+
baseSelect.addEventListener('change', toggleButtonState);
+
headSelect.addEventListener('change', toggleButtonState);
-
// Run once on page load
-
toggleButtonState();
-
</script>
+
// Run once on page load
+
toggleButtonState();
+
</script>
{{ end }}
{{ define "dropdown" }}
-
{{ $root := index . 0 }}
-
{{ $name := index . 1 }}
-
{{ $default := index . 2 }}
-
<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">
+
{{ $root := index . 0 }}
+
{{ $name := index . 1 }}
+
{{ $default := index . 2 }}
+
<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">
<optgroup label="branches ({{ len $root.Branches }})" class="bold text-sm">
{{ range $root.Branches }}
-
<option
-
value="{{ .Reference.Name }}"
-
class="py-1"
-
{{ if eq .Reference.Name $default }}selected{{ end }}>
+
<option value="{{ .Reference.Name }}" class="py-1" {{if eq .Reference.Name $default}}selected{{end}}>
{{ .Reference.Name }}
</option>
{{ end }}
</optgroup>
-
<optgroup label="tags ({{ len $root.Tags }})" class="bold text-sm">
-
{{ range $root.Tags }}
-
<option
-
value="{{ .Reference.Name }}"
-
class="py-1"
-
{{ if eq .Reference.Name $default }}selected{{ end }}>
-
{{ .Reference.Name }}
-
</option>
-
{{ else }}
-
<option class="py-1" disabled>no tags found</option>
-
{{ end }}
-
</optgroup>
+
<optgroup label="tags ({{ len $root.Tags }})" class="bold text-sm">
+
{{ range $root.Tags }}
+
<option value="{{ .Reference.Name }}" class="py-1" {{if eq .Reference.Name $default}}selected{{end}}>
+
{{ .Reference.Name }}
+
</option>
+
{{ else }}
+
<option class="py-1" disabled>no tags found</option>
+
{{ end }}
+
</optgroup>
</select>
{{ end }}
+78 -127
appview/pages/templates/repo/fragments/diff.html
···
{{ $parent := $commit.Parent }}
{{ $last := sub (len $diff) 1 }}
-
<div class="flex flex-col gap-4">
{{ range $idx, $hunk := $diff }}
{{ with $hunk }}
-
<section
-
class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
-
<div id="file-{{ .Name.New }}">
-
<div id="diff-file">
-
<details open>
-
<summary class="list-none cursor-pointer sticky top-0">
-
<div
-
id="diff-file-header"
-
class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
-
<div
-
id="left-side-items"
-
class="p-2 flex gap-2 items-center overflow-x-auto">
-
<div class="flex gap-1 items-center">
-
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
-
{{ if .IsNew }}
-
<span
-
class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">
-
ADDED
-
</span>
-
{{ else if .IsDelete }}
-
<span
-
class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">
-
DELETED
-
</span>
-
{{ else if .IsCopy }}
-
<span
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
-
COPIED
-
</span>
-
{{ else if .IsRename }}
-
<span
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
-
RENAMED
-
</span>
-
{{ else }}
-
<span
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
-
MODIFIED
-
</span>
-
{{ end }}
+
<section class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
+
<div id="file-{{ .Name.New }}">
+
<div id="diff-file">
+
<details open>
+
<summary class="list-none cursor-pointer sticky top-0">
+
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
+
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
+
<div class="flex gap-1 items-center">
+
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
+
{{ if .IsNew }}
+
<span class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">ADDED</span>
+
{{ else if .IsDelete }}
+
<span class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">DELETED</span>
+
{{ else if .IsCopy }}
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">COPIED</span>
+
{{ else if .IsRename }}
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">RENAMED</span>
+
{{ else }}
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">MODIFIED</span>
+
{{ end }}
-
{{ template "repo/fragments/diffStatPill" .Stats }}
-
</div>
-
-
<div class="flex gap-2 items-center overflow-x-auto">
-
{{ if .IsDelete }}
-
<a
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
-
{{ if $this }}
-
href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"
-
{{ end }}>
-
{{ .Name.Old }}
-
</a>
-
{{ else if (or .IsCopy .IsRename) }}
-
<a
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
-
{{ if $parent }}
-
href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}"
-
{{ end }}>
-
{{ .Name.Old }}
-
</a>
-
{{ i "arrow-right" "w-4 h-4" }}
-
<a
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
-
{{ if $this }}
-
href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"
-
{{ end }}>
-
{{ .Name.New }}
-
</a>
-
{{ else }}
-
<a
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
-
{{ if $this }}
-
href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"
-
{{ end }}>
-
{{ .Name.New }}
-
</a>
-
{{ end }}
-
</div>
+
{{ template "repo/fragments/diffStatPill" .Stats }}
</div>
-
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
-
<div id="right-side-items" class="p-2 flex items-center">
-
<a
-
title="top of file"
-
href="#file-{{ .Name.New }}"
-
class="{{ $iconstyle }}">
-
{{ i "arrow-up-to-line" "w-4 h-4" }}
+
<div class="flex gap-2 items-center overflow-x-auto">
+
{{ if .IsDelete }}
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}>
+
{{ .Name.Old }}
</a>
-
{{ if gt $idx 0 }}
-
{{ $prev := index $diff (sub $idx 1) }}
-
<a
-
title="previous file"
-
href="#file-{{ $prev.Name.New }}"
-
class="{{ $iconstyle }}">
-
{{ i "arrow-up" "w-4 h-4" }}
-
</a>
-
{{ end }}
-
-
{{ if lt $idx $last }}
-
{{ $next := index $diff (add $idx 1) }}
-
<a
-
title="next file"
-
href="#file-{{ $next.Name.New }}"
-
class="{{ $iconstyle }}">
-
{{ i "arrow-down" "w-4 h-4" }}
-
</a>
+
{{ else if (or .IsCopy .IsRename) }}
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $parent}}href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}"{{end}}>
+
{{ .Name.Old }}
+
</a>
+
{{ i "arrow-right" "w-4 h-4" }}
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
+
{{ .Name.New }}
+
</a>
+
{{ else }}
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
+
{{ .Name.New }}
+
</a>
{{ end }}
</div>
</div>
-
</summary>
-
<div class="transition-all duration-700 ease-in-out">
-
{{ if .IsDelete }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
This file has been deleted.
-
</p>
-
{{ else if .IsCopy }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
This file has been copied.
-
</p>
-
{{ else if .IsBinary }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
This is a binary file and will not be displayed.
-
</p>
-
{{ else }}
-
{{ if $isSplit }}
-
{{- template "repo/fragments/splitDiff" .Split -}}
-
{{ else }}
-
{{- template "repo/fragments/unifiedDiff" . -}}
+
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
+
<div id="right-side-items" class="p-2 flex items-center">
+
<a title="top of file" href="#file-{{ .Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-up-to-line" "w-4 h-4" }}</a>
+
{{ if gt $idx 0 }}
+
{{ $prev := index $diff (sub $idx 1) }}
+
<a title="previous file" href="#file-{{ $prev.Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-up" "w-4 h-4" }}</a>
{{ end }}
-
{{- end -}}
+
+
{{ if lt $idx $last }}
+
{{ $next := index $diff (add $idx 1) }}
+
<a title="next file" href="#file-{{ $next.Name.New }}" class="{{ $iconstyle }}">{{ i "arrow-down" "w-4 h-4" }}</a>
+
{{ end }}
+
</div>
+
</div>
-
</details>
-
</div>
+
</summary>
+
+
<div class="transition-all duration-700 ease-in-out">
+
{{ if .IsDelete }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This file has been deleted.
+
</p>
+
{{ else if .IsCopy }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This file has been copied.
+
</p>
+
{{ else if .IsBinary }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This is a binary file and will not be displayed.
+
</p>
+
{{ else }}
+
{{ if $isSplit }}
+
{{- template "repo/fragments/splitDiff" .Split -}}
+
{{ else }}
+
{{- template "repo/fragments/unifiedDiff" . -}}
+
{{ end }}
+
{{- end -}}
+
</div>
+
+
</details>
+
</div>
-
</section>
+
</div>
+
</section>
{{ end }}
{{ end }}
</div>
+2 -5
appview/pages/templates/repo/fragments/diffChangedFiles.html
···
{{ define "repo/fragments/diffChangedFiles" }}
{{ $stat := .Stat }}
{{ $fileTree := fileTree .ChangedFiles }}
-
<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">
+
<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">
<div class="diff-stat">
<div class="flex gap-2 items-center">
-
<strong class="text-sm uppercase dark:text-gray-200">
-
Changed files
-
</strong>
+
<strong class="text-sm uppercase dark:text-gray-200">Changed files</strong>
{{ template "repo/fragments/diffStatPill" $stat }}
</div>
{{ template "repo/fragments/fileTree" $fileTree }}
+6 -14
appview/pages/templates/repo/fragments/diffOpts.html
···
{{ define "repo/fragments/diffOpts" }}
-
<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">
+
<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">
<strong class="text-sm uppercase dark:text-gray-200">options</strong>
{{ $active := "unified" }}
{{ if .Split }}
{{ $active = "split" }}
{{ end }}
{{ $values := list "unified" "split" }}
-
{{ block "tabSelector" (dict "Name" "diff" "Values" $values "Active" $active) }}
-
{{ end }}
+
{{ block "tabSelector" (dict "Name" "diff" "Values" $values "Active" $active) }} {{ end }}
</section>
{{ end }}
···
{{ $name := .Name }}
{{ $all := .Values }}
{{ $active := .Active }}
-
<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">
+
<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">
{{ $activeTab := "bg-white dark:bg-gray-700 shadow-sm" }}
{{ $inactiveTab := "bg-gray-100 dark:bg-gray-800 shadow-inner" }}
{{ range $index, $value := $all }}
{{ $isActive := eq $value $active }}
-
<a
-
href="?{{ $name }}={{ $value }}"
-
class="py-2 text-sm w-full block hover:no-underline text-center {{ if $isActive }}
-
{{ $activeTab }}
-
{{ else }}
-
{{ $inactiveTab }}
-
{{ end }}">
-
{{ $value }}
+
<a href="?{{ $name }}={{ $value }}"
+
class="py-2 text-sm w-full block hover:no-underline text-center {{ if $isActive }} {{$activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}">
+
{{ $value }}
</a>
{{ end }}
</div>
+5 -16
appview/pages/templates/repo/fragments/diffStatPill.html
···
{{ define "repo/fragments/diffStatPill" }}
<div class="flex items-center font-mono text-sm">
{{ if and .Insertions .Deletions }}
-
<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>
-
<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>
+
<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>
+
<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>
{{ else if .Insertions }}
-
<span
-
class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">
-
+{{ .Insertions }}
-
</span>
+
<span class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span>
{{ else if .Deletions }}
-
<span
-
class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">
-
-{{ .Deletions }}
-
</span>
+
<span class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span>
{{ end }}
</div>
{{ end }}
+
+7 -20
appview/pages/templates/repo/fragments/editRepoDescription.html
···
{{ define "repo/fragments/editRepoDescription" }}
-
<form
-
hx-put="/{{ .RepoInfo.FullName }}/description"
-
hx-target="this"
-
hx-swap="outerHTML"
-
class="flex flex-wrap gap-2">
-
<input
-
type="text"
-
class="p-1"
-
name="description"
-
value="{{ .RepoInfo.Description }}" />
-
<button
-
type="submit"
-
class="btn p-1 flex items-center gap-2 no-underline text-sm">
-
{{ i "check" "w-3 h-3" }} save
+
<form hx-put="/{{ .RepoInfo.FullName }}/description" hx-target="this" hx-swap="outerHTML" class="flex flex-wrap gap-2">
+
<input type="text" class="p-1" name="description" value="{{ .RepoInfo.Description }}">
+
<button type="submit" class="btn p-1 flex items-center gap-2 no-underline text-sm">
+
{{ i "check" "w-3 h-3" }} save
</button>
-
<button
-
type="button"
-
class="btn p-1 flex items-center gap-2 no-underline text-sm"
-
hx-get="/{{ .RepoInfo.FullName }}/description">
-
{{ i "x" "w-3 h-3" }} cancel
+
<button type="button" class="btn p-1 flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description" >
+
{{ i "x" "w-3 h-3" }} cancel
</button>
-
</form>
+
</form>
{{ end }}
+3 -8
appview/pages/templates/repo/fragments/fileTree.html
···
<summary class="cursor-pointer list-none pt-1">
<span class="tree-directory inline-flex items-center gap-2 ">
{{ i "folder" "flex-shrink-0 size-4 fill-current" }}
-
<span class="filename truncate text-black dark:text-white">
-
{{ .Name }}
-
</span>
+
<span class="filename truncate text-black dark:text-white">{{ .Name }}</span>
</span>
</summary>
<div class="ml-1 pl-2 border-l border-gray-200 dark:border-gray-700">
···
{{ else if .Name }}
<div class="tree-file flex items-center gap-2 pt-1">
{{ i "file" "flex-shrink-0 size-4" }}
-
<a
-
href="#file-{{ .Path }}"
-
class="filename truncate text-black dark:text-white no-underline hover:underline">
-
{{ .Name }}
-
</a>
+
<a href="#file-{{ .Path }}" class="filename truncate text-black dark:text-white no-underline hover:underline">{{ .Name }}</a>
</div>
{{ else }}
{{ range $child := .Children }}
···
{{ end }}
{{ end }}
{{ end }}
+
+82 -124
appview/pages/templates/repo/fragments/interdiff.html
···
{{ define "repo/fragments/interdiff" }}
-
{{ $repo := index . 0 }}
-
{{ $x := index . 1 }}
-
{{ $opts := index . 2 }}
-
{{ $fileTree := fileTree $x.AffectedFiles }}
-
{{ $diff := $x.Files }}
-
{{ $last := sub (len $diff) 1 }}
-
{{ $isSplit := $opts.Split }}
+
{{ $repo := index . 0 }}
+
{{ $x := index . 1 }}
+
{{ $opts := index . 2 }}
+
{{ $fileTree := fileTree $x.AffectedFiles }}
+
{{ $diff := $x.Files }}
+
{{ $last := sub (len $diff) 1 }}
+
{{ $isSplit := $opts.Split }}
+
<div class="flex flex-col gap-4">
+
{{ range $idx, $hunk := $diff }}
+
{{ with $hunk }}
+
<section class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
+
<div id="file-{{ .Name }}">
+
<div id="diff-file">
+
<details {{ if not (.Status.IsOnlyInOne) }}open{{end}}>
+
<summary class="list-none cursor-pointer sticky top-0">
+
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
+
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
+
<div class="flex gap-1 items-center" style="direction: ltr;">
+
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
+
{{ if .Status.IsOk }}
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">CHANGED</span>
+
{{ else if .Status.IsUnchanged }}
+
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">UNCHANGED</span>
+
{{ else if .Status.IsOnlyInOne }}
+
<span class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">REVERTED</span>
+
{{ else if .Status.IsOnlyInTwo }}
+
<span class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">NEW</span>
+
{{ else if .Status.IsRebased }}
+
<span class="bg-amber-100 text-amber-700 dark:bg-amber-800/50 dark:text-amber-400 {{ $markerstyle }}">REBASED</span>
+
{{ else }}
+
<span class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">ERROR</span>
+
{{ end }}
+
</div>
-
<div class="flex flex-col gap-4">
-
{{ range $idx, $hunk := $diff }}
-
{{ with $hunk }}
-
<section
-
class="border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
-
<div id="file-{{ .Name }}">
-
<div id="diff-file">
-
<details {{ if not (.Status.IsOnlyInOne) }}open{{ end }}>
-
<summary class="list-none cursor-pointer sticky top-0">
-
<div
-
id="diff-file-header"
-
class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
-
<div
-
id="left-side-items"
-
class="p-2 flex gap-2 items-center overflow-x-auto">
-
<div
-
class="flex gap-1 items-center"
-
style="direction: ltr;">
-
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
-
{{ if .Status.IsOk }}
-
<span
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
-
CHANGED
-
</span>
-
{{ else if .Status.IsUnchanged }}
-
<span
-
class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">
-
UNCHANGED
-
</span>
-
{{ else if .Status.IsOnlyInOne }}
-
<span
-
class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">
-
REVERTED
-
</span>
-
{{ else if .Status.IsOnlyInTwo }}
-
<span
-
class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">
-
NEW
-
</span>
-
{{ else if .Status.IsRebased }}
-
<span
-
class="bg-amber-100 text-amber-700 dark:bg-amber-800/50 dark:text-amber-400 {{ $markerstyle }}">
-
REBASED
-
</span>
-
{{ else }}
-
<span
-
class="bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400 {{ $markerstyle }}">
-
ERROR
-
</span>
-
{{ end }}
-
</div>
+
<div class="flex gap-2 items-center overflow-x-auto" style="direction: rtl;">
+
<a class="dark:text-white whitespace-nowrap overflow-x-auto" href="">
+
{{ .Name }}
+
</a>
+
</div>
+
</div>
-
<div
-
class="flex gap-2 items-center overflow-x-auto"
-
style="direction: rtl;">
-
<a
-
class="dark:text-white whitespace-nowrap overflow-x-auto"
-
href="">
-
{{ .Name }}
-
</a>
-
</div>
-
</div>
+
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
+
<div id="right-side-items" class="p-2 flex items-center">
+
<a title="top of file" href="#file-{{ .Name }}" class="{{ $iconstyle }}">{{ i "arrow-up-to-line" "w-4 h-4" }}</a>
+
{{ if gt $idx 0 }}
+
{{ $prev := index $diff (sub $idx 1) }}
+
<a title="previous file" href="#file-{{ $prev.Name }}" class="{{ $iconstyle }}">{{ i "arrow-up" "w-4 h-4" }}</a>
+
{{ end }}
-
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded" }}
-
<div id="right-side-items" class="p-2 flex items-center">
-
<a
-
title="top of file"
-
href="#file-{{ .Name }}"
-
class="{{ $iconstyle }}">
-
{{ i "arrow-up-to-line" "w-4 h-4" }}
-
</a>
-
{{ if gt $idx 0 }}
-
{{ $prev := index $diff (sub $idx 1) }}
-
<a
-
title="previous file"
-
href="#file-{{ $prev.Name }}"
-
class="{{ $iconstyle }}">
-
{{ i "arrow-up" "w-4 h-4" }}
-
</a>
-
{{ end }}
+
{{ if lt $idx $last }}
+
{{ $next := index $diff (add $idx 1) }}
+
<a title="next file" href="#file-{{ $next.Name }}" class="{{ $iconstyle }}">{{ i "arrow-down" "w-4 h-4" }}</a>
+
{{ end }}
+
</div>
-
{{ if lt $idx $last }}
-
{{ $next := index $diff (add $idx 1) }}
-
<a
-
title="next file"
-
href="#file-{{ $next.Name }}"
-
class="{{ $iconstyle }}">
-
{{ i "arrow-down" "w-4 h-4" }}
-
</a>
-
{{ end }}
-
</div>
-
</div>
-
</summary>
+
</div>
+
</summary>
-
<div class="transition-all duration-700 ease-in-out">
-
{{ if .Status.IsUnchanged }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
This file has not been changed.
-
</p>
-
{{ else if .Status.IsRebased }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
This patch was likely rebased, as context lines do not
-
match.
-
</p>
-
{{ else if .Status.IsError }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
Failed to calculate interdiff for this file.
-
</p>
-
{{ else }}
-
{{ if $isSplit }}
-
{{- template "repo/fragments/splitDiff" .Split -}}
-
{{ else }}
-
{{- template "repo/fragments/unifiedDiff" . -}}
-
{{ end }}
-
{{- end -}}
-
</div>
-
</details>
+
<div class="transition-all duration-700 ease-in-out">
+
{{ if .Status.IsUnchanged }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This file has not been changed.
+
</p>
+
{{ else if .Status.IsRebased }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This patch was likely rebased, as context lines do not match.
+
</p>
+
{{ else if .Status.IsError }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
Failed to calculate interdiff for this file.
+
</p>
+
{{ else }}
+
{{ if $isSplit }}
+
{{- template "repo/fragments/splitDiff" .Split -}}
+
{{ else }}
+
{{- template "repo/fragments/unifiedDiff" . -}}
+
{{ end }}
+
{{- end -}}
</div>
-
</div>
-
</section>
-
{{ end }}
+
+
</details>
+
+
</div>
+
</div>
+
</section>
{{ end }}
-
</div>
+
{{ end }}
+
</div>
{{ end }}
+
+8 -9
appview/pages/templates/repo/fragments/interdiffFiles.html
···
{{ define "repo/fragments/interdiffFiles" }}
-
{{ $fileTree := fileTree .AffectedFiles }}
-
<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">
-
<div class="diff-stat">
-
<div class="flex gap-2 items-center">
-
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
-
</div>
-
{{ template "repo/fragments/fileTree" $fileTree }}
+
{{ $fileTree := fileTree .AffectedFiles }}
+
<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">
+
<div class="diff-stat">
+
<div class="flex gap-2 items-center">
+
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
</div>
-
</section>
+
{{ template "repo/fragments/fileTree" $fileTree }}
+
</div>
+
</section>
{{ end }}
+24 -18
appview/pages/templates/repo/fragments/meta.html
···
{{ define "repo/fragments/meta" }}
-
<meta
-
name="vcs:clone"
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}" />
-
<meta
-
name="forge:summary"
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}" />
-
<meta
-
name="forge:dir"
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}/tree/{ref}/{path}" />
-
<meta
-
name="forge:file"
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}" />
-
<meta
-
name="forge:line"
-
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}#L{line}" />
-
<meta
-
name="go-import"
-
content="tangled.sh/{{ .RepoInfo.FullNameWithoutAt }} git https://tangled.sh/{{ .RepoInfo.FullName }}" />
+
<meta
+
name="vcs:clone"
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}"
+
/>
+
<meta
+
name="forge:summary"
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}"
+
/>
+
<meta
+
name="forge:dir"
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}/tree/{ref}/{path}"
+
/>
+
<meta
+
name="forge:file"
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}"
+
/>
+
<meta
+
name="forge:line"
+
content="https://tangled.sh/{{ .RepoInfo.FullName }}/blob/{ref}/{path}#L{line}"
+
/>
+
<meta
+
name="go-import"
+
content="tangled.sh/{{ .RepoInfo.FullNameWithoutAt }} git https://tangled.sh/{{ .RepoInfo.FullName }}"
+
/>
{{ end }}
+7 -7
appview/pages/templates/repo/fragments/og.html
···
{{ define "repo/fragments/og" }}
-
{{ $title := or .Title .RepoInfo.FullName }}
-
{{ $description := or .Description .RepoInfo.Description }}
-
{{ $url := or .Url (printf "https://tangled.sh/%s" .RepoInfo.FullName) }}
+
{{ $title := or .Title .RepoInfo.FullName }}
+
{{ $description := or .Description .RepoInfo.Description }}
+
{{ $url := or .Url (printf "https://tangled.sh/%s" .RepoInfo.FullName) }}
-
<meta property="og:title" content="{{ unescapeHtml $title }}" />
-
<meta property="og:type" content="object" />
-
<meta property="og:url" content="{{ $url }}" />
-
<meta property="og:description" content="{{ $description }}" />
+
<meta property="og:title" content="{{ unescapeHtml $title }}" />
+
<meta property="og:type" content="object" />
+
<meta property="og:url" content="{{ $url }}" />
+
<meta property="og:description" content="{{ $description }}" />
{{ end }}
+28 -21
appview/pages/templates/repo/fragments/reaction.html
···
{{ define "repo/fragments/reaction" }}
-
<button
-
id="reactIndi-{{ .Kind }}"
-
class="flex justify-center items-center min-w-8 min-h-8 rounded border
+
<button
+
id="reactIndi-{{ .Kind }}"
+
class="flex justify-center items-center min-w-8 min-h-8 rounded border
leading-4 px-3 gap-1
{{ if eq .Count 0 }}
-
hidden
-
{{ end }}
+
hidden
+
{{ end }}
{{ if .IsReacted }}
-
bg-sky-100 border-sky-400 dark:bg-sky-900 dark:border-sky-500
-
{{ else }}
-
border-gray-200 hover:bg-gray-50 hover:border-gray-300
-
dark:border-gray-700 dark:hover:bg-gray-700 dark:hover:border-gray-600
-
{{ end }}
+
bg-sky-100
+
border-sky-400
+
dark:bg-sky-900
+
dark:border-sky-500
+
{{ else }}
+
border-gray-200
+
hover:bg-gray-50
+
hover:border-gray-300
+
dark:border-gray-700
+
dark:hover:bg-gray-700
+
dark:hover:border-gray-600
+
{{ end }}
"
-
{{ if .IsReacted }}
-
hx-delete="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
-
{{ else }}
-
hx-post="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
-
{{ end }}
-
hx-swap="outerHTML"
-
hx-trigger="click from:(#reactBtn-{{ .Kind }}, #reactIndi-{{ .Kind }})"
-
hx-disabled-elt="this">
-
<span>{{ .Kind }}</span>
-
<span>{{ .Count }}</span>
-
</button>
+
{{ if .IsReacted }}
+
hx-delete="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
+
{{ else }}
+
hx-post="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
+
{{ end }}
+
hx-swap="outerHTML"
+
hx-trigger="click from:(#reactBtn-{{ .Kind }}, #reactIndi-{{ .Kind }})"
+
hx-disabled-elt="this"
+
>
+
<span>{{ .Kind }}</span> <span>{{ .Count }}</span>
+
</button>
{{ end }}
+24 -18
appview/pages/templates/repo/fragments/reactionsPopUp.html
···
{{ define "repo/fragments/reactionsPopUp" }}
-
<details id="reactionsPopUp" class="relative inline-block">
-
<summary
-
class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700
+
<details
+
id="reactionsPopUp"
+
class="relative inline-block"
+
>
+
<summary
+
class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700
hover:bg-gray-50
hover:border-gray-300
dark:hover:bg-gray-700
dark:hover:border-gray-600
-
cursor-pointer list-none">
-
{{ i "smile" "size-4" }}
-
</summary>
-
<div
-
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">
-
{{ range $kind := . }}
-
<button
-
id="reactBtn-{{ $kind }}"
-
class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700"
-
hx-on:click="this.parentElement.parentElement.removeAttribute('open')">
-
{{ $kind }}
-
</button>
-
{{ end }}
-
</div>
-
</details>
+
cursor-pointer list-none"
+
>
+
{{ i "smile" "size-4" }}
+
</summary>
+
<div
+
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"
+
>
+
{{ range $kind := . }}
+
<button
+
id="reactBtn-{{ $kind }}"
+
class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700"
+
hx-on:click="this.parentElement.parentElement.removeAttribute('open')"
+
>
+
{{ $kind }}
+
</button>
+
{{ end }}
+
</div>
+
</details>
{{ end }}
+7 -13
appview/pages/templates/repo/fragments/repoDescription.html
···
{{ define "repo/fragments/repoDescription" }}
-
<span
-
id="repo-description"
-
class="flex flex-wrap items-center gap-2 text-sm"
-
hx-target="this"
-
hx-swap="outerHTML">
+
<span id="repo-description" class="flex flex-wrap items-center gap-2 text-sm" hx-target="this" hx-swap="outerHTML">
{{ if .RepoInfo.Description }}
-
{{ .RepoInfo.Description }}
+
{{ .RepoInfo.Description }}
{{ else }}
-
<span class="italic">this repo has no description</span>
+
<span class="italic">this repo has no description</span>
{{ end }}
{{ if .RepoInfo.Roles.IsOwner }}
-
<button
-
class="flex items-center gap-2 no-underline text-sm"
-
hx-get="/{{ .RepoInfo.FullName }}/description/edit">
-
{{ i "pencil" "w-3 h-3" }}
-
</button>
+
<button class="flex items-center gap-2 no-underline text-sm" hx-get="/{{ .RepoInfo.FullName }}/description/edit">
+
{{ i "pencil" "w-3 h-3" }}
+
</button>
{{ end }}
-
</span>
+
</span>
{{ end }}
+23 -22
appview/pages/templates/repo/fragments/repoStar.html
···
{{ define "repo/fragments/repoStar" }}
-
<button
-
id="starBtn"
-
class="btn disabled:opacity-50 disabled:cursor-not-allowed flex gap-2 items-center group"
-
{{ if .IsStarred }}
-
hx-delete="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
-
{{ else }}
-
hx-post="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
-
{{ end }}
+
<button
+
id="starBtn"
+
class="btn disabled:opacity-50 disabled:cursor-not-allowed flex gap-2 items-center group"
+
{{ if .IsStarred }}
+
hx-delete="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
+
{{ else }}
+
hx-post="/star?subject={{ .RepoAt }}&countHint={{ .Stats.StarCount }}"
+
{{ end }}
-
hx-trigger="click"
-
hx-target="this"
-
hx-swap="outerHTML"
-
hx-disabled-elt="#starBtn">
-
{{ if .IsStarred }}
-
{{ i "star" "w-4 h-4 fill-current" }}
-
{{ else }}
-
{{ i "star" "w-4 h-4" }}
-
{{ end }}
-
<span class="text-sm">
-
{{ .Stats.StarCount }}
-
</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
+
hx-trigger="click"
+
hx-target="this"
+
hx-swap="outerHTML"
+
hx-disabled-elt="#starBtn"
+
>
+
{{ if .IsStarred }}
+
{{ i "star" "w-4 h-4 fill-current" }}
+
{{ else }}
+
{{ i "star" "w-4 h-4" }}
+
{{ end }}
+
<span class="text-sm">
+
{{ .Stats.StarCount }}
+
</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
{{ end }}
+58 -113
appview/pages/templates/repo/fragments/splitDiff.html
···
{{ define "repo/fragments/splitDiff" }}
-
{{ $name := .Id }}
-
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}}
-
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
-
{{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
-
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
-
{{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}}
-
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}}
-
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
-
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
-
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
-
<div class="grid grid-cols-2 divide-x divide-gray-200 dark:divide-gray-700">
-
<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">
-
&middot;&middot;&middot;
-
</div>
-
{{- range .LeftLines -}}
-
{{- if .IsEmpty -}}
-
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
-
<span aria-hidden="true" class="invisible">
-
{{ .LineNumber }}
-
</span>
-
</div>
-
<div class="{{ $opStyle }}">
-
<span aria-hidden="true" class="invisible">{{ .Op.String }}</span>
-
</div>
-
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
-
</div>
-
{{- else if eq .Op.String "-" -}}
-
<div
-
class="{{ $delStyle }} {{ $containerStyle }}"
-
id="{{ $name }}-O{{ .LineNumber }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
-
<a
-
class="{{ $linkStyle }}"
-
href="#{{ $name }}-O{{ .LineNumber }}">
-
{{ .LineNumber }}
-
</a>
-
</div>
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
-
<div class="px-2">{{ .Content }}</div>
-
</div>
-
{{- else if eq .Op.String " " -}}
-
<div
-
class="{{ $ctxStyle }} {{ $containerStyle }}"
-
id="{{ $name }}-O{{ .LineNumber }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
-
<a
-
class="{{ $linkStyle }}"
-
href="#{{ $name }}-O{{ .LineNumber }}">
-
{{ .LineNumber }}
-
</a>
-
</div>
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
-
<div class="px-2">{{ .Content }}</div>
-
</div>
-
{{- end -}}
-
{{- end -}}
-
{{- end -}}
-
</div></div></pre>
+
{{ $name := .Id }}
+
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}}
+
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
+
{{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
+
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
+
{{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}}
+
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}}
+
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
+
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
+
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
+
<div class="grid grid-cols-2 divide-x divide-gray-200 dark:divide-gray-700">
+
<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">&middot;&middot;&middot;</div>
+
{{- range .LeftLines -}}
+
{{- if .IsEmpty -}}
+
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div>
+
<div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div>
+
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
+
</div>
+
{{- else if eq .Op.String "-" -}}
+
<div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}">
+
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div>
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
+
<div class="px-2">{{ .Content }}</div>
+
</div>
+
{{- else if eq .Op.String " " -}}
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}">
+
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div>
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
+
<div class="px-2">{{ .Content }}</div>
+
</div>
+
{{- end -}}
+
{{- end -}}
+
{{- end -}}</div></div></pre>
-
<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">
-
&middot;&middot;&middot;
-
</div>
-
{{- range .RightLines -}}
-
{{- if .IsEmpty -}}
-
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
-
<span aria-hidden="true" class="invisible">
-
{{ .LineNumber }}
-
</span>
-
</div>
-
<div class="{{ $opStyle }}">
-
<span aria-hidden="true" class="invisible">{{ .Op.String }}</span>
-
</div>
-
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
-
</div>
-
{{- else if eq .Op.String "+" -}}
-
<div
-
class="{{ $addStyle }} {{ $containerStyle }}"
-
id="{{ $name }}-N{{ .LineNumber }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
-
<a
-
class="{{ $linkStyle }}"
-
href="#{{ $name }}-N{{ .LineNumber }}">
-
{{ .LineNumber }}
-
</a>
-
</div>
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
-
<div class="px-2">{{ .Content }}</div>
-
</div>
-
{{- else if eq .Op.String " " -}}
-
<div
-
class="{{ $ctxStyle }} {{ $containerStyle }}"
-
id="{{ $name }}-N{{ .LineNumber }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}">
-
<a
-
class="{{ $linkStyle }}"
-
href="#{{ $name }}-N{{ .LineNumber }}">
-
{{ .LineNumber }}
-
</a>
-
</div>
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
-
<div class="px-2">{{ .Content }}</div>
-
</div>
-
{{- end -}}
-
{{- end -}}
-
{{- end -}}</div></div></pre>
-
</div>
+
<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">&middot;&middot;&middot;</div>
+
{{- range .RightLines -}}
+
{{- if .IsEmpty -}}
+
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div>
+
<div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div>
+
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
+
</div>
+
{{- else if eq .Op.String "+" -}}
+
<div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}">
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div>
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
+
<div class="px-2" >{{ .Content }}</div>
+
</div>
+
{{- else if eq .Op.String " " -}}
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}">
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div>
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
+
<div class="px-2">{{ .Content }}</div>
+
</div>
+
{{- end -}}
+
{{- end -}}
+
{{- end -}}</div></div></pre>
+
</div>
{{ end }}
+6 -14
appview/pages/templates/repo/fragments/time.html
···
{{ define "repo/fragments/timeWrapper" }}
-
<time
-
datetime="{{ .Time | iso8601DateTimeFmt }}"
-
title="{{ .Time | longTimeFmt }}">
-
{{ .Content }}
-
</time>
+
<time datetime="{{ .Time | iso8601DateTimeFmt }}" title="{{ .Time | longTimeFmt }}">{{ .Content }}</time>
{{ end }}
{{ define "repo/fragments/time" }}
-
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | relTimeFmt)) }}
+
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | relTimeFmt)) }}
{{ end }}
{{ define "repo/fragments/shortTime" }}
-
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | shortRelTimeFmt)) }}
+
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (. | shortRelTimeFmt)) }}
{{ end }}
{{ define "repo/fragments/shortTimeAgo" }}
-
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (print (. | shortRelTimeFmt) " ago")) }}
+
{{ template "repo/fragments/timeWrapper" (dict "Time" . "Content" (print (. | shortRelTimeFmt) " ago")) }}
{{ end }}
{{ define "repo/fragments/duration" }}
-
<time
-
datetime="{{ . | iso8601DurationFmt }}"
-
title="{{ . | longDurationFmt }}">
-
{{ . | durationFmt }}
-
</time>
-
{{ end }}
+
<time datetime="{{ . | iso8601DurationFmt }}" title="{{ . | longDurationFmt }}">{{ . | durationFmt }}</time>
+
{{ end }}
+45 -79
appview/pages/templates/repo/fragments/unifiedDiff.html
···
{{ define "repo/fragments/unifiedDiff" }}
-
{{ $name := .Id }}
-
<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">
-
&middot;&middot;&middot;
-
</div>
-
{{- $oldStart := .OldPosition -}}
-
{{- $newStart := .NewPosition -}}
-
{{- $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" -}}
-
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
-
{{- $lineNrSepStyle1 := "" -}}
-
{{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
-
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
-
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}}
-
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
-
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
-
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
-
{{- range .Lines -}}
-
{{- if eq .Op.String "+" -}}
-
<div
-
class="{{ $addStyle }} {{ $containerStyle }}"
-
id="{{ $name }}-N{{ $newStart }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle1 }}">
-
<span aria-hidden="true" class="invisible">{{ $newStart }}</span>
-
</div>
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle2 }}">
-
<a class="{{ $linkStyle }}" href="#{{ $name }}-N{{ $newStart }}">
-
{{ $newStart }}
-
</a>
-
</div>
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
-
<div class="px-2">{{ .Line }}</div>
-
</div>
-
{{- $newStart = add64 $newStart 1 -}}
-
{{- end -}}
-
{{- if eq .Op.String "-" -}}
-
<div
-
class="{{ $delStyle }} {{ $containerStyle }}"
-
id="{{ $name }}-O{{ $oldStart }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle1 }}">
-
<a class="{{ $linkStyle }}" href="#{{ $name }}-O{{ $oldStart }}">
-
{{ $oldStart }}
-
</a>
-
</div>
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle2 }}">
-
<span aria-hidden="true" class="invisible">{{ $oldStart }}</span>
-
</div>
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
-
<div class="px-2">{{ .Line }}</div>
-
</div>
-
{{- $oldStart = add64 $oldStart 1 -}}
-
{{- end -}}
-
{{- if eq .Op.String " " -}}
-
<div
-
class="{{ $ctxStyle }} {{ $containerStyle }}"
-
id="{{ $name }}-O{{ $oldStart }}-N{{ $newStart }}">
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle1 }}">
-
<a
-
class="{{ $linkStyle }}"
-
href="#{{ $name }}-O{{ $oldStart }}-N{{ $newStart }}">
-
{{ $oldStart }}
-
</a>
-
</div>
-
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle2 }}">
-
<a
-
class="{{ $linkStyle }}"
-
href="#{{ $name }}-O{{ $oldStart }}-N{{ $newStart }}">
-
{{ $newStart }}
-
</a>
-
</div>
-
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
-
<div class="px-2">{{ .Line }}</div>
-
</div>
-
{{- $newStart = add64 $newStart 1 -}}
-
{{- $oldStart = add64 $oldStart 1 -}}
-
{{- end -}}
-
{{- end -}}
-
{{- end -}}</div></div></pre>
+
{{ $name := .Id }}
+
<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">&middot;&middot;&middot;</div>
+
{{- $oldStart := .OldPosition -}}
+
{{- $newStart := .NewPosition -}}
+
{{- $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" -}}
+
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
+
{{- $lineNrSepStyle1 := "" -}}
+
{{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
+
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
+
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}}
+
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
+
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
+
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
+
{{- range .Lines -}}
+
{{- if eq .Op.String "+" -}}
+
<div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{$newStart}}">
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div>
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div>
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
+
<div class="px-2">{{ .Line }}</div>
+
</div>
+
{{- $newStart = add64 $newStart 1 -}}
+
{{- end -}}
+
{{- if eq .Op.String "-" -}}
+
<div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}">
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div>
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div>
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
+
<div class="px-2">{{ .Line }}</div>
+
</div>
+
{{- $oldStart = add64 $oldStart 1 -}}
+
{{- end -}}
+
{{- if eq .Op.String " " -}}
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}-N{{$newStart}}">
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $oldStart }}</a></div>
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $newStart }}</a></div>
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
+
<div class="px-2">{{ .Line }}</div>
+
</div>
+
{{- $newStart = add64 $newStart 1 -}}
+
{{- $oldStart = add64 $oldStart 1 -}}
+
{{- end -}}
+
{{- end -}}
+
{{- end -}}</div></div></pre>
{{ end }}
+
+254 -308
appview/pages/templates/repo/index.html
···
{{ define "title" }}{{ .RepoInfo.FullName }} at {{ .Ref }}{{ end }}
+
{{ define "extrameta" }}
-
{{ template "repo/fragments/meta" . }}
+
{{ template "repo/fragments/meta" . }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
{{ end }}
{{ define "repoContent" }}
-
<main>
-
{{ if .Languages }}
-
{{ block "repoLanguages" . }}{{ end }}
-
{{ end }}
-
<div class="flex items-center justify-between pb-5">
-
{{ block "branchSelector" . }}{{ end }}
-
<div class="flex md:hidden items-center gap-4">
-
<a
-
href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}"
-
class="inline-flex items-center text-sm gap-1">
-
{{ i "git-commit-horizontal" "w-4" "h-4" }}
-
{{ .TotalCommits }}
-
</a>
-
<a
-
href="/{{ .RepoInfo.FullName }}/branches"
-
class="inline-flex items-center text-sm gap-1">
-
{{ i "git-branch" "w-4" "h-4" }}
-
{{ len .Branches }}
-
</a>
-
<a
-
href="/{{ .RepoInfo.FullName }}/tags"
-
class="inline-flex items-center text-sm gap-1">
-
{{ i "tags" "w-4" "h-4" }}
-
{{ len .Tags }}
-
</a>
-
</div>
-
</div>
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
-
{{ block "fileTree" . }}{{ end }}
-
{{ block "rightInfo" . }}{{ end }}
-
</div>
-
</main>
+
<main>
+
{{ if .Languages }}
+
{{ block "repoLanguages" . }}{{ end }}
+
{{ end }}
+
<div class="flex items-center justify-between pb-5">
+
{{ block "branchSelector" . }}{{ end }}
+
<div class="flex md:hidden items-center gap-4">
+
<a href="/{{ .RepoInfo.FullName }}/commits/{{ .Ref | urlquery }}" class="inline-flex items-center text-sm gap-1">
+
{{ i "git-commit-horizontal" "w-4" "h-4" }} {{ .TotalCommits }}
+
</a>
+
<a href="/{{ .RepoInfo.FullName }}/branches" class="inline-flex items-center text-sm gap-1">
+
{{ i "git-branch" "w-4" "h-4" }} {{ len .Branches }}
+
</a>
+
<a href="/{{ .RepoInfo.FullName }}/tags" class="inline-flex items-center text-sm gap-1">
+
{{ i "tags" "w-4" "h-4" }} {{ len .Tags }}
+
</a>
+
</div>
+
</div>
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
+
{{ block "fileTree" . }}{{ end }}
+
{{ block "rightInfo" . }}{{ end }}
+
</div>
+
</main>
{{ end }}
{{ define "repoLanguages" }}
-
<div class="flex gap-[1px] -m-6 mb-6 overflow-hidden rounded-t">
-
{{ range $value := .Languages }}
-
<div
-
title="{{ or $value.Name "Other" }} {{ printf "%.1f" $value.Percentage }}%"
-
class="h-[4px] rounded-full"
-
style="background-color: {{ $value.Color }}; width: {{ $value.Percentage }}%"></div>
-
{{ end }}
-
</div>
+
<div class="flex gap-[1px] -m-6 mb-6 overflow-hidden rounded-t">
+
{{ range $value := .Languages }}
+
<div
+
title='{{ or $value.Name "Other" }} {{ printf "%.1f" $value.Percentage }}%'
+
class="h-[4px] rounded-full"
+
style="background-color: {{ $value.Color }}; width: {{ $value.Percentage }}%"
+
></div>
+
{{ end }}
+
</div>
{{ end }}
+
{{ define "branchSelector" }}
<div class="flex gap-2 items-center items-stretch justify-center">
<select
-
onchange="window.location.href = '/{{ .RepoInfo.FullName }}/tree/' + encodeURIComponent(this.value)"
-
class="p-1 border max-w-32 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
-
<optgroup label="branches ({{ len .Branches }})" class="bold text-sm">
-
{{ range .Branches }}
-
<option
-
value="{{ .Reference.Name }}"
-
class="py-1"
-
{{ if eq .Reference.Name $.Ref }}
-
selected
-
{{ end }}>
-
{{ .Reference.Name }}
-
</option>
-
{{ end }}
-
</optgroup>
-
<optgroup label="tags ({{ len .Tags }})" class="bold text-sm">
-
{{ range .Tags }}
-
<option
-
value="{{ .Reference.Name }}"
-
class="py-1"
-
{{ if eq .Reference.Name $.Ref }}
-
selected
-
{{ end }}>
-
{{ .Reference.Name }}
-
</option>
-
{{ else }}
-
<option class="py-1" disabled>no tags found</option>
-
{{ end }}
-
</optgroup>
+
onchange="window.location.href = '/{{ .RepoInfo.FullName }}/tree/' + encodeURIComponent(this.value)"
+
class="p-1 border max-w-32 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"
+
>
+
<optgroup label="branches ({{len .Branches}})" class="bold text-sm">
+
{{ range .Branches }}
+
<option
+
value="{{ .Reference.Name }}"
+
class="py-1"
+
{{ if eq .Reference.Name $.Ref }}
+
selected
+
{{ end }}
+
>
+
{{ .Reference.Name }}
+
</option>
+
{{ end }}
+
</optgroup>
+
<optgroup label="tags ({{len .Tags}})" class="bold text-sm">
+
{{ range .Tags }}
+
<option
+
value="{{ .Reference.Name }}"
+
class="py-1"
+
{{ if eq .Reference.Name $.Ref }}
+
selected
+
{{ end }}
+
>
+
{{ .Reference.Name }}
+
</option>
+
{{ else }}
+
<option class="py-1" disabled>no tags found</option>
+
{{ end }}
+
</optgroup>
</select>
<div class="flex items-center gap-2">
-
{{ $isOwner := and .LoggedInUser .RepoInfo.Roles.IsOwner }}
-
{{ $isCollaborator := and .LoggedInUser .RepoInfo.Roles.IsCollaborator }}
-
{{ if and (or $isOwner $isCollaborator) .ForkInfo .ForkInfo.IsFork }}
+
{{ $isOwner := and .LoggedInUser .RepoInfo.Roles.IsOwner }}
+
{{ $isCollaborator := and .LoggedInUser .RepoInfo.Roles.IsCollaborator }}
+
{{ if and (or $isOwner $isCollaborator) .ForkInfo .ForkInfo.IsFork }}
{{ $disabled := "" }}
{{ $title := "" }}
{{ if eq .ForkInfo.Status 0 }}
-
{{ $disabled = "disabled" }}
-
{{ $title = "This branch is not behind the upstream" }}
+
{{ $disabled = "disabled" }}
+
{{ $title = "This branch is not behind the upstream" }}
{{ else if eq .ForkInfo.Status 2 }}
-
{{ $disabled = "disabled" }}
-
{{ $title = "This branch has conflicts that must be resolved" }}
+
{{ $disabled = "disabled" }}
+
{{ $title = "This branch has conflicts that must be resolved" }}
{{ else if eq .ForkInfo.Status 3 }}
-
{{ $disabled = "disabled" }}
-
{{ $title = "This branch does not exist on the upstream" }}
+
{{ $disabled = "disabled" }}
+
{{ $title = "This branch does not exist on the upstream" }}
{{ end }}
-
<button
-
id="syncBtn"
-
{{ $disabled }}
-
{{ if $title }}title="{{ $title }}"{{ end }}
-
class="btn flex gap-2 items-center disabled:opacity-50 disabled:cursor-not-allowed"
-
hx-post="/{{ .RepoInfo.FullName }}/fork/sync"
-
hx-trigger="click"
-
hx-swap="none">
+
id="syncBtn"
+
{{ $disabled }}
+
{{ if $title }}title="{{ $title }}"{{ end }}
+
class="btn flex gap-2 items-center disabled:opacity-50 disabled:cursor-not-allowed"
+
hx-post="/{{ .RepoInfo.FullName }}/fork/sync"
+
hx-trigger="click"
+
hx-swap="none"
+
>
{{ if $disabled }}
-
{{ i "refresh-cw-off" "w-4 h-4" }}
+
{{ i "refresh-cw-off" "w-4 h-4" }}
{{ else }}
-
{{ i "refresh-cw" "w-4 h-4" }}
+
{{ i "refresh-cw" "w-4 h-4" }}
{{ end }}
<span>sync</span>
</button>
-
{{ end }}
-
<a
-
href="/{{ .RepoInfo.FullName }}/compare?base={{ $.Ref | urlquery }}"
-
class="btn flex items-center gap-2 no-underline hover:no-underline"
-
title="Compare branches or tags">
-
{{ i "git-compare" "w-4 h-4" }}
-
</a>
+
{{ end }}
+
<a
+
href="/{{ .RepoInfo.FullName }}/compare?base={{ $.Ref | urlquery }}"
+
class="btn flex items-center gap-2 no-underline hover:no-underline"
+
title="Compare branches or tags"
+
>
+
{{ i "git-compare" "w-4 h-4" }}
+
</a>
</div>
-
</div>
+
</div>
{{ end }}
{{ define "fileTree" }}
-
<div
-
id="file-tree"
-
class="col-span-1 pr-2 md:border-r md:border-gray-200 dark:md:border-gray-700">
+
<div id="file-tree" class="col-span-1 pr-2 md:border-r md:border-gray-200 dark:md:border-gray-700" >
{{ $linkstyle := "no-underline hover:underline dark:text-white" }}
{{ range .Files }}
···
<div class="text-xs col-span-1 text-right">
{{ with .LastCommit }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}"
-
class="text-gray-500 dark:text-gray-400">
-
{{ template "repo/fragments/time" .When }}
-
</a>
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .When }}</a>
{{ end }}
</div>
</div>
···
{{ end }}
{{ define "rightInfo" }}
-
<div id="right-info" class="hidden md:block col-span-1">
-
{{ block "commitLog" . }}{{ end }}
-
{{ block "branchList" . }}{{ end }}
-
{{ block "tagList" . }}{{ end }}
-
</div>
+
<div id="right-info" class="hidden md:block col-span-1">
+
{{ block "commitLog" . }} {{ end }}
+
{{ block "branchList" . }} {{ end }}
+
{{ block "tagList" . }} {{ end }}
+
</div>
{{ end }}
{{ define "commitLog" }}
-
<div id="commit-log" class="md:col-span-1 px-2 pb-4">
-
<div class="flex justify-between items-center">
-
<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">
-
{{ i "logs" "w-4 h-4" }} commits
-
<span
-
class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
-
{{ .TotalCommits }}
-
</span>
-
</a>
-
</div>
-
<div class="flex flex-col gap-6">
-
{{ range .CommitsTrunc }}
-
<div>
-
<div id="commit-message">
-
{{ $messageParts := splitN .Message "\n\n" 2 }}
-
<div class="text-base cursor-pointer">
-
<div>
-
<div>
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
-
class="inline no-underline hover:underline dark:text-white">
-
{{ index $messageParts 0 }}
-
</a>
-
{{ if gt (len $messageParts) 1 }}
+
<div id="commit-log" class="md:col-span-1 px-2 pb-4">
+
<div class="flex justify-between items-center">
+
<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">
+
{{ i "logs" "w-4 h-4" }} commits
+
<span class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ .TotalCommits }}</span>
+
</a>
+
</div>
+
<div class="flex flex-col gap-6">
+
{{ range .CommitsTrunc }}
+
<div>
+
<div id="commit-message">
+
{{ $messageParts := splitN .Message "\n\n" 2 }}
+
<div class="text-base cursor-pointer">
+
<div>
+
<div>
+
<a
+
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
+
class="inline no-underline hover:underline dark:text-white"
+
>{{ index $messageParts 0 }}</a
+
>
+
{{ if gt (len $messageParts) 1 }}
-
<button
-
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
-
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
-
{{ i "ellipsis" "w-3 h-3" }}
-
</button>
-
{{ end }}
-
</div>
-
{{ if gt (len $messageParts) 1 }}
-
<p
-
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
-
{{ nl2br (index $messageParts 1) }}
-
</p>
+
<button
+
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
+
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')"
+
>
+
{{ i "ellipsis" "w-3 h-3" }}
+
</button>
{{ end }}
-
</div>
</div>
+
{{ if gt (len $messageParts) 1 }}
+
<p
+
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300"
+
>
+
{{ nl2br (index $messageParts 1) }}
+
</p>
+
{{ end }}
</div>
+
</div>
+
</div>
-
<!-- commit info bar -->
-
<div
-
class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center flex-wrap">
-
{{ $verified := $.VerifiedCommits.IsVerified .Hash.String }}
-
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
-
{{ if $verified }}
+
<!-- commit info bar -->
+
<div class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center flex-wrap">
+
{{ $verified := $.VerifiedCommits.IsVerified .Hash.String }}
+
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
+
{{ if $verified }}
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
-
{{ end }}
-
<span class="font-mono">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
-
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
-
{{ slice .Hash.String 0 8 }}
-
{{ if $verified }}
-
{{ i "shield-check" "w-3 h-3" }}
-
{{ end }}
+
{{ end }}
+
<span class="font-mono">
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash.String }}"
+
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
+
{{ slice .Hash.String 0 8 }}
+
{{ if $verified }}
+
{{ i "shield-check" "w-3 h-3" }}
+
{{ end }}
</a>
-
</span>
-
<span class="mx-1 before:content-['·'] before:select-none"></span>
-
<span>
-
{{ $didOrHandle := index $.EmailToDidOrHandle .Author.Email }}
-
<a
-
href="{{ if $didOrHandle }}
-
/{{ $didOrHandle }}
-
{{ else }}
-
mailto:{{ .Author.Email }}
-
{{ end }}"
-
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
-
{{ if $didOrHandle }}
-
{{ template "user/fragments/picHandleLink" $didOrHandle }}
-
{{ else }}
-
{{ .Author.Name }}
-
{{ end }}
-
</a>
-
</span>
-
<div
-
class="inline-block px-1 select-none after:content-['·']"></div>
-
{{ template "repo/fragments/time" .Committer.When }}
+
</span>
+
<span
+
class="mx-1 before:content-['·'] before:select-none"
+
></span>
+
<span>
+
{{ $didOrHandle := index $.EmailToDidOrHandle .Author.Email }}
+
<a
+
href="{{ if $didOrHandle }}
+
/{{ $didOrHandle }}
+
{{ else }}
+
mailto:{{ .Author.Email }}
+
{{ end }}"
+
class="text-gray-500 dark:text-gray-400 no-underline hover:underline"
+
>{{ if $didOrHandle }}
+
{{ template "user/fragments/picHandleLink" $didOrHandle }}
+
{{ else }}
+
{{ .Author.Name }}
+
{{ end }}</a
+
>
+
</span>
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
+
{{ template "repo/fragments/time" .Committer.When }}
+
<!-- tags/branches -->
+
{{ $tagsForCommit := index $.TagMap .Hash.String }}
+
{{ if gt (len $tagsForCommit) 0 }}
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
+
{{ end }}
+
{{ range $tagsForCommit }}
+
<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">
+
{{ . }}
+
</span>
+
{{ end }}
-
<!-- tags/branches -->
-
{{ $tagsForCommit := index $.TagMap .Hash.String }}
-
{{ if gt (len $tagsForCommit) 0 }}
-
<div
-
class="inline-block px-1 select-none after:content-['·']"></div>
-
{{ end }}
-
{{ range $tagsForCommit }}
-
<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">
-
{{ . }}
-
</span>
-
{{ end }}
-
-
-
<!-- ci status -->
-
{{ $pipeline := index $.Pipelines .Hash.String }}
-
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
-
<div
-
class="inline-block px-1 select-none after:content-['·']"></div>
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "RepoInfo" $.RepoInfo "Pipeline" $pipeline) }}
-
{{ end }}
-
</div>
-
</div>
-
{{ end }}
+
<!-- ci status -->
+
{{ $pipeline := index $.Pipelines .Hash.String }}
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "RepoInfo" $.RepoInfo "Pipeline" $pipeline) }}
+
{{ end }}
+
</div>
</div>
+
{{ end }}
</div>
+
</div>
{{ end }}
{{ define "branchList" }}
{{ if gt (len .BranchesTrunc) 0 }}
-
<div
-
id="branches"
-
class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
-
<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">
+
<div id="branches" class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
+
<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">
{{ i "git-branch" "w-4 h-4" }} branches
-
<span
-
class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
-
{{ len .Branches }}
-
</span>
+
<span class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ len .Branches }}</span>
</a>
<div class="flex flex-col gap-1">
{{ range .BranchesTrunc }}
-
<div
-
class="text-base flex items-center justify-between overflow-hidden">
-
<div class="flex items-center gap-2 min-w-0 flex-1">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
-
class="inline-block truncate no-underline hover:underline dark:text-white">
-
{{ .Reference.Name }}
-
</a>
-
{{ if .Commit }}
-
<span
-
class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
-
<span
-
class="whitespace-nowrap text-xs text-gray-500 dark:text-gray-400 shrink-0">
-
{{ template "repo/fragments/time" .Commit.Committer.When }}
-
</span>
-
{{ end }}
-
{{ if .IsDefault }}
-
<span
-
class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
-
<span
-
class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono shrink-0">
-
default
-
</span>
-
{{ end }}
-
</div>
-
{{ if ne $.Ref .Reference.Name }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/compare/{{ $.Ref | urlquery }}...{{ .Reference.Name | urlquery }}"
-
class="text-xs flex gap-2 items-center shrink-0 ml-2"
-
title="Compare branches or tags">
-
{{ i "git-compare" "w-3 h-3" }} compare
-
</a>
+
<div class="text-base flex items-center justify-between overflow-hidden">
+
<div class="flex items-center gap-2 min-w-0 flex-1">
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
+
class="inline-block truncate no-underline hover:underline dark:text-white">
+
{{ .Reference.Name }}
+
</a>
+
{{ if .Commit }}
+
<span class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
+
<span class="whitespace-nowrap text-xs text-gray-500 dark:text-gray-400 shrink-0">{{ template "repo/fragments/time" .Commit.Committer.When }}</span>
+
{{ end }}
+
{{ if .IsDefault }}
+
<span class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·'] shrink-0"></span>
+
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono shrink-0">default</span>
{{ end }}
</div>
+
{{ if ne $.Ref .Reference.Name }}
+
<a href="/{{ $.RepoInfo.FullName }}/compare/{{ $.Ref | urlquery }}...{{ .Reference.Name | urlquery }}"
+
class="text-xs flex gap-2 items-center shrink-0 ml-2"
+
title="Compare branches or tags">
+
{{ i "git-compare" "w-3 h-3" }} compare
+
</a>
+
{{ end }}
+
</div>
{{ end }}
</div>
</div>
···
{{ define "tagList" }}
{{ if gt (len .TagsTrunc) 0 }}
-
<div
-
id="tags"
-
class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
+
<div id="tags" class="md:col-span-1 px-2 py-4 border-t border-gray-200 dark:border-gray-700">
<div class="flex justify-between items-center">
-
<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">
+
<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">
{{ i "tags" "w-4 h-4" }} tags
-
<span
-
class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
-
{{ len .Tags }}
-
</span>
+
<span class="bg-gray-100 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ len .Tags }}</span>
</a>
</div>
<div class="flex flex-col gap-1">
{{ range $idx, $tag := .TagsTrunc }}
-
{{ with $tag }}
-
<div>
-
<div class="text-base flex items-center gap-2">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
-
class="inline no-underline hover:underline dark:text-white">
-
{{ .Reference.Name }}
-
</a>
-
</div>
-
<div>
-
{{ with .Tag }}
-
<span class="text-xs text-gray-500 dark:text-gray-400">
-
{{ template "repo/fragments/time" .Tagger.When }}
-
</span>
-
{{ end }}
-
{{ if eq $idx 0 }}
-
{{ with .Tag }}
-
<span
-
class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·']"></span>
-
{{ end }}
-
<span
-
class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono">
-
latest
-
</span>
-
{{ end }}
-
</div>
-
</div>
-
{{ end }}
+
{{ with $tag }}
+
<div>
+
<div class="text-base flex items-center gap-2">
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ .Reference.Name | urlquery }}"
+
class="inline no-underline hover:underline dark:text-white">
+
{{ .Reference.Name }}
+
</a>
+
</div>
+
<div>
+
{{ with .Tag }}
+
<span class="text-xs text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .Tagger.When }}</span>
+
{{ end }}
+
{{ if eq $idx 0 }}
+
{{ with .Tag }}<span class="px-1 text-gray-500 dark:text-gray-400 select-none after:content-['·']"></span>{{ end }}
+
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-xs font-mono">latest</span>
+
{{ end }}
+
</div>
+
</div>
+
{{ end }}
{{ end }}
</div>
</div>
···
{{ end }}
{{ define "repoAfter" }}
-
{{- if or .HTMLReadme .Readme -}}
-
<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 overflow-auto {{ if not .Raw }}
-
prose dark:prose-invert dark:[&_pre]:bg-gray-900
-
dark:[&_code]:text-gray-300 dark:[&_pre_code]:bg-gray-900
-
dark:[&_pre]:border dark:[&_pre]:border-gray-700
-
{{ end }}">
-
<article class="{{ if .Raw }}whitespace-pre{{ end }}">
-
{{- if .Raw -}}
-
<pre class="dark:bg-gray-800 dark:text-white overflow-x-auto">
+
{{- if or .HTMLReadme .Readme -}}
+
<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 overflow-auto {{ if not .Raw }}
+
prose dark:prose-invert dark:[&_pre]:bg-gray-900
+
dark:[&_code]:text-gray-300 dark:[&_pre_code]:bg-gray-900
+
dark:[&_pre]:border dark:[&_pre]:border-gray-700
+
{{ end }}"
+
>
+
<article class="{{ if .Raw }}whitespace-pre{{ end }}">{{- if .Raw -}}<pre class="dark:bg-gray-800 dark:text-white overflow-x-auto">
{{- .Readme -}}
-
</pre
-
>
-
{{- else -}}
-
{{ .HTMLReadme }}
-
{{- end -}}
-
</article>
-
</section>
-
{{- end -}}
+
</pre>
+
{{- else -}}
+
{{ .HTMLReadme }}
+
{{- end -}}</article>
+
</section>
+
{{- end -}}
-
{{ template "repo/fragments/cloneInstructions" . }}
+
{{ template "repo/fragments/cloneInstructions" . }}
{{ end }}
+39 -44
appview/pages/templates/repo/issues/fragments/editIssueComment.html
···
{{ define "repo/issues/fragments/editIssueComment" }}
{{ with .Comment }}
-
<div id="comment-container-{{ .CommentId }}">
-
<div
-
class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
-
{{ $owner := didOrHandle $.LoggedInUser.Did $.LoggedInUser.Handle }}
-
<a href="/{{ $owner }}" class="no-underline hover:underline">
-
{{ $owner }}
-
</a>
+
<div id="comment-container-{{.CommentId}}">
+
<div class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
+
{{ $owner := didOrHandle $.LoggedInUser.Did $.LoggedInUser.Handle }}
+
<a href="/{{ $owner }}" class="no-underline hover:underline">{{ $owner }}</a>
-
<!-- show user "hats" -->
-
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
-
{{ if $isIssueAuthor }}
-
<span class="before:content-['·']"></span>
-
author
-
{{ end }}
-
+
<!-- show user "hats" -->
+
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
+
{{ if $isIssueAuthor }}
+
<span class="before:content-['·']"></span>
+
author
+
{{ end }}
-
<span class="before:content-['·']"></span>
-
<a
+
<span class="before:content-['·']"></span>
+
<a
href="#{{ .CommentId }}"
class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-400 hover:underline no-underline"
id="{{ .CommentId }}">
-
{{ template "repo/fragments/time" .Created }}
-
</a>
+
{{ template "repo/fragments/time" .Created }}
+
</a>
-
<button
-
class="btn px-2 py-1 flex items-center gap-2 text-sm group"
-
hx-post="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
-
hx-include="#edit-textarea-{{ .CommentId }}"
-
hx-target="#comment-container-{{ .CommentId }}"
-
hx-swap="outerHTML">
-
{{ i "check" "w-4 h-4" }}
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
-
<button
-
class="btn px-2 py-1 flex items-center gap-2 text-sm"
-
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
-
hx-target="#comment-container-{{ .CommentId }}"
-
hx-swap="outerHTML">
-
{{ i "x" "w-4 h-4" }}
-
</button>
-
<span id="comment-{{ .CommentId }}-status"></span>
-
</div>
+
<button
+
class="btn px-2 py-1 flex items-center gap-2 text-sm group"
+
hx-post="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
+
hx-include="#edit-textarea-{{ .CommentId }}"
+
hx-target="#comment-container-{{ .CommentId }}"
+
hx-swap="outerHTML">
+
{{ i "check" "w-4 h-4" }}
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
+
<button
+
class="btn px-2 py-1 flex items-center gap-2 text-sm"
+
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
+
hx-target="#comment-container-{{ .CommentId }}"
+
hx-swap="outerHTML">
+
{{ i "x" "w-4 h-4" }}
+
</button>
+
<span id="comment-{{.CommentId}}-status"></span>
+
</div>
-
<div>
-
<textarea
-
id="edit-textarea-{{ .CommentId }}"
-
name="body"
-
class="w-full p-2 border rounded min-h-[100px]">
-
{{ .Body }}</textarea
-
>
-
</div>
+
<div>
+
<textarea
+
id="edit-textarea-{{ .CommentId }}"
+
name="body"
+
class="w-full p-2 border rounded min-h-[100px]">{{ .Body }}</textarea>
</div>
+
</div>
{{ end }}
{{ end }}
+
+45 -48
appview/pages/templates/repo/issues/fragments/issueComment.html
···
{{ define "repo/issues/fragments/issueComment" }}
{{ with .Comment }}
-
<div id="comment-container-{{ .CommentId }}">
-
<div
-
class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
-
{{ template "user/fragments/picHandleLink" .OwnerDid }}
-
-
-
<!-- show user "hats" -->
-
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
-
{{ if $isIssueAuthor }}
-
<span class="before:content-['·']"></span>
-
author
-
{{ end }}
-
+
<div id="comment-container-{{.CommentId}}">
+
<div class="flex items-center gap-2 mb-2 text-gray-500 dark:text-gray-400 text-sm flex-wrap">
+
{{ template "user/fragments/picHandleLink" .OwnerDid }}
+
<!-- show user "hats" -->
+
{{ $isIssueAuthor := eq .OwnerDid $.Issue.OwnerDid }}
+
{{ if $isIssueAuthor }}
<span class="before:content-['·']"></span>
-
<a
+
author
+
{{ end }}
+
+
<span class="before:content-['·']"></span>
+
<a
href="#{{ .CommentId }}"
class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-400 hover:underline no-underline"
id="{{ .CommentId }}">
-
{{ if .Deleted }}
-
deleted
-
{{ template "repo/fragments/time" .Deleted }}
-
{{ else if .Edited }}
-
edited
-
{{ template "repo/fragments/time" .Edited }}
-
{{ else }}
-
{{ template "repo/fragments/time" .Created }}
-
{{ end }}
-
</a>
-
-
{{ $isCommentOwner := and $.LoggedInUser (eq $.LoggedInUser.Did .OwnerDid) }}
-
{{ if and $isCommentOwner (not .Deleted) }}
-
<button
-
class="btn px-2 py-1 text-sm"
-
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
-
hx-swap="outerHTML"
-
hx-target="#comment-container-{{ .CommentId }}">
-
{{ i "pencil" "w-4 h-4" }}
-
</button>
-
<button
-
class="btn px-2 py-1 text-sm text-red-500 flex gap-2 items-center group"
-
hx-delete="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
-
hx-confirm="Are you sure you want to delete your comment?"
-
hx-swap="outerHTML"
-
hx-target="#comment-container-{{ .CommentId }}">
-
{{ i "trash-2" "w-4 h-4" }}
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
+
{{ if .Deleted }}
+
deleted {{ template "repo/fragments/time" .Deleted }}
+
{{ else if .Edited }}
+
edited {{ template "repo/fragments/time" .Edited }}
+
{{ else }}
+
{{ template "repo/fragments/time" .Created }}
{{ end }}
+
</a>
-
</div>
-
{{ if not .Deleted }}
-
<div class="prose dark:prose-invert">
-
{{ .Body | markdown }}
-
</div>
+
{{ $isCommentOwner := and $.LoggedInUser (eq $.LoggedInUser.Did .OwnerDid) }}
+
{{ if and $isCommentOwner (not .Deleted) }}
+
<button
+
class="btn px-2 py-1 text-sm"
+
hx-get="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/edit"
+
hx-swap="outerHTML"
+
hx-target="#comment-container-{{.CommentId}}"
+
>
+
{{ i "pencil" "w-4 h-4" }}
+
</button>
+
<button
+
class="btn px-2 py-1 text-sm text-red-500 flex gap-2 items-center group"
+
hx-delete="/{{ $.RepoInfo.FullName }}/issues/{{ .Issue }}/comment/{{ .CommentId }}/"
+
hx-confirm="Are you sure you want to delete your comment?"
+
hx-swap="outerHTML"
+
hx-target="#comment-container-{{.CommentId}}"
+
>
+
{{ i "trash-2" "w-4 h-4" }}
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
{{ end }}
+
</div>
+
{{ if not .Deleted }}
+
<div class="prose dark:prose-invert">
+
{{ .Body | markdown }}
+
</div>
+
{{ end }}
+
</div>
{{ end }}
{{ end }}
+119 -123
appview/pages/templates/repo/issues/issue.html
···
-
{{ define "title" }}
-
{{ .Issue.Title }} &middot; issue #{{ .Issue.IssueId }} &middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title" }}{{ .Issue.Title }} &middot; issue #{{ .Issue.IssueId }} &middot; {{ .RepoInfo.FullName }}{{ end }}
+
{{ define "extrameta" }}
-
{{ $title := printf "%s &middot; issue #%d &middot; %s" .Issue.Title .Issue.IssueId .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/issues/%d" .RepoInfo.FullName .Issue.IssueId }}
+
{{ $title := printf "%s &middot; issue #%d &middot; %s" .Issue.Title .Issue.IssueId .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/issues/%d" .RepoInfo.FullName .Issue.IssueId }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
<header class="pb-4">
-
<h1 class="text-2xl">
+
<header class="pb-4">
+
<h1 class="text-2xl">
{{ .Issue.Title }}
-
<span class="text-gray-500 dark:text-gray-400">
-
#{{ .Issue.IssueId }}
-
</span>
-
</h1>
-
</header>
+
<span class="text-gray-500 dark:text-gray-400">#{{ .Issue.IssueId }}</span>
+
</h1>
+
</header>
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
-
{{ $icon := "ban" }}
-
{{ if eq .State "open" }}
-
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
-
{{ $icon = "circle-dot" }}
-
{{ end }}
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
+
{{ $icon := "ban" }}
+
{{ if eq .State "open" }}
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
+
{{ $icon = "circle-dot" }}
+
{{ end }}
+
<section class="mt-2">
+
<div class="inline-flex items-center gap-2">
+
<div id="state"
+
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
+
<span class="text-white">{{ .State }}</span>
+
</div>
+
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
+
opened by
+
{{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }}
+
{{ template "user/fragments/picHandleLink" $owner }}
+
<span class="select-none before:content-['\00B7']"></span>
+
{{ template "repo/fragments/time" .Issue.Created }}
+
</span>
+
</div>
-
<section class="mt-2">
-
<div class="inline-flex items-center gap-2">
-
<div
-
id="state"
-
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
-
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
-
<span class="text-white">{{ .State }}</span>
-
</div>
-
<span
-
class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
-
opened by
-
{{ $owner := didOrHandle .Issue.OwnerDid .IssueOwnerHandle }}
-
{{ template "user/fragments/picHandleLink" $owner }}
-
<span class="select-none before:content-['\00B7']"></span>
-
{{ template "repo/fragments/time" .Issue.Created }}
-
</span>
-
</div>
+
{{ if .Issue.Body }}
+
<article id="body" class="mt-8 prose dark:prose-invert">
+
{{ .Issue.Body | markdown }}
+
</article>
+
{{ end }}
-
{{ if .Issue.Body }}
-
<article id="body" class="mt-8 prose dark:prose-invert">
-
{{ .Issue.Body | markdown }}
-
</article>
-
{{ end }}
-
-
-
<div class="flex items-center gap-2 mt-2">
-
{{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }}
-
{{ range $kind := .OrderedReactionKinds }}
-
{{ template "repo/fragments/reaction"
-
(dict
-
"Kind" $kind
-
"Count" (index $.Reactions $kind)
-
"IsReacted" (index $.UserReacted $kind)
-
"ThreadAt" $.Issue.IssueAt)
-
}}
-
{{ end }}
-
</div>
-
</section>
+
<div class="flex items-center gap-2 mt-2">
+
{{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }}
+
{{ range $kind := .OrderedReactionKinds }}
+
{{
+
template "repo/fragments/reaction"
+
(dict
+
"Kind" $kind
+
"Count" (index $.Reactions $kind)
+
"IsReacted" (index $.UserReacted $kind)
+
"ThreadAt" $.Issue.IssueAt)
+
}}
+
{{ end }}
+
</div>
+
</section>
{{ end }}
{{ define "repoAfter" }}
-
<section id="comments" class="my-2 mt-2 space-y-2 relative">
-
{{ range $index, $comment := .Comments }}
-
<div
-
id="comment-{{ .CommentId }}"
-
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">
-
{{ if gt $index 0 }}
-
<div
-
class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
+
<section id="comments" class="my-2 mt-2 space-y-2 relative">
+
{{ range $index, $comment := .Comments }}
+
<div
+
id="comment-{{ .CommentId }}"
+
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">
+
{{ if gt $index 0 }}
+
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
+
{{ end }}
+
{{ template "repo/issues/fragments/issueComment" (dict "RepoInfo" $.RepoInfo "LoggedInUser" $.LoggedInUser "Issue" $.Issue "Comment" .)}}
+
</div>
{{ end }}
-
{{ template "repo/issues/fragments/issueComment" (dict "RepoInfo" $.RepoInfo "LoggedInUser" $.LoggedInUser "Issue" $.Issue "Comment" .) }}
-
</div>
-
{{ end }}
-
</section>
+
</section>
-
{{ block "newComment" . }}{{ end }}
+
{{ block "newComment" . }} {{ end }}
{{ end }}
{{ define "newComment" }}
{{ if .LoggedInUser }}
-
<form
+
<form
id="comment-form"
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
-
hx-on::after-request="if(event.detail.successful) this.reset()">
-
<div
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full md:w-3/5">
-
<div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
-
{{ template "user/fragments/picHandleLink" (didOrHandle .LoggedInUser.Did .LoggedInUser.Handle) }}
-
</div>
-
<textarea
-
id="comment-textarea"
-
name="body"
-
class="w-full p-2 rounded border border-gray-200 dark:border-gray-700"
-
placeholder="Add to the discussion. Markdown is supported."
-
onkeyup="updateCommentForm()"></textarea>
-
<div id="issue-comment"></div>
-
<div id="issue-action" class="error"></div>
+
hx-on::after-request="if(event.detail.successful) this.reset()"
+
>
+
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-full md:w-3/5">
+
<div class="text-sm pb-2 text-gray-500 dark:text-gray-400">
+
{{ template "user/fragments/picHandleLink" (didOrHandle .LoggedInUser.Did .LoggedInUser.Handle) }}
</div>
+
<textarea
+
id="comment-textarea"
+
name="body"
+
class="w-full p-2 rounded border border-gray-200 dark:border-gray-700"
+
placeholder="Add to the discussion. Markdown is supported."
+
onkeyup="updateCommentForm()"
+
></textarea>
+
<div id="issue-comment"></div>
+
<div id="issue-action" class="error"></div>
+
</div>
-
<div class="flex gap-2 mt-2">
+
<div class="flex gap-2 mt-2">
<button
-
id="comment-button"
-
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
-
type="submit"
-
hx-disabled-elt="#comment-button"
-
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group"
-
disabled>
-
{{ i "message-square-plus" "w-4 h-4" }}
-
comment
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
id="comment-button"
+
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
+
type="submit"
+
hx-disabled-elt="#comment-button"
+
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group"
+
disabled
+
>
+
{{ i "message-square-plus" "w-4 h-4" }}
+
comment
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
{{ $isIssueAuthor := and .LoggedInUser (eq .LoggedInUser.Did .Issue.OwnerDid) }}
{{ $isRepoCollaborator := .RepoInfo.Roles.IsCollaborator }}
{{ $isRepoOwner := .RepoInfo.Roles.IsOwner }}
{{ if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "open") }}
-
<button
+
<button
id="close-button"
type="button"
class="btn flex items-center gap-2"
hx-indicator="#close-spinner"
-
hx-trigger="click">
+
hx-trigger="click"
+
>
{{ i "ban" "w-4 h-4" }}
close
<span id="close-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</span>
-
</button>
-
<div
+
</button>
+
<div
id="close-with-comment"
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment"
hx-trigger="click from:#close-button"
···
hx-target="#issue-comment"
hx-indicator="#close-spinner"
hx-vals="js:{body: document.getElementById('comment-textarea').value.trim() !== '' ? document.getElementById('comment-textarea').value : ''}"
-
hx-swap="none"></div>
-
<div
+
hx-swap="none"
+
>
+
</div>
+
<div
id="close-issue"
hx-disabled-elt="#close-issue"
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/close"
hx-trigger="click from:#close-button"
hx-target="#issue-action"
hx-indicator="#close-spinner"
-
hx-swap="none"></div>
-
<script>
-
document.addEventListener("htmx:configRequest", function (evt) {
-
if (evt.target.id === "close-with-comment") {
-
const commentText = document
-
.getElementById("comment-textarea")
-
.value.trim();
-
if (commentText === "") {
-
evt.detail.parameters = {};
-
evt.preventDefault();
+
hx-swap="none"
+
>
+
</div>
+
<script>
+
document.addEventListener('htmx:configRequest', function(evt) {
+
if (evt.target.id === 'close-with-comment') {
+
const commentText = document.getElementById('comment-textarea').value.trim();
+
if (commentText === '') {
+
evt.detail.parameters = {};
+
evt.preventDefault();
+
}
}
-
}
});
-
</script>
+
</script>
{{ else if and (or $isIssueAuthor $isRepoCollaborator $isRepoOwner) (eq .State "closed") }}
-
<button
+
<button
type="button"
class="btn flex items-center gap-2"
hx-post="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/reopen"
hx-indicator="#reopen-spinner"
-
hx-swap="none">
+
hx-swap="none"
+
>
{{ i "refresh-ccw-dot" "w-4 h-4" }}
reopen
<span id="reopen-spinner" class="group">
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</span>
-
</button>
+
</button>
{{ end }}
<script>
···
updateCommentForm();
});
</script>
-
</div>
-
</form>
+
</div>
+
</form>
{{ else }}
-
<div
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-fit">
-
<a href="/login" class="underline">login</a>
-
to join the discussion
+
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm py-4 px-4 relative w-fit">
+
<a href="/login" class="underline">login</a> to join the discussion
</div>
{{ end }}
{{ end }}
+83 -94
appview/pages/templates/repo/issues/issues.html
···
{{ define "title" }}issues &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "extrameta" }}
-
{{ $title := "issues" }}
-
{{ $url := printf "https://tangled.sh/%s/issues" .RepoInfo.FullName }}
+
{{ $title := "issues"}}
+
{{ $url := printf "https://tangled.sh/%s/issues" .RepoInfo.FullName }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
<div class="flex justify-between items-center gap-4">
-
<div class="flex gap-4">
-
<a
+
<div class="flex justify-between items-center gap-4">
+
<div class="flex gap-4">
+
<a
href="?state=open"
-
class="flex items-center gap-2 {{ if .FilteringByOpen }}
-
font-bold
-
{{ else }}
-
text-gray-500 dark:text-gray-400
-
{{ end }}">
+
class="flex items-center gap-2 {{ if .FilteringByOpen }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
+
>
{{ i "circle-dot" "w-4 h-4" }}
<span>{{ .RepoInfo.Stats.IssueCount.Open }} open</span>
-
</a>
-
<a
+
</a>
+
<a
href="?state=closed"
-
class="flex items-center gap-2 {{ if not .FilteringByOpen }}
-
font-bold
-
{{ else }}
-
text-gray-500 dark:text-gray-400
-
{{ end }}">
+
class="flex items-center gap-2 {{ if not .FilteringByOpen }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
+
>
{{ i "ban" "w-4 h-4" }}
<span>{{ .RepoInfo.Stats.IssueCount.Closed }} closed</span>
-
</a>
-
</div>
-
<a
+
</a>
+
</div>
+
<a
href="/{{ .RepoInfo.FullName }}/issues/new"
-
class="btn-create text-sm flex items-center justify-center gap-2 no-underline hover:no-underline hover:text-white">
+
class="btn-create text-sm flex items-center justify-center gap-2 no-underline hover:no-underline hover:text-white"
+
>
{{ i "circle-plus" "w-4 h-4" }}
<span>new</span>
-
</a>
-
</div>
-
<div class="error" id="issues"></div>
+
</a>
+
</div>
+
<div class="error" id="issues"></div>
{{ end }}
{{ define "repoAfter" }}
-
<div class="flex flex-col gap-2 mt-2">
-
{{ range .Issues }}
-
<div
-
class="rounded drop-shadow-sm bg-white px-6 py-4 dark:bg-gray-800 dark:border-gray-700">
-
<div class="pb-2">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}"
-
class="no-underline hover:underline">
-
{{ .Title }}
-
<span class="text-gray-500">#{{ .IssueId }}</span>
-
</a>
-
</div>
-
<p
-
class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
-
{{ $icon := "ban" }}
-
{{ $state := "closed" }}
-
{{ if .Open }}
-
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
-
{{ $icon = "circle-dot" }}
-
{{ $state = "open" }}
-
{{ end }}
+
<div class="flex flex-col gap-2 mt-2">
+
{{ range .Issues }}
+
<div class="rounded drop-shadow-sm bg-white px-6 py-4 dark:bg-gray-800 dark:border-gray-700">
+
<div class="pb-2">
+
<a
+
href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}"
+
class="no-underline hover:underline"
+
>
+
{{ .Title }}
+
<span class="text-gray-500">#{{ .IssueId }}</span>
+
</a>
+
</div>
+
<p class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
+
{{ $icon := "ban" }}
+
{{ $state := "closed" }}
+
{{ if .Open }}
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
+
{{ $icon = "circle-dot" }}
+
{{ $state = "open" }}
+
{{ end }}
+
<span class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
+
{{ i $icon "w-3 h-3 mr-1.5 text-white dark:text-white" }}
+
<span class="text-white dark:text-white">{{ $state }}</span>
+
</span>
-
<span
-
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
-
{{ i $icon "w-3 h-3 mr-1.5 text-white dark:text-white" }}
-
<span class="text-white dark:text-white">{{ $state }}</span>
-
</span>
-
-
<span class="ml-1">
-
{{ template "user/fragments/picHandleLink" .OwnerDid }}
-
</span>
+
<span class="ml-1">
+
{{ template "user/fragments/picHandleLink" .OwnerDid }}
+
</span>
-
<span class="before:content-['·']">
-
{{ template "repo/fragments/time" .Created }}
-
</span>
+
<span class="before:content-['·']">
+
{{ template "repo/fragments/time" .Created }}
+
</span>
-
<span class="before:content-['·']">
-
{{ $s := "s" }}
-
{{ if eq .Metadata.CommentCount 1 }}
-
{{ $s = "" }}
-
{{ end }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}"
-
class="text-gray-500 dark:text-gray-400">
-
{{ .Metadata.CommentCount }}
-
comment{{ $s }}
-
</a>
-
</span>
-
</p>
-
</div>
-
{{ end }}
+
<span class="before:content-['·']">
+
{{ $s := "s" }}
+
{{ if eq .Metadata.CommentCount 1 }}
+
{{ $s = "" }}
+
{{ end }}
+
<a href="/{{ $.RepoInfo.FullName }}/issues/{{ .IssueId }}" class="text-gray-500 dark:text-gray-400">{{ .Metadata.CommentCount }} comment{{$s}}</a>
+
</span>
+
</p>
</div>
+
{{ end }}
+
</div>
-
{{ block "pagination" . }}{{ end }}
+
{{ block "pagination" . }} {{ end }}
{{ end }}
{{ define "pagination" }}
-
<div class="flex justify-end mt-4 gap-2">
+
<div class="flex justify-end mt-4 gap-2">
{{ $currentState := "closed" }}
{{ if .FilteringByOpen }}
{{ $currentState = "open" }}
{{ end }}
{{ if gt .Page.Offset 0 }}
-
{{ $prev := .Page.Previous }}
-
<a
-
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
-
hx-boost="true"
-
href="/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $prev.Offset }}&limit={{ $prev.Limit }}">
-
{{ i "chevron-left" "w-4 h-4" }}
-
previous
-
</a>
+
{{ $prev := .Page.Previous }}
+
<a
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
+
hx-boost="true"
+
href = "/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $prev.Offset }}&limit={{ $prev.Limit }}"
+
>
+
{{ i "chevron-left" "w-4 h-4" }}
+
previous
+
</a>
{{ else }}
-
<div></div>
+
<div></div>
{{ end }}
{{ if eq (len .Issues) .Page.Limit }}
-
{{ $next := .Page.Next }}
-
<a
-
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
-
hx-boost="true"
-
href="/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $next.Offset }}&limit={{ $next.Limit }}">
-
next
-
{{ i "chevron-right" "w-4 h-4" }}
-
</a>
+
{{ $next := .Page.Next }}
+
<a
+
class="btn flex items-center gap-2 no-underline hover:no-underline dark:text-white dark:hover:bg-gray-700"
+
hx-boost="true"
+
href = "/{{ $.RepoInfo.FullName }}/issues?state={{ $currentState }}&offset={{ $next.Offset }}&limit={{ $next.Limit }}"
+
>
+
next
+
{{ i "chevron-right" "w-4 h-4" }}
+
</a>
{{ end }}
-
</div>
+
</div>
{{ end }}
+33 -31
appview/pages/templates/repo/issues/new.html
···
{{ define "title" }}new issue &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "repoContent" }}
-
<form
-
hx-post="/{{ .RepoInfo.FullName }}/issues/new"
-
class="mt-6 space-y-6"
-
hx-swap="none"
-
hx-indicator="#spinner">
-
<div class="flex flex-col gap-4">
-
<div>
-
<label for="title">title</label>
-
<input type="text" name="title" id="title" class="w-full" />
-
</div>
-
<div>
-
<label for="body">body</label>
-
<textarea
-
name="body"
-
id="body"
-
rows="6"
-
class="w-full resize-y"
-
placeholder="Describe your issue. Markdown is supported."></textarea>
-
</div>
-
<div>
-
<button type="submit" class="btn-create flex items-center gap-2">
-
{{ i "circle-plus" "w-4 h-4" }}
-
create issue
-
<span id="create-pull-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</div>
-
</div>
-
<div id="issues" class="error"></div>
-
</form>
+
<form
+
hx-post="/{{ .RepoInfo.FullName }}/issues/new"
+
class="mt-6 space-y-6"
+
hx-swap="none"
+
hx-indicator="#spinner"
+
>
+
<div class="flex flex-col gap-4">
+
<div>
+
<label for="title">title</label>
+
<input type="text" name="title" id="title" class="w-full" />
+
</div>
+
<div>
+
<label for="body">body</label>
+
<textarea
+
name="body"
+
id="body"
+
rows="6"
+
class="w-full resize-y"
+
placeholder="Describe your issue. Markdown is supported."
+
></textarea>
+
</div>
+
<div>
+
<button type="submit" class="btn-create flex items-center gap-2">
+
{{ i "circle-plus" "w-4 h-4" }}
+
create issue
+
<span id="create-pull-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</div>
+
</div>
+
<div id="issues" class="error"></div>
+
</form>
{{ end }}
+135 -208
appview/pages/templates/repo/log.html
···
{{ define "title" }}commits &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "extrameta" }}
-
{{ $title := printf "commits &middot; %s" .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/commits" .RepoInfo.FullName }}
+
{{ $title := printf "commits &middot; %s" .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/commits" .RepoInfo.FullName }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
<section id="commit-table" class="overflow-x-auto">
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">commits</h2>
+
<section id="commit-table" class="overflow-x-auto">
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
+
commits
+
</h2>
<!-- desktop view (hidden on small screens) -->
-
<div
-
class="hidden md:flex md:flex-col divide-y divide-gray-200 dark:divide-gray-700">
+
<div class="hidden md:flex md:flex-col divide-y divide-gray-200 dark:divide-gray-700">
{{ $grid := "grid grid-cols-14 gap-4" }}
<div class="{{ $grid }}">
-
<div
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-2">
-
Author
-
</div>
-
<div
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-3">
-
Commit
-
</div>
-
<div
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-6">
-
Message
-
</div>
-
<div
-
class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-1"></div>
-
<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>
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-2">Author</div>
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-3">Commit</div>
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-6">Message</div>
+
<div class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold col-span-1"></div>
+
<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>
</div>
{{ range $index, $commit := .Commits }}
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
<div class="{{ $grid }} py-3">
<div class="align-top truncate col-span-2">
-
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
-
{{ if $didOrHandle }}
-
{{ template "user/fragments/picHandleLink" $didOrHandle }}
-
{{ else }}
-
<a
-
href="mailto:{{ $commit.Author.Email }}"
-
class="text-gray-700 dark:text-gray-300 no-underline hover:underline">
-
{{ $commit.Author.Name }}
-
</a>
-
{{ end }}
+
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
+
{{ if $didOrHandle }}
+
{{ template "user/fragments/picHandleLink" $didOrHandle }}
+
{{ else }}
+
<a href="mailto:{{ $commit.Author.Email }}" class="text-gray-700 dark:text-gray-300 no-underline hover:underline">{{ $commit.Author.Name }}</a>
+
{{ end }}
</div>
<div class="align-top font-mono flex items-start col-span-3">
-
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
-
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
-
{{ if $verified }}
-
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
-
{{ end }}
-
<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">
-
{{ slice $commit.Hash.String 0 8 }}
+
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
+
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
{{ if $verified }}
-
{{ i "shield-check" "w-4 h-4" }}
+
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
{{ end }}
-
</a>
-
<div class="{{ if not $verified }}ml-6{{ end }}inline-flex">
-
<button
-
class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
-
title="Copy SHA"
-
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)">
-
{{ i "copy" "w-4 h-4" }}
-
</button>
-
<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">
-
{{ i "folder-code" "w-4 h-4" }}
+
<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">
+
{{ slice $commit.Hash.String 0 8 }}
+
{{ if $verified }}
+
{{ i "shield-check" "w-4 h-4" }}
+
{{ end }}
</a>
-
</div>
+
<div class="{{ if not $verified }} ml-6 {{ end }}inline-flex">
+
<button class="p-1 mx-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
+
title="Copy SHA"
+
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)">
+
{{ i "copy" "w-4 h-4" }}
+
</button>
+
<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">
+
{{ i "folder-code" "w-4 h-4" }}
+
</a>
+
</div>
+
</div>
<div class="align-top col-span-6">
<div>
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
-
class="dark:text-white no-underline hover:underline">
-
{{ index $messageParts 0 }}
-
</a>
-
{{ if gt (len $messageParts) 1 }}
-
<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>
-
{{ end }}
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}" class="dark:text-white no-underline hover:underline">{{ index $messageParts 0 }}</a>
+
{{ if gt (len $messageParts) 1 }}
+
<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>
+
{{ end }}
-
{{ if index $.TagMap $commit.Hash.String }}
-
{{ range $tag := index $.TagMap $commit.Hash.String }}
-
<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">
-
{{ $tag }}
-
</span>
+
{{ if index $.TagMap $commit.Hash.String }}
+
{{ range $tag := index $.TagMap $commit.Hash.String }}
+
<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">
+
{{ $tag }}
+
</span>
+
{{ end }}
{{ end }}
-
{{ end }}
</div>
{{ if gt (len $messageParts) 1 }}
-
<p class="hidden mt-1 text-sm text-gray-600 dark:text-gray-400">
-
{{ nl2br (index $messageParts 1) }}
-
</p>
+
<p class="hidden mt-1 text-sm text-gray-600 dark:text-gray-400">{{ nl2br (index $messageParts 1) }}</p>
{{ end }}
</div>
<div class="align-top col-span-1">
-
<!-- ci status -->
-
{{ $pipeline := index $.Pipelines .Hash.String }}
-
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
-
{{ end }}
-
</div>
-
<div
-
class="align-top justify-self-end text-gray-500 dark:text-gray-400 col-span-2">
-
{{ template "repo/fragments/shortTimeAgo" $commit.Committer.When }}
+
<!-- ci status -->
+
{{ $pipeline := index $.Pipelines .Hash.String }}
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
+
{{ end }}
</div>
+
<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>
</div>
{{ end }}
</div>
<!-- mobile view (visible only on small screens) -->
<div class="md:hidden">
-
{{ range $index, $commit := .Commits }}
-
<div
-
class="relative p-2 mb-2 {{ if ne $index (sub (len $.Commits) 1) }}
-
border-b border-gray-200 dark:border-gray-700
-
{{ end }}">
-
<div id="commit-message">
-
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
-
<div class="text-base cursor-pointer">
-
<div class="flex items-center justify-between">
-
<div class="flex-1">
-
<div>
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
-
class="inline no-underline hover:underline dark:text-white">
-
{{ index $messageParts 0 }}
-
</a>
-
{{ if gt (len $messageParts) 1 }}
-
<button
-
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
-
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
-
{{ i "ellipsis" "w-3 h-3" }}
-
</button>
-
{{ end }}
+
{{ range $index, $commit := .Commits }}
+
<div class="relative p-2 mb-2 {{ if ne $index (sub (len $.Commits) 1) }}border-b border-gray-200 dark:border-gray-700{{ end }}">
+
<div id="commit-message">
+
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
+
<div class="text-base cursor-pointer">
+
<div class="flex items-center justify-between">
+
<div class="flex-1">
+
<div>
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
+
class="inline no-underline hover:underline dark:text-white">
+
{{ index $messageParts 0 }}
+
</a>
+
{{ if gt (len $messageParts) 1 }}
+
<button
+
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
+
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
+
{{ i "ellipsis" "w-3 h-3" }}
+
</button>
+
{{ end }}
+
+
{{ if index $.TagMap $commit.Hash.String }}
+
{{ range $tag := index $.TagMap $commit.Hash.String }}
+
<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">
+
{{ $tag }}
+
</span>
+
{{ end }}
+
{{ end }}
+
</div>
-
{{ if index $.TagMap $commit.Hash.String }}
-
{{ range $tag := index $.TagMap $commit.Hash.String }}
-
<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">
-
{{ $tag }}
-
</span>
-
{{ end }}
+
{{ if gt (len $messageParts) 1 }}
+
<p class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
+
{{ nl2br (index $messageParts 1) }}
+
</p>
+
{{ end }}
+
</div>
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
+
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
+
title="Browse repository at this commit">
+
{{ i "folder-code" "w-4 h-4" }}
+
</a>
+
</div>
+
</div>
+
</div>
+
+
<div class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center">
+
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
+
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
+
{{ if $verified }}
+
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
{{ end }}
-
</div>
+
<span class="font-mono">
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
+
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
+
{{ slice $commit.Hash.String 0 8 }}
+
{{ if $verified }}
+
{{ i "shield-check" "w-3 h-3" }}
+
{{ end }}
+
</a>
+
</span>
+
<span class="mx-2 before:content-['·'] before:select-none"></span>
+
<span>
+
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
+
<a href="{{ if $didOrHandle }}/{{ $didOrHandle }}{{ else }}mailto:{{ $commit.Author.Email }}{{ end }}"
+
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
+
{{ if $didOrHandle }}{{ template "user/fragments/picHandleLink" $didOrHandle }}{{ else }}{{ $commit.Author.Name }}{{ end }}
+
</a>
+
</span>
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
+
<span>{{ template "repo/fragments/shortTime" $commit.Committer.When }}</span>
-
{{ if gt (len $messageParts) 1 }}
-
<p
-
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
-
{{ nl2br (index $messageParts 1) }}
-
</p>
-
{{ end }}
+
<!-- ci status -->
+
{{ $pipeline := index $.Pipelines .Hash.String }}
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
+
<span class="text-sm">
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
+
</span>
+
{{ end }}
</div>
-
<a
-
href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
-
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
-
title="Browse repository at this commit">
-
{{ i "folder-code" "w-4 h-4" }}
-
</a>
-
</div>
</div>
-
</div>
+
{{ end }}
+
</div>
+
</section>
-
<div
-
class="text-xs mt-2 text-gray-500 dark:text-gray-400 flex items-center">
-
{{ $verified := $.VerifiedCommits.IsVerified $commit.Hash.String }}
-
{{ $hashStyle := "text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-900" }}
-
{{ if $verified }}
-
{{ $hashStyle = "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 rounded" }}
-
{{ end }}
-
<span class="font-mono">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
-
class="no-underline hover:underline {{ $hashStyle }} px-2 py-1 rounded flex items-center gap-2">
-
{{ slice $commit.Hash.String 0 8 }}
-
{{ if $verified }}
-
{{ i "shield-check" "w-3 h-3" }}
-
{{ end }}
-
</a>
-
</span>
-
<span class="mx-2 before:content-['·'] before:select-none"></span>
-
<span>
-
{{ $didOrHandle := index $.EmailToDidOrHandle $commit.Author.Email }}
-
<a
-
href="{{ if $didOrHandle }}
-
/{{ $didOrHandle }}
-
{{ else }}
-
mailto:{{ $commit.Author.Email }}
-
{{ end }}"
-
class="text-gray-500 dark:text-gray-400 no-underline hover:underline">
-
{{ if $didOrHandle }}
-
{{ template "user/fragments/picHandleLink" $didOrHandle }}
-
{{ else }}
-
{{ $commit.Author.Name }}
-
{{ end }}
-
</a>
-
</span>
-
<div
-
class="inline-block px-1 select-none after:content-['·']"></div>
-
<span>
-
{{ template "repo/fragments/shortTime" $commit.Committer.When }}
-
</span>
-
-
<!-- ci status -->
-
{{ $pipeline := index $.Pipelines .Hash.String }}
-
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
-
<div
-
class="inline-block px-1 select-none after:content-['·']"></div>
-
<span class="text-sm">
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" $pipeline "RepoInfo" $.RepoInfo) }}
-
</span>
-
{{ end }}
-
</div>
-
</div>
-
{{ end }}
-
</div>
-
</section>
{{ end }}
{{ define "repoAfter" }}
{{ $commits_len := len .Commits }}
<div class="flex justify-end mt-4 gap-2">
-
{{ 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 }}
-
{{ 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 }}
+
{{ 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 }}
+
{{ 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 }}
</div>
{{ end }}
+49 -56
appview/pages/templates/repo/new.html
···
{{ define "title" }}new repo{{ end }}
{{ define "content" }}
-
<div class="p-6">
-
<p class="text-xl font-bold dark:text-white">Create a new repository</p>
-
</div>
-
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
-
<form
-
hx-post="/repo/new"
-
class="space-y-12"
-
hx-swap="none"
-
hx-indicator="#spinner">
-
<div class="space-y-2">
-
<label for="name" class="-mb-1 dark:text-white">Repository name</label>
-
<input
+
<div class="p-6">
+
<p class="text-xl font-bold dark:text-white">Create a new repository</p>
+
</div>
+
<div class="p-6 bg-white dark:bg-gray-800 drop-shadow-sm rounded">
+
<form hx-post="/repo/new" class="space-y-12" hx-swap="none" hx-indicator="#spinner">
+
<div class="space-y-2">
+
<label for="name" class="-mb-1 dark:text-white">Repository name</label>
+
<input
type="text"
id="name"
name="name"
required
-
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600" />
-
<p class="text-sm text-gray-500 dark:text-gray-400">
-
All repositories are publicly visible.
-
</p>
+
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
/>
+
<p class="text-sm text-gray-500 dark:text-gray-400">All repositories are publicly visible.</p>
-
<label for="branch" class="dark:text-white">Default branch</label>
-
<input
+
<label for="branch" class="dark:text-white">Default branch</label>
+
<input
type="text"
id="branch"
name="branch"
value="main"
required
-
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600" />
+
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
/>
-
<label for="description" class="dark:text-white">Description</label>
-
<input
+
<label for="description" class="dark:text-white">Description</label>
+
<input
type="text"
id="description"
name="description"
-
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600" />
-
</div>
+
class="w-full max-w-md dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
/>
+
</div>
-
<fieldset class="space-y-3">
-
<legend class="dark:text-white">Select a knot</legend>
-
<div class="space-y-2">
-
<div class="flex flex-col">
-
{{ range .Knots }}
-
<div class="flex items-center">
-
<input
-
type="radio"
-
name="domain"
-
value="{{ . }}"
-
class="mr-2"
-
id="domain-{{ . }}" />
-
<span class="dark:text-white">{{ . }}</span>
-
</div>
-
{{ else }}
-
<p class="dark:text-white">No knots available.</p>
-
{{ end }}
+
<fieldset class="space-y-3">
+
<legend class="dark:text-white">Select a knot</legend>
+
<div class="space-y-2">
+
<div class="flex flex-col">
+
{{ range .Knots }}
+
<div class="flex items-center">
+
<input
+
type="radio"
+
name="domain"
+
value="{{ . }}"
+
class="mr-2"
+
id="domain-{{ . }}"
+
/>
+
<span class="dark:text-white">{{ . }}</span>
</div>
+
{{ else }}
+
<p class="dark:text-white">No knots available.</p>
+
{{ end }}
</div>
-
<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>
-
</fieldset>
+
</div>
+
<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>
+
</fieldset>
-
<div class="space-y-2">
+
<div class="space-y-2">
<button type="submit" class="btn-create flex items-center gap-2">
-
{{ i "book-plus" "w-4 h-4" }}
-
create repo
-
<span id="create-pull-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
+
{{ i "book-plus" "w-4 h-4" }}
+
create repo
+
<span id="create-pull-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
</button>
<div id="repo" class="error"></div>
-
</div>
-
</form>
-
</div>
+
</div>
+
</form>
+
</div>
{{ end }}
+12 -21
appview/pages/templates/repo/pipelines/fragments/logBlock.html
···
{{ define "repo/pipelines/fragments/logBlock" }}
-
<div id="lines" hx-swap-oob="beforeend">
-
<details
-
id="step-{{ .Id }}"
-
{{ if not .Collapsed }}open{{ end }}
-
class="group pb-2 rounded-sm border border-gray-200 dark:border-gray-700">
-
<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">
-
<div class="group-open:hidden flex items-center gap-1">
-
{{ i "chevron-right" "w-4 h-4" }}
-
{{ .Name }}
-
</div>
-
<div class="hidden group-open:flex items-center gap-1">
-
{{ i "chevron-down" "w-4 h-4" }}
-
{{ .Name }}
-
</div>
-
</summary>
-
<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 id="lines" hx-swap-oob="beforeend">
+
<details id="step-{{ .Id }}" {{if not .Collapsed}}open{{end}} class="group pb-2 rounded-sm border border-gray-200 dark:border-gray-700">
+
<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">
+
<div class="group-open:hidden flex items-center gap-1">
+
{{ i "chevron-right" "w-4 h-4" }} {{ .Name }}
+
</div>
+
<div class="hidden group-open:flex items-center gap-1">
+
{{ i "chevron-down" "w-4 h-4" }} {{ .Name }}
</div>
-
</details>
-
</div>
+
</summary>
+
<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>
+
</details>
+
</div>
{{ end }}
+2 -3
appview/pages/templates/repo/pipelines/fragments/logLine.html
···
{{ define "repo/pipelines/fragments/logLine" }}
-
<div id="step-body-{{ .Id }}" hx-swap-oob="beforeend" class="whitespace-pre">
-
<p>{{ .Content }}</p>
-
</div>
+
<div id="step-body-{{ .Id }}" hx-swap-oob="beforeend" class="whitespace-pre"><p>{{ .Content }}</p></div>
{{ end }}
+
+9 -22
appview/pages/templates/repo/pipelines/fragments/pipelineSymbol.html
···
{{ $offset := 0.0 }}
<div class="flex gap-1 items-center">
<svg class="w-4 h-4 transform -rotate-90" viewBox="0 0 20 20">
-
<circle
-
cx="10"
-
cy="10"
-
r="{{ $radius }}"
-
fill="none"
-
stroke="#f3f4f633"
-
stroke-width="2" />
+
<circle cx="10" cy="10" r="{{ $radius }}" fill="none" stroke="#f3f4f633" stroke-width="2"/>
{{ range $kind, $count := $c }}
{{ $color := "" }}
{{ if or (eq $kind "pending") (eq $kind "running") }}
-
{{ $color = "#eab308" }}
-
{{/* amber-500 */}}
+
{{ $color = "#eab308" }} {{/* amber-500 */}}
{{ else if eq $kind "success" }}
-
{{ $color = "#10b981" }}
-
{{/* green-500 */}}
+
{{ $color = "#10b981" }} {{/* green-500 */}}
{{ else if eq $kind "cancelled" }}
-
{{ $color = "#6b7280" }}
-
{{/* gray-500 */}}
+
{{ $color = "#6b7280" }} {{/* gray-500 */}}
{{ else if eq $kind "timeout" }}
-
{{ $color = "#fb923c" }}
-
{{/* orange-400 */}}
+
{{ $color = "#fb923c" }} {{/* orange-400 */}}
{{ else }}
-
{{ $color = "#ef4444" }}
-
{{/* red-500 for failed or unknown */}}
+
{{ $color = "#ef4444" }} {{/* red-500 for failed or unknown */}}
{{ end }}
{{ $percent := divf64 (f64 $count) (f64 $total) }}
{{ $length := mulf64 $percent $circumference }}
-
<circle
-
cx="10"
-
cy="10"
-
r="{{ $radius }}"
+
cx="10" cy="10" r="{{ $radius }}"
fill="none"
stroke="{{ $color }}"
stroke-width="2"
stroke-dasharray="{{ printf "%.2f %.2f" $length (subf64 $circumference $length) }}"
-
stroke-dashoffset="{{ printf "%.2f" (negf64 $offset) }}" />
+
stroke-dashoffset="{{ printf "%.2f" (negf64 $offset) }}"
+
/>
{{ $offset = addf64 $offset $length }}
{{ end }}
</svg>
+22 -27
appview/pages/templates/repo/pipelines/fragments/tooltip.html
···
{{ $repoinfo := .RepoInfo }}
{{ $pipeline := .Pipeline }}
{{ $id := $pipeline.Id }}
-
<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">
+
<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">
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700">
{{ range $name, $all := $pipeline.Statuses }}
-
<a
-
href="/{{ $repoinfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}"
-
class="hover:no-underline">
-
<div class="flex items-center justify-between p-2">
-
{{ $lastStatus := $all.Latest }}
-
{{ $kind := $lastStatus.Status.String }}
+
<a href="/{{ $repoinfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}" class="hover:no-underline">
+
<div class="flex items-center justify-between p-2">
+
{{ $lastStatus := $all.Latest }}
+
{{ $kind := $lastStatus.Status.String }}
-
-
<div id="left" class="flex items-center gap-2 flex-shrink-0">
-
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
-
{{ $name }}
-
</div>
-
<div id="right" class="flex items-center gap-2 flex-shrink-0">
-
<span class="font-bold">{{ $kind }}</span>
-
{{ if .TimeTaken }}
-
{{ template "repo/fragments/duration" .TimeTaken }}
-
{{ else }}
-
{{ template "repo/fragments/shortTimeAgo" $pipeline.Created }}
-
{{ end }}
-
</div>
+
<div id="left" class="flex items-center gap-2 flex-shrink-0">
+
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
+
{{ $name }}
+
</div>
+
<div id="right" class="flex items-center gap-2 flex-shrink-0">
+
<span class="font-bold">{{ $kind }}</span>
+
{{ if .TimeTaken }}
+
{{ template "repo/fragments/duration" .TimeTaken }}
+
{{ else }}
+
{{ template "repo/fragments/shortTimeAgo" $pipeline.Created }}
+
{{ end }}
</div>
-
</a>
-
{{ else }}
-
<div
-
class="flex items-center gap-2 p-2 italic text-gray-600 dark:text-gray-400 ">
-
{{ i "hourglass" "size-4" }}
-
Waiting for spindle ...
</div>
+
</a>
+
{{ else }}
+
<div class="flex items-center gap-2 p-2 italic text-gray-600 dark:text-gray-400 ">
+
{{ i "hourglass" "size-4" }}
+
Waiting for spindle ...
+
</div>
{{ end }}
</div>
</div>
+72 -82
appview/pages/templates/repo/pipelines/pipelines.html
···
{{ define "title" }}pipelines &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "extrameta" }}
-
{{ $title := "pipelines" }}
-
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ $title := "pipelines"}}
+
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
<div class="flex justify-between items-center gap-4">
-
<div class="w-full flex flex-col gap-2">
-
{{ range .Pipelines }}
-
{{ block "pipeline" (list $ .) }}{{ end }}
-
{{ else }}
-
<p class="text-center pt-5 text-gray-400 dark:text-gray-500">
-
No pipelines run for this repository.
-
</p>
-
{{ end }}
-
</div>
+
<div class="flex justify-between items-center gap-4">
+
<div class="w-full flex flex-col gap-2">
+
{{ range .Pipelines }}
+
{{ block "pipeline" (list $ .) }} {{ end }}
+
{{ else }}
+
<p class="text-center pt-5 text-gray-400 dark:text-gray-500">
+
No pipelines run for this repository.
+
</p>
+
{{ end }}
</div>
+
</div>
{{ end }}
+
{{ define "pipeline" }}
{{ $root := index . 0 }}
{{ $p := index . 1 }}
<div class="py-2 bg-white dark:bg-gray-800 dark:text-white">
-
{{ block "pipelineHeader" $ }}{{ end }}
+
{{ block "pipelineHeader" $ }} {{ end }}
</div>
{{ end }}
···
{{ $root := index . 0 }}
{{ $p := index . 1 }}
{{ with $p }}
-
<div class="grid grid-cols-6 md:grid-cols-12 gap-2 items-center w-full">
-
<div class="text-sm md:text-base col-span-1">
-
{{ .Trigger.Kind.String }}
-
</div>
+
<div class="grid grid-cols-6 md:grid-cols-12 gap-2 items-center w-full">
+
<div class="text-sm md:text-base col-span-1">
+
{{ .Trigger.Kind.String }}
+
</div>
-
<div class="col-span-2 md:col-span-7 flex items-center gap-4">
-
{{ $target := .Trigger.TargetRef }}
-
{{ $workflows := .Workflows }}
-
{{ $link := "" }}
-
{{ if .IsResponding }}
-
{{ $link = printf "/%s/pipelines/%s/workflow/%d" $root.RepoInfo.FullName .Id (index $workflows 0) }}
-
{{ end }}
-
{{ if .Trigger.IsPush }}
-
<span class="font-bold">{{ $target }}</span>
-
<span
-
class="hidden md:inline-flex gap-2 items-center font-mono text-sm">
-
{{ $old := deref .Trigger.PushOldSha }}
-
{{ $new := deref .Trigger.PushNewSha }}
-
-
-
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $new }}">
-
{{ slice $new 0 8 }}
-
</a>
-
{{ i "arrow-left" "size-4" }}
-
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $old }}">
-
{{ slice $old 0 8 }}
-
</a>
-
</span>
-
{{ else if .Trigger.IsPullRequest }}
-
{{ $sha := deref .Trigger.PRSourceSha }}
-
<span class="inline-flex gap-2 items-center">
+
<div class="col-span-2 md:col-span-7 flex items-center gap-4">
+
{{ $target := .Trigger.TargetRef }}
+
{{ $workflows := .Workflows }}
+
{{ $link := "" }}
+
{{ if .IsResponding }}
+
{{ $link = printf "/%s/pipelines/%s/workflow/%d" $root.RepoInfo.FullName .Id (index $workflows 0) }}
+
{{ end }}
+
{{ if .Trigger.IsPush }}
<span class="font-bold">{{ $target }}</span>
-
{{ i "arrow-left" "size-4" }}
-
{{ .Trigger.PRSourceBranch }}
-
<span class="text-sm font-mono">
-
@
-
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $sha }}">
-
{{ slice $sha 0 8 }}
-
</a>
+
<span class="hidden md:inline-flex gap-2 items-center font-mono text-sm">
+
{{ $old := deref .Trigger.PushOldSha }}
+
{{ $new := deref .Trigger.PushNewSha }}
+
+
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $new }}">{{ slice $new 0 8 }}</a>
+
{{ i "arrow-left" "size-4" }}
+
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $old }}">{{ slice $old 0 8 }}</a>
</span>
-
</span>
-
{{ end }}
-
</div>
+
{{ else if .Trigger.IsPullRequest }}
+
{{ $sha := deref .Trigger.PRSourceSha }}
+
<span class="inline-flex gap-2 items-center">
+
<span class="font-bold">{{ $target }}</span>
+
{{ i "arrow-left" "size-4" }}
+
{{ .Trigger.PRSourceBranch }}
+
<span class="text-sm font-mono">
+
@
+
<a href="/{{ $root.RepoInfo.FullName }}/commit/{{ $sha }}">{{ slice $sha 0 8 }}</a>
+
</span>
+
</span>
+
{{ end }}
+
</div>
-
<div class="text-sm md:text-base col-span-1">
-
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" . "RepoInfo" $root.RepoInfo) }}
-
</div>
+
<div class="text-sm md:text-base col-span-1">
+
{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "Pipeline" . "RepoInfo" $root.RepoInfo) }}
+
</div>
+
+
<div class="text-sm md:text-base col-span-1 text-right">
+
{{ template "repo/fragments/shortTimeAgo" .Created }}
+
</div>
-
<div class="text-sm md:text-base col-span-1 text-right">
-
{{ template "repo/fragments/shortTimeAgo" .Created }}
-
</div>
+
{{ $t := .TimeTaken }}
+
<div class="text-sm md:text-base col-span-1 text-right">
+
{{ if $t }}
+
<time title="{{ $t }}">{{ $t | durationFmt }}</time>
+
{{ else }}
+
<time>--</time>
+
{{ end }}
+
</div>
-
{{ $t := .TimeTaken }}
-
<div class="text-sm md:text-base col-span-1 text-right">
-
{{ if $t }}
-
<time title="{{ $t }}">{{ $t | durationFmt }}</time>
-
{{ else }}
-
<time>--</time>
-
{{ end }}
-
</div>
+
<div class="col-span-1 flex justify-end">
+
{{ if $link }}
+
<a class="md:hidden" href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
+
{{ i "arrow-up-right" "size-4" }}
+
</a>
+
<a class="hidden md:inline underline" href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
+
view
+
</a>
+
{{ end }}
+
</div>
-
<div class="col-span-1 flex justify-end">
-
{{ if $link }}
-
<a
-
class="md:hidden"
-
href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
-
{{ i "arrow-up-right" "size-4" }}
-
</a>
-
<a
-
class="hidden md:inline underline"
-
href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ .Id }}/workflow/{{ index $workflows 0 }}">
-
view
-
</a>
-
{{ end }}
</div>
-
</div>
{{ end }}
{{ end }}
+37 -48
appview/pages/templates/repo/pipelines/workflow.html
···
-
{{ define "title" }}
-
{{ .Workflow }} &middot; pipeline {{ .Pipeline.Id }} &middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title" }} {{ .Workflow }} &middot; pipeline {{ .Pipeline.Id }} &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "extrameta" }}
-
{{ $title := "pipelines" }}
-
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ $title := "pipelines"}}
+
{{ $url := printf "https://tangled.sh/%s/pipelines" .RepoInfo.FullName }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2 mt-2">
-
<div class="col-span-1">
-
{{ block "sidebar" . }}{{ end }}
-
</div>
-
<div class="col-span-1 md:col-span-3">
-
{{ block "logs" . }}{{ end }}
-
</div>
-
</section>
+
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2 mt-2">
+
<div class="col-span-1">
+
{{ block "sidebar" . }} {{ end }}
+
</div>
+
<div class="col-span-1 md:col-span-3">
+
{{ block "logs" . }} {{ end }}
+
</div>
+
</section>
{{ end }}
{{ define "sidebar" }}
···
{{ with .Pipeline }}
{{ $id := .Id }}
-
<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">
+
<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">
{{ range $name, $all := .Statuses }}
-
<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">
-
<div
-
class="flex gap-2 items-center justify-between p-2 {{ if eq $name $active }}
-
{{ $activeTab }}
+
<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">
+
<div
+
class="flex gap-2 items-center justify-between p-2 {{ if eq $name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}">
+
{{ $lastStatus := $all.Latest }}
+
{{ $kind := $lastStatus.Status.String }}
+
+
<div id="left" class="flex items-center gap-2 flex-shrink-0">
+
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
+
{{ $name }}
+
</div>
+
<div id="right" class="flex items-center gap-2 flex-shrink-0">
+
<span class="font-bold">{{ $kind }}</span>
+
{{ if .TimeTaken }}
+
{{ template "repo/fragments/duration" .TimeTaken }}
{{ else }}
-
{{ $inactiveTab }}
-
{{ end }}">
-
{{ $lastStatus := $all.Latest }}
-
{{ $kind := $lastStatus.Status.String }}
-
-
-
<div id="left" class="flex items-center gap-2 flex-shrink-0">
-
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
-
{{ $name }}
-
</div>
-
<div id="right" class="flex items-center gap-2 flex-shrink-0">
-
<span class="font-bold">{{ $kind }}</span>
-
{{ if .TimeTaken }}
-
{{ template "repo/fragments/duration" .TimeTaken }}
-
{{ else }}
-
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
-
{{ end }}
-
</div>
+
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
+
{{ end }}
</div>
-
</a>
+
</div>
+
</a>
{{ end }}
</div>
{{ end }}
{{ end }}
{{ define "logs" }}
-
<div
-
id="log-stream"
-
class="text-sm"
-
hx-ext="ws"
-
ws-connect="/{{ $.RepoInfo.FullName }}/pipelines/{{ .Pipeline.Id }}/workflow/{{ .Workflow }}/logs">
-
<div id="lines" class="flex flex-col gap-2"></div>
+
<div id="log-stream"
+
class="text-sm"
+
hx-ext="ws"
+
ws-connect="/{{ $.RepoInfo.FullName }}/pipelines/{{ .Pipeline.Id }}/workflow/{{ .Workflow }}/logs">
+
<div id="lines" class="flex flex-col gap-2">
+
</div>
</div>
{{ end }}
+63 -62
appview/pages/templates/repo/pulls/fragments/pullActions.html
···
{{ $isSameRepoBranch := .Pull.IsBranchBased }}
{{ $isUpToDate := .ResubmitCheck.No }}
<div class="relative w-fit">
-
<div id="actions-{{ $roundNumber }}" class="flex flex-wrap gap-2">
-
<button
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ $roundNumber }}/comment"
-
hx-target="#actions-{{ $roundNumber }}"
-
hx-swap="outerHtml"
-
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group">
-
{{ i "message-square-plus" "w-4 h-4" }}
-
<span>comment</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
-
{{ if and $isPushAllowed $isOpen $isLastRound }}
-
{{ $disabled := "" }}
-
{{ if $isConflicted }}
-
{{ $disabled = "disabled" }}
+
<div id="actions-{{$roundNumber}}" class="flex flex-wrap gap-2">
+
<button
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ $roundNumber }}/comment"
+
hx-target="#actions-{{$roundNumber}}"
+
hx-swap="outerHtml"
+
class="btn p-2 flex items-center gap-2 no-underline hover:no-underline group">
+
{{ i "message-square-plus" "w-4 h-4" }}
+
<span>comment</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
+
{{ if and $isPushAllowed $isOpen $isLastRound }}
+
{{ $disabled := "" }}
+
{{ if $isConflicted }}
+
{{ $disabled = "disabled" }}
+
{{ end }}
+
<button
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge"
+
hx-swap="none"
+
hx-confirm="Are you sure you want to merge pull #{{ .Pull.PullId }} into the `{{ .Pull.TargetBranch }}` branch?"
+
class="btn p-2 flex items-center gap-2 group" {{ $disabled }}>
+
{{ i "git-merge" "w-4 h-4" }}
+
<span>merge{{if $stackCount}} {{$stackCount}}{{end}}</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
{{ end }}
-
<button
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/merge"
-
hx-swap="none"
-
hx-confirm="Are you sure you want to merge pull #{{ .Pull.PullId }} into the `{{ .Pull.TargetBranch }}` branch?"
-
class="btn p-2 flex items-center gap-2 group"
-
{{ $disabled }}>
-
{{ i "git-merge" "w-4 h-4" }}
-
<span>merge{{ if $stackCount }}{{ $stackCount }}{{ end }}</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
-
{{ end }}
-
{{ if and $isPullAuthor $isOpen $isLastRound }}
-
{{ $disabled := "" }}
-
{{ if $isUpToDate }}
-
{{ $disabled = "disabled" }}
-
{{ end }}
-
<button
-
id="resubmitBtn"
-
{{ if not .Pull.IsPatchBased }}
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
-
{{ else }}
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
-
hx-target="#actions-{{ $roundNumber }}" hx-swap="outerHtml"
+
{{ if and $isPullAuthor $isOpen $isLastRound }}
+
{{ $disabled := "" }}
+
{{ if $isUpToDate }}
+
{{ $disabled = "disabled" }}
{{ end }}
+
<button id="resubmitBtn"
+
{{ if not .Pull.IsPatchBased }}
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
+
{{ else }}
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
+
hx-target="#actions-{{$roundNumber}}"
+
hx-swap="outerHtml"
+
{{ end }}
-
hx-disabled-elt="#resubmitBtn"
-
class="btn p-2 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed group"
-
{{ $disabled }}
+
hx-disabled-elt="#resubmitBtn"
+
class="btn p-2 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed group" {{ $disabled }}
-
{{ if $disabled }}
-
title="Update this branch to resubmit this pull request"
-
{{ else }}
-
title="Resubmit this pull request"
-
{{ end }}>
-
{{ i "rotate-ccw" "w-4 h-4" }}
-
<span>resubmit</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
-
{{ end }}
+
{{ if $disabled }}
+
title="Update this branch to resubmit this pull request"
+
{{ else }}
+
title="Resubmit this pull request"
+
{{ end }}
+
>
+
{{ i "rotate-ccw" "w-4 h-4" }}
+
<span>resubmit</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
+
{{ end }}
-
{{ if and (or $isPullAuthor $isPushAllowed) $isOpen $isLastRound }}
-
<button
+
{{ if and (or $isPullAuthor $isPushAllowed) $isOpen $isLastRound }}
+
<button
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/close"
hx-swap="none"
class="btn p-2 flex items-center gap-2 group">
-
{{ i "ban" "w-4 h-4" }}
-
<span>close</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
{{ i "ban" "w-4 h-4" }}
+
<span>close</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
-
{{ end }}
+
{{ end }}
-
{{ if and (or $isPullAuthor $isPushAllowed) $isClosed $isLastRound }}
-
<button
+
{{ if and (or $isPullAuthor $isPushAllowed) $isClosed $isLastRound }}
+
<button
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/reopen"
hx-swap="none"
class="btn p-2 flex items-center gap-2 group">
-
{{ i "refresh-ccw-dot" "w-4 h-4" }}
-
<span>reopen</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
{{ i "refresh-ccw-dot" "w-4 h-4" }}
+
<span>reopen</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
-
{{ end }}
+
{{ end }}
</div>
</div>
{{ end }}
+
+
+39 -42
appview/pages/templates/repo/pulls/fragments/pullCompareBranches.html
···
{{ define "repo/pulls/fragments/pullCompareBranches" }}
-
<div id="patch-upload">
-
<label for="targetBranch" class="dark:text-white">
-
select a source branch
-
</label>
-
<div class="flex flex-wrap gap-2 items-center">
-
<select
-
name="sourceBranch"
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600">
-
<option disabled selected>source branch</option>
+
<div id="patch-upload">
+
<label for="targetBranch" class="dark:text-white">select a source branch</label>
+
<div class="flex flex-wrap gap-2 items-center">
+
<select
+
name="sourceBranch"
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
>
+
<option disabled selected>source branch</option>
-
{{ $recent := index .Branches 0 }}
-
{{ range .Branches }}
-
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
-
{{ $preset := false }}
-
{{ if $.SourceBranch }}
-
{{ $preset = eq .Reference.Name $.SourceBranch }}
-
{{ else }}
-
{{ $preset = $isRecent }}
-
{{ end }}
+
{{ $recent := index .Branches 0 }}
+
{{ range .Branches }}
+
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
+
{{ $preset := false }}
+
{{ if $.SourceBranch }}
+
{{ $preset = eq .Reference.Name $.SourceBranch }}
+
{{ else }}
+
{{ $preset = $isRecent }}
+
{{ end }}
+
+
<option
+
value="{{ .Reference.Name }}"
+
{{ if $preset }}
+
selected
+
{{ end }}
+
class="py-1"
+
>
+
{{ .Reference.Name }}
+
{{ if $isRecent }}(new){{ end }}
+
</option>
+
{{ end }}
+
</select>
+
</div>
+
</div>
-
-
<option
-
value="{{ .Reference.Name }}"
-
{{ if $preset }}
-
selected
-
{{ end }}
-
class="py-1">
-
{{ .Reference.Name }}
-
{{ if $isRecent }}(new){{ end }}
-
</option>
-
{{ end }}
-
</select>
+
<div class="flex items-center gap-2">
+
<input type="checkbox" id="isStacked" name="isStacked" value="on">
+
<label for="isStacked" class="my-0 py-0 normal-case font-normal">Submit as stacked PRs</label>
</div>
-
</div>
-
<div class="flex items-center gap-2">
-
<input type="checkbox" id="isStacked" name="isStacked" value="on" />
-
<label for="isStacked" class="my-0 py-0 normal-case font-normal">
-
Submit as stacked PRs
-
</label>
-
</div>
-
-
<p class="mt-4">
-
Title and description are optional; if left out, they will be extracted from
-
the first commit.
-
</p>
+
<p class="mt-4">
+
Title and description are optional; if left out, they will be extracted
+
from the first commit.
+
</p>
{{ end }}
+45 -45
appview/pages/templates/repo/pulls/fragments/pullCompareForks.html
···
{{ define "repo/pulls/fragments/pullCompareForks" }}
-
<div id="patch-upload">
-
<label for="forkSelect" class="dark:text-white">
-
select a fork to compare
-
</label>
-
selected:
-
{{ .Selected }}
-
<div class="flex flex-wrap gap-4 items-center">
-
<div class="flex flex-wrap gap-2 items-center">
-
<select
-
id="forkSelect"
-
name="fork"
-
required
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
-
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
-
hx-target="#branch-selection"
-
hx-vals='{"fork": this.value}'
-
hx-swap="innerHTML"
-
onchange="document.getElementById('hiddenForkInput').value = this.value;">
-
<option disabled selected>select a fork</option>
-
{{ range .Forks }}
-
<option
-
value="{{ .Name }}"
-
{{ if eq .Name $.Selected }}selected{{ end }}
-
class="py-1">
-
{{ .Name }}
-
</option>
-
{{ end }}
-
</select>
+
<div id="patch-upload">
+
<label for="forkSelect" class="dark:text-white"
+
>select a fork to compare</label
+
>
+
selected: {{ .Selected }}
+
<div class="flex flex-wrap gap-4 items-center">
+
<div class="flex flex-wrap gap-2 items-center">
+
<select
+
id="forkSelect"
+
name="fork"
+
required
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
hx-get="/{{ $.RepoInfo.FullName }}/pulls/new/fork-branches"
+
hx-target="#branch-selection"
+
hx-vals='{"fork": this.value}'
+
hx-swap="innerHTML"
+
onchange="document.getElementById('hiddenForkInput').value = this.value;"
+
>
+
<option disabled selected>select a fork</option>
+
{{ range .Forks }}
+
<option value="{{ .Name }}" {{ if eq .Name $.Selected }}selected{{ end }} class="py-1">
+
{{ .Name }}
+
</option>
+
{{ end }}
+
</select>
-
<input type="hidden" id="hiddenForkInput" name="fork" value="" />
-
</div>
+
<input
+
type="hidden"
+
id="hiddenForkInput"
+
name="fork"
+
value=""
+
/>
+
</div>
-
<div id="branch-selection">
-
<div class="text-sm text-gray-500 dark:text-gray-400">
-
Select a fork first to view available branches
+
<div id="branch-selection">
+
<div class="text-sm text-gray-500 dark:text-gray-400">
+
Select a fork first to view available branches
+
</div>
+
</div>
</div>
-
</div>
</div>
-
</div>
-
<div class="flex items-center gap-2">
-
<input type="checkbox" id="isStacked" name="isStacked" value="on" />
-
<label for="isStacked" class="my-0 py-0 normal-case font-normal">
-
Submit as stacked PRs
-
</label>
-
</div>
+
<div class="flex items-center gap-2">
+
<input type="checkbox" id="isStacked" name="isStacked" value="on">
+
<label for="isStacked" class="my-0 py-0 normal-case font-normal">Submit as stacked PRs</label>
+
</div>
-
<p class="mt-4">
-
Title and description are optional; if left out, they will be extracted from
-
the first commit.
-
</p>
+
<p class="mt-4">
+
Title and description are optional; if left out, they will be extracted
+
from the first commit.
+
</p>
{{ end }}
+22 -20
appview/pages/templates/repo/pulls/fragments/pullCompareForksBranches.html
···
{{ define "repo/pulls/fragments/pullCompareForksBranches" }}
-
<div class="flex flex-wrap gap-2 items-center">
-
<select
-
name="sourceBranch"
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600">
-
<option disabled selected>source branch</option>
+
<div class="flex flex-wrap gap-2 items-center">
+
<select
+
name="sourceBranch"
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
>
+
<option disabled selected>source branch</option>
-
{{ $recent := index .SourceBranches 0 }}
-
{{ range .SourceBranches }}
-
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
-
<option
-
value="{{ .Reference.Name }}"
-
{{ if $isRecent }}
-
selected
-
{{ end }}
-
class="py-1">
-
{{ .Reference.Name }}
-
{{ if $isRecent }}(new){{ end }}
-
</option>
-
{{ end }}
-
</select>
-
</div>
+
{{ $recent := index .SourceBranches 0 }}
+
{{ range .SourceBranches }}
+
{{ $isRecent := eq .Reference.Name $recent.Reference.Name }}
+
<option
+
value="{{ .Reference.Name }}"
+
{{ if $isRecent }}
+
selected
+
{{ end }}
+
class="py-1"
+
>
+
{{ .Reference.Name }}
+
{{ if $isRecent }}(new){{ end }}
+
</option>
+
{{ end }}
+
</select>
+
</div>
{{ end }}
+59 -68
appview/pages/templates/repo/pulls/fragments/pullHeader.html
···
{{ define "repo/pulls/fragments/pullHeader" }}
-
<header class="pb-4">
+
<header class="pb-4">
<h1 class="text-2xl dark:text-white">
-
{{ .Pull.Title }}
-
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
+
{{ .Pull.Title }}
+
<span class="text-gray-500 dark:text-gray-400">#{{ .Pull.PullId }}</span>
</h1>
-
</header>
+
</header>
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
-
{{ $icon := "ban" }}
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
+
{{ $icon := "ban" }}
-
{{ if .Pull.State.IsOpen }}
+
{{ if .Pull.State.IsOpen }}
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
{{ $icon = "git-pull-request" }}
-
{{ else if .Pull.State.IsMerged }}
+
{{ else if .Pull.State.IsMerged }}
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
{{ $icon = "git-merge" }}
-
{{ end }}
+
{{ end }}
-
{{ $owner := resolve .Pull.OwnerDid }}
-
<section class="mt-2">
+
{{ $owner := resolve .Pull.OwnerDid }}
+
<section class="mt-2">
<div class="flex items-center gap-2">
-
<div
-
id="state"
-
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}">
-
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
-
<span class="text-white">{{ .Pull.State.String }}</span>
-
</div>
-
<span
-
class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
-
opened by
-
{{ template "user/fragments/picHandleLink" .Pull.OwnerDid }}
-
<span class="select-none before:content-['\00B7']"></span>
-
{{ template "repo/fragments/time" .Pull.Created }}
+
<div
+
id="state"
+
class="inline-flex items-center rounded px-3 py-1 {{ $bgColor }}"
+
>
+
{{ i $icon "w-4 h-4 mr-1.5 text-white" }}
+
<span class="text-white">{{ .Pull.State.String }}</span>
+
</div>
+
<span class="text-gray-500 dark:text-gray-400 text-sm flex flex-wrap items-center gap-1">
+
opened by
+
{{ template "user/fragments/picHandleLink" .Pull.OwnerDid }}
+
<span class="select-none before:content-['\00B7']"></span>
+
{{ template "repo/fragments/time" .Pull.Created }}
-
-
<span class="select-none before:content-['\00B7']"></span>
-
<span>
-
targeting
-
<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">
-
<a
-
href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}"
-
class="no-underline hover:underline">
-
{{ .Pull.TargetBranch }}
-
</a>
-
</span>
+
<span class="select-none before:content-['\00B7']"></span>
+
<span>
+
targeting
+
<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">
+
<a href="/{{ .RepoInfo.FullName }}/tree/{{ .Pull.TargetBranch }}" class="no-underline hover:underline">{{ .Pull.TargetBranch }}</a>
+
</span>
+
</span>
+
{{ if not .Pull.IsPatchBased }}
+
from
+
<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">
+
{{ if .Pull.IsForkBased }}
+
{{ if .Pull.PullSource.Repo }}
+
<a href="/{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}" class="no-underline hover:underline">{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}</a>:
+
{{- else -}}
+
<span class="italic">[deleted fork]</span>
+
{{- end -}}
+
{{- end -}}
+
{{- .Pull.PullSource.Branch -}}
+
</span>
+
{{ end }}
</span>
-
{{ if not .Pull.IsPatchBased }}
-
from
-
<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">
-
{{ if .Pull.IsForkBased }}
-
{{ if .Pull.PullSource.Repo }}
-
<a
-
href="/{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}"
-
class="no-underline hover:underline">
-
{{ $owner }}/{{ .Pull.PullSource.Repo.Name }}
-
</a>
-
:
-
{{- else -}}
-
<span class="italic">[deleted fork]</span>
-
{{- end -}}
-
{{- end -}}
-
{{- .Pull.PullSource.Branch -}}
-
</span>
-
{{ end }}
-
</span>
</div>
{{ if .Pull.Body }}
-
<article id="body" class="mt-8 prose dark:prose-invert">
-
{{ .Pull.Body | markdown }}
-
</article>
+
<article id="body" class="mt-8 prose dark:prose-invert">
+
{{ .Pull.Body | markdown }}
+
</article>
{{ end }}
{{ with .OrderedReactionKinds }}
-
<div class="flex items-center gap-2 mt-2">
+
<div class="flex items-center gap-2 mt-2">
{{ template "repo/fragments/reactionsPopUp" . }}
{{ range $kind := . }}
-
{{ template "repo/fragments/reaction"
-
(dict
-
"Kind" $kind
-
"Count" (index $.Reactions $kind)
-
"IsReacted" (index $.UserReacted $kind)
-
"ThreadAt" $.Pull.PullAt)
-
}}
+
{{
+
template "repo/fragments/reaction"
+
(dict
+
"Kind" $kind
+
"Count" (index $.Reactions $kind)
+
"IsReacted" (index $.UserReacted $kind)
+
"ThreadAt" $.Pull.PullAt)
+
}}
{{ end }}
-
</div>
+
</div>
{{ end }}
-
</section>
+
</section>
+
+
{{ end }}
+31 -28
appview/pages/templates/repo/pulls/fragments/pullNewComment.html
···
{{ define "repo/pulls/fragments/pullNewComment" }}
-
<div
-
id="pull-comment-card-{{ .RoundNumber }}"
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm p-4 relative w-full flex flex-col gap-2">
-
<div class="text-sm text-gray-500 dark:text-gray-400">
-
{{ didOrHandle .LoggedInUser.Did .LoggedInUser.Handle }}
-
</div>
-
<form
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/comment"
-
hx-indicator="#create-comment-spinner"
-
hx-swap="none"
-
class="w-full flex flex-wrap gap-2">
-
<textarea
+
<div
+
id="pull-comment-card-{{ .RoundNumber }}"
+
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm p-4 relative w-full flex flex-col gap-2">
+
<div class="text-sm text-gray-500 dark:text-gray-400">
+
{{ didOrHandle .LoggedInUser.Did .LoggedInUser.Handle }}
+
</div>
+
<form
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/comment"
+
hx-indicator="#create-comment-spinner"
+
hx-swap="none"
+
class="w-full flex flex-wrap gap-2"
+
>
+
<textarea
name="body"
class="w-full p-2 rounded border border-gray-200"
-
placeholder="Add to the discussion..."></textarea>
-
<button type="submit" class="btn flex items-center gap-2">
+
placeholder="Add to the discussion..."></textarea
+
>
+
<button type="submit" class="btn flex items-center gap-2">
{{ i "message-square" "w-4 h-4" }}
<span>comment</span>
<span id="create-comment-spinner" class="group">
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</span>
-
</button>
-
<button
-
type="button"
-
class="btn flex items-center gap-2 group"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/actions"
-
hx-swap="outerHTML"
-
hx-target="#pull-comment-card-{{ .RoundNumber }}">
-
{{ i "x" "w-4 h-4" }}
-
<span>cancel</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
-
<div id="pull-comment"></div>
-
</form>
-
</div>
+
</button>
+
<button
+
type="button"
+
class="btn flex items-center gap-2 group"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .RoundNumber }}/actions"
+
hx-swap="outerHTML"
+
hx-target="#pull-comment-card-{{ .RoundNumber }}"
+
>
+
{{ i "x" "w-4 h-4" }}
+
<span>cancel</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
+
<div id="pull-comment"></div>
+
</form>
+
</div>
{{ end }}
+17 -19
appview/pages/templates/repo/pulls/fragments/pullPatchUpload.html
···
{{ define "repo/pulls/fragments/pullPatchUpload" }}
-
<div id="patch-upload">
-
<p>
-
You can paste a
-
<code>git diff</code>
-
or a
-
<code>git format-patch</code>
-
patch series here.
-
</p>
-
<textarea
-
hx-trigger="keyup changed delay:500ms, paste delay:500ms"
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/new/validate-patch"
-
hx-swap="none"
-
name="patch"
-
id="patch"
-
rows="12"
-
class="w-full mt-2 resize-y font-mono dark:bg-gray-700 dark:text-white dark:border-gray-600"
-
placeholder="diff --git a/file.txt b/file.txt
+
<div id="patch-upload">
+
<p>
+
You can paste a <code>git diff</code> or a
+
<code>git format-patch</code> patch series here.
+
</p>
+
<textarea
+
hx-trigger="keyup changed delay:500ms, paste delay:500ms"
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/new/validate-patch"
+
hx-swap="none"
+
name="patch"
+
id="patch"
+
rows="12"
+
class="w-full mt-2 resize-y font-mono dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
placeholder="diff --git a/file.txt b/file.txt
index 1234567..abcdefg 100644
--- a/file.txt
-
+++ b/file.txt"></textarea>
-
</div>
+
+++ b/file.txt"
+
></textarea>
+
</div>
{{ end }}
+57 -53
appview/pages/templates/repo/pulls/fragments/pullResubmit.html
···
{{ define "repo/pulls/fragments/pullResubmit" }}
<div
-
id="resubmit-pull-card"
-
class="rounded relative border bg-amber-50 dark:bg-amber-900 border-amber-200 dark:border-amber-500 px-6 py-2">
-
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-50">
-
{{ i "pencil" "w-4 h-4" }}
-
<span class="font-medium">resubmit your patch</span>
-
</div>
+
id="resubmit-pull-card"
+
class="rounded relative border bg-amber-50 dark:bg-amber-900 border-amber-200 dark:border-amber-500 px-6 py-2">
-
<div class="mt-2 text-sm text-gray-700 dark:text-gray-200">
-
You can update this patch to address any reviews. This will begin a new
-
round of reviews, but you'll still be able to view your previous
-
submissions and feedback.
-
</div>
+
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-50">
+
{{ i "pencil" "w-4 h-4" }}
+
<span class="font-medium">resubmit your patch</span>
+
</div>
-
<div class="mt-4 flex flex-col">
-
<form
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
-
hx-swap="none"
-
class="w-full flex flex-wrap gap-2"
-
hx-indicator="#resubmit-spinner">
-
<textarea
-
name="patch"
-
class="w-full p-2 mb-2"
-
placeholder="Paste your updated patch here."
-
rows="15">
-
{{ .Pull.LatestPatch }}
-
</textarea
+
<div class="mt-2 text-sm text-gray-700 dark:text-gray-200">
+
You can update this patch to address any reviews.
+
This will begin a new round of reviews,
+
but you'll still be able to view your previous submissions and feedback.
+
</div>
+
+
<div class="mt-4 flex flex-col">
+
<form
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/resubmit"
+
hx-swap="none"
+
class="w-full flex flex-wrap gap-2"
+
hx-indicator="#resubmit-spinner"
>
-
<button
-
type="submit"
-
class="btn flex items-center gap-2"
-
{{ if or .Pull.State.IsClosed }}
-
disabled
-
{{ end }}>
-
{{ i "rotate-ccw" "w-4 h-4" }}
-
<span>resubmit</span>
-
<span id="resubmit-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
<button
-
type="button"
-
class="btn flex items-center gap-2"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Pull.LastRoundNumber }}/actions"
-
hx-swap="outerHTML"
-
hx-target="#resubmit-pull-card"
-
hx-indicator="#cancel-resubmit-spinner">
-
{{ i "x" "w-4 h-4" }}
-
<span>cancel</span>
-
<span id="cancel-resubmit-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</form>
+
<textarea
+
name="patch"
+
class="w-full p-2 mb-2"
+
placeholder="Paste your updated patch here."
+
rows="15"
+
>
+
{{.Pull.LatestPatch}}
+
</textarea>
+
<button
+
type="submit"
+
class="btn flex items-center gap-2"
+
{{ if or .Pull.State.IsClosed }}
+
disabled
+
{{ end }}
+
>
+
{{ i "rotate-ccw" "w-4 h-4" }}
+
<span>resubmit</span>
+
<span id="resubmit-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
<button
+
type="button"
+
class="btn flex items-center gap-2"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Pull.LastRoundNumber }}/actions"
+
hx-swap="outerHTML"
+
hx-target="#resubmit-pull-card"
+
hx-indicator="#cancel-resubmit-spinner"
+
>
+
{{ i "x" "w-4 h-4" }}
+
<span>cancel</span>
+
<span id="cancel-resubmit-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</form>
-
<div id="resubmit-error" class="error"></div>
-
<div id="resubmit-success" class="success"></div>
-
</div>
+
<div id="resubmit-error" class="error"></div>
+
<div id="resubmit-success" class="success"></div>
+
</div>
</div>
{{ end }}
+10 -27
appview/pages/templates/repo/pulls/fragments/pullStack.html
···
{{ define "repo/pulls/fragments/pullStack" }}
<details class="bg-white dark:bg-gray-800 group" open>
-
<summary
-
class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
+
<summary class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
<span class="flex items-center gap-2">
<span class="group-open:hidden">
{{ i "chevrons-up-down" "w-4 h-4" }}
···
{{ i "chevrons-down-up" "w-4 h-4" }}
</span>
STACK
-
<span
-
class="bg-gray-200 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">
-
{{ len .Stack }}
-
</span>
+
<span class="bg-gray-200 dark:bg-gray-700 font-normal rounded py-1/2 px-1 text-sm">{{ len .Stack }}</span>
</span>
</summary>
-
{{ block "pullList" (list .Stack $) }}{{ end }}
+
{{ block "pullList" (list .Stack $) }} {{ end }}
</details>
{{ if gt (len .AbandonedPulls) 0 }}
<details class="mt-4 bg-white dark:bg-gray-800 group" open>
-
<summary
-
class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
+
<summary class="p-2 text-sm font-bold list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
<span class="flex items-center gap-2">
<span class="group-open:hidden">
{{ i "chevrons-up-down" "w-4 h-4" }}
···
{{ i "chevrons-down-up" "w-4 h-4" }}
</span>
ABANDONED PULLS
-
<span
-
class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm ml-1">
-
{{ len .AbandonedPulls }}
-
</span>
+
<span class="bg-gray-200 dark:bg-gray-700 rounded py-1/2 px-1 text-sm ml-1">{{ len .AbandonedPulls }}</span>
</span>
</summary>
-
{{ block "pullList" (list .AbandonedPulls $) }}{{ end }}
+
{{ block "pullList" (list .AbandonedPulls $) }} {{ end }}
</details>
{{ end }}
{{ end }}
···
{{ define "pullList" }}
{{ $list := index . 0 }}
{{ $root := index . 1 }}
-
<div
-
class="grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
+
<div class="grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
{{ range $pull := $list }}
{{ $isCurrent := false }}
{{ $pipeline := index $root.Pipelines $pull.LatestSha }}
{{ with $root.Pull }}
{{ $isCurrent = eq $pull.PullId $root.Pull.PullId }}
{{ end }}
-
<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">
-
<div
-
class="flex gap-2 items-center px-2 {{ if $isCurrent }}
-
bg-gray-100/50 dark:bg-gray-700/50
-
{{ end }}">
+
<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">
+
<div class="flex gap-2 items-center px-2 {{ if $isCurrent }}bg-gray-100/50 dark:bg-gray-700/50{{ end }}">
{{ if $isCurrent }}
<div class="flex-shrink-0">
{{ i "arrow-right" "w-4 h-4" }}
</div>
{{ end }}
-
<div
-
class="{{ if not $isCurrent }}
-
pl-6
-
{{ end }} flex-grow min-w-0 w-full py-2">
+
<div class="{{ if not $isCurrent }} pl-6 {{ end }} flex-grow min-w-0 w-full py-2">
{{ template "repo/pulls/fragments/summarizedHeader" (list $pull $pipeline) }}
</div>
</div>
+4 -7
appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html
···
{{ $commentCount := len $lastSubmission.Comments }}
{{ if and $pipeline $pipeline.Id }}
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
-
<span
-
class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
+
<span class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
{{ end }}
<span>
<div class="inline-flex items-center gap-1">
{{ i "message-square" "w-3 h-3 md:hidden" }}
{{ $commentCount }}
-
<span class="hidden md:inline">
-
comment{{ if ne $commentCount 1 }}s{{ end }}
-
</span>
+
<span class="hidden md:inline">comment{{if ne $commentCount 1}}s{{end}}</span>
</div>
</span>
-
<span
-
class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
+
<span class="before:content-['·'] before:select-none text-gray-500 dark:text-gray-400"></span>
<span>
<span class="hidden md:inline">round</span>
<span class="font-mono">#{{ $latestRound }}</span>
···
</div>
{{ end }}
{{ end }}
+
+1
appview/pages/templates/repo/pulls/fragments/summarizedPullState.html
···
{{ i $icon $style }}
{{ end }}
+
+20 -23
appview/pages/templates/repo/pulls/interdiff.html
···
{{ define "title" }}
-
interdiff of round #{{ .Round }} and #{{ sub .Round 1 }} &middot; pull
-
#{{ .Pull.PullId }} &middot;
-
{{ .RepoInfo.FullName }}
+
interdiff of round #{{ .Round }} and #{{ sub .Round 1 }} &middot; pull #{{ .Pull.PullId }} &middot; {{ .RepoInfo.FullName }}
{{ end }}
+
{{ define "extrameta" }}
-
{{ $title := printf "interdiff of %d and %d &middot; %s &middot; pull #%d &middot; %s" .Round (sub .Round 1) .Pull.Title .Pull.PullId .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
-
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" (unescapeHtml $title) "Url" $url) }}
+
{{ $title := printf "interdiff of %d and %d &middot; %s &middot; pull #%d &middot; %s" .Round (sub .Round 1) .Pull.Title .Pull.PullId .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
+
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" (unescapeHtml $title) "Url" $url) }}
{{ end }}
{{ define "content" }}
-
<section
-
class="rounded drop-shadow-sm bg-white dark:bg-gray-800 py-4 px-6 dark:text-white">
+
<section class="rounded drop-shadow-sm bg-white dark:bg-gray-800 py-4 px-6 dark:text-white">
<header class="pb-2">
<div class="flex gap-3 items-center mb-3">
-
<a
-
href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/"
-
class="flex items-center gap-2 font-medium">
+
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/" class="flex items-center gap-2 font-medium">
{{ i "arrow-left" "w-5 h-5" }}
back
</a>
<span class="select-none before:content-['\00B7']"></span>
-
interdiff of round #{{ .Round }} and
-
#{{ sub .Round 1 }}
+
interdiff of round #{{ .Round }} and #{{ sub .Round 1 }}
</div>
<div class="border-t border-gray-200 dark:border-gray-700 my-2"></div>
{{ template "repo/pulls/fragments/pullHeader" . }}
</header>
</section>
+
{{ end }}
{{ define "topbarLayout" }}
···
{{ end }}
{{ block "contentAfterLayout" . }}
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
-
{{ block "contentAfterLeft" . }}{{ end }}
-
</div>
-
<main class="col-span-1 md:col-span-10">
-
{{ block "contentAfter" . }}{{ end }}
-
</main>
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
+
{{ block "contentAfterLeft" . }} {{ end }}
</div>
+
<main class="col-span-1 md:col-span-10">
+
{{ block "contentAfter" . }}{{ end }}
+
</main>
+
</div>
{{ end }}
</div>
{{ end }}
···
</footer>
{{ end }}
+
{{ define "contentAfter" }}
{{ template "repo/fragments/interdiff" (list .RepoInfo.FullName .Interdiff .DiffOpts) }}
-
{{ end }}
+
{{end}}
{{ define "contentAfterLeft" }}
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
<div class="sticky top-0 flex-grow max-h-screen">
{{ template "repo/fragments/interdiffFiles" .Interdiff }}
</div>
-
{{ end }}
+
{{end}}
+132 -122
appview/pages/templates/repo/pulls/new.html
···
{{ define "title" }}new pull &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "repoContent" }}
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
-
Create new pull request
-
</h2>
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
+
Create new pull request
+
</h2>
-
<form
-
hx-post="/{{ .RepoInfo.FullName }}/pulls/new"
-
hx-indicator="#create-pull-spinner"
-
hx-swap="none">
-
<div class="flex flex-col gap-6">
-
<div class="flex gap-2 items-center">
-
<p>First, choose a target branch on {{ .RepoInfo.FullName }}:</p>
-
<div>
-
<select
-
required
-
name="targetBranch"
-
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600">
-
<option disabled selected>target branch</option>
+
<form
+
hx-post="/{{ .RepoInfo.FullName }}/pulls/new"
+
hx-indicator="#create-pull-spinner"
+
hx-swap="none"
+
>
+
<div class="flex flex-col gap-6">
+
<div class="flex gap-2 items-center">
+
<p>First, choose a target branch on {{ .RepoInfo.FullName }}:</p>
+
<div>
+
<select
+
required
+
name="targetBranch"
+
class="p-1 border border-gray-200 bg-white dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
>
+
<option disabled selected>target branch</option>
-
{{ range .Branches }}
-
{{ $preset := false }}
-
{{ if $.TargetBranch }}
-
{{ $preset = eq .Reference.Name $.TargetBranch }}
-
{{ else }}
-
{{ $preset = .IsDefault }}
-
{{ end }}
+
{{ range .Branches }}
-
<option
-
value="{{ .Reference.Name }}"
-
class="py-1"
-
{{ if $preset }}selected{{ end }}>
-
{{ .Reference.Name }}
-
</option>
-
{{ end }}
-
</select>
-
</div>
-
</div>
+
{{ $preset := false }}
+
{{ if $.TargetBranch }}
+
{{ $preset = eq .Reference.Name $.TargetBranch }}
+
{{ else }}
+
{{ $preset = .IsDefault }}
+
{{ end }}
+
+
<option value="{{ .Reference.Name }}" class="py-1" {{if $preset}}selected{{end}}>
+
{{ .Reference.Name }}
+
</option>
+
{{ end }}
+
</select>
+
</div>
+
</div>
-
<div class="flex flex-col gap-2">
-
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
-
Choose pull strategy
-
</h2>
-
<nav class="flex space-x-4 items-center">
-
<button
-
type="button"
-
class="btn"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/patch-upload"
-
hx-target="#patch-strategy"
-
hx-swap="innerHTML">
-
paste patch
-
</button>
+
<div class="flex flex-col gap-2">
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
+
Choose pull strategy
+
</h2>
+
<nav class="flex space-x-4 items-center">
+
<button
+
type="button"
+
class="btn"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/patch-upload"
+
hx-target="#patch-strategy"
+
hx-swap="innerHTML"
+
>
+
paste patch
+
</button>
-
{{ if .RepoInfo.Roles.IsPushAllowed }}
-
<span class="text-sm text-gray-500 dark:text-gray-400">or</span>
-
<button
-
type="button"
-
class="btn"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-branches"
-
hx-target="#patch-strategy"
-
hx-swap="innerHTML">
-
compare branches
-
</button>
-
{{ end }}
+
{{ if .RepoInfo.Roles.IsPushAllowed }}
+
<span class="text-sm text-gray-500 dark:text-gray-400">
+
or
+
</span>
+
<button
+
type="button"
+
class="btn"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-branches"
+
hx-target="#patch-strategy"
+
hx-swap="innerHTML"
+
>
+
compare branches
+
</button>
+
{{ end }}
-
<span class="text-sm text-gray-500 dark:text-gray-400">or</span>
-
<script>
-
function getQueryParams() {
-
return Object.fromEntries(
-
new URLSearchParams(window.location.search),
-
);
-
}
-
</script>
-
<!--
+
<span class="text-sm text-gray-500 dark:text-gray-400">
+
or
+
</span>
+
<script>
+
function getQueryParams() {
+
return Object.fromEntries(new URLSearchParams(window.location.search));
+
}
+
</script>
+
<!--
since compare-forks need the server to load forks, we
hx-get this button; unlike simply loading the pullCompareForks template
as we do for the rest of the gang below. the hx-vals thing just populates
the query params so the forks page gets it.
-->
-
<button
-
type="button"
-
class="btn"
-
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-forks"
-
hx-target="#patch-strategy"
-
hx-swap="innerHTML"
-
{{ if eq .Strategy "fork" }}
-
hx-trigger="click, load" hx-vals='js:{...getQueryParams()}'
-
{{ end }}>
-
compare forks
-
</button>
-
</nav>
-
<section id="patch-strategy" class="flex flex-col gap-2">
-
{{ if eq .Strategy "patch" }}
-
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
-
{{ else if eq .Strategy "branch" }}
-
{{ template "repo/pulls/fragments/pullCompareBranches" . }}
-
{{ else }}
-
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
-
{{ end }}
-
</section>
+
<button
+
type="button"
+
class="btn"
+
hx-get="/{{ .RepoInfo.FullName }}/pulls/new/compare-forks"
+
hx-target="#patch-strategy"
+
hx-swap="innerHTML"
+
{{ if eq .Strategy "fork" }}
+
hx-trigger="click, load"
+
hx-vals='js:{...getQueryParams()}'
+
{{ end }}
+
>
+
compare forks
+
</button>
-
<div id="patch-error" class="error dark:text-red-300"></div>
-
</div>
-
<div>
-
<label for="title" class="dark:text-white">write a title</label>
+
</nav>
+
<section id="patch-strategy" class="flex flex-col gap-2">
+
{{ if eq .Strategy "patch" }}
+
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
+
{{ else if eq .Strategy "branch" }}
+
{{ template "repo/pulls/fragments/pullCompareBranches" . }}
+
{{ else }}
+
{{ template "repo/pulls/fragments/pullPatchUpload" . }}
+
{{ end }}
+
</section>
-
<input
-
type="text"
-
name="title"
-
id="title"
-
value="{{ .Title }}"
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600"
-
placeholder="One-line summary of your change." />
-
</div>
+
<div id="patch-error" class="error dark:text-red-300"></div>
+
</div>
+
+
<div>
+
<label for="title" class="dark:text-white">write a title</label>
+
+
<input
+
type="text"
+
name="title"
+
id="title"
+
value="{{ .Title }}"
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
placeholder="One-line summary of your change."
+
/>
+
</div>
-
<div>
-
<label for="body" class="dark:text-white">add a description</label>
+
<div>
+
<label for="body" class="dark:text-white"
+
>add a description</label
+
>
-
<textarea
-
name="body"
-
id="body"
-
rows="6"
-
class="w-full resize-y dark:bg-gray-700 dark:text-white dark:border-gray-600"
-
placeholder="Describe your change. Markdown is supported.">
-
{{ .Body }}</textarea
-
>
-
</div>
+
<textarea
+
name="body"
+
id="body"
+
rows="6"
+
class="w-full resize-y dark:bg-gray-700 dark:text-white dark:border-gray-600"
+
placeholder="Describe your change. Markdown is supported."
+
>{{ .Body }}</textarea>
+
</div>
-
<div class="flex justify-start items-center gap-2 mt-4">
-
<button type="submit" class="btn-create flex items-center gap-2">
-
{{ i "git-pull-request-create" "w-4 h-4" }}
-
create pull
-
<span id="create-pull-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</div>
-
</div>
-
<div id="pull" class="error dark:text-red-300"></div>
-
</form>
+
<div class="flex justify-start items-center gap-2 mt-4">
+
<button type="submit" class="btn-create flex items-center gap-2">
+
{{ i "git-pull-request-create" "w-4 h-4" }}
+
create pull
+
<span id="create-pull-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</div>
+
</div>
+
<div id="pull" class="error dark:text-red-300"></div>
+
</form>
{{ end }}
+34 -39
appview/pages/templates/repo/pulls/patch.html
···
{{ define "title" }}
-
patch of {{ .Pull.Title }} &middot; round #{{ .Round }} &middot; pull
-
#{{ .Pull.PullId }} &middot;
-
{{ .RepoInfo.FullName }}
+
patch of {{ .Pull.Title }} &middot; round #{{ .Round }} &middot; pull #{{ .Pull.PullId }} &middot; {{ .RepoInfo.FullName }}
{{ end }}
+
{{ define "extrameta" }}
-
{{ $title := printf "patch of %s &middot; pull #%d &middot; %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
+
{{ $title := printf "patch of %s &middot; pull #%d &middot; %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/pulls/%d/round/%d" .RepoInfo.FullName .Pull.PullId .Round }}
+
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ end }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
-
{{ end }}
{{ define "content" }}
-
<section>
+
<section>
<section
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
-
<div class="flex gap-3 items-center mb-3">
-
<a
-
href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/"
-
class="flex items-center gap-2 font-medium">
-
{{ i "arrow-left" "w-5 h-5" }}
-
back
-
</a>
-
<span class="select-none before:content-['\00B7']"></span>
-
round
-
<span class="flex items-center">
-
{{ i "hash" "w-4 h-4" }}{{ .Round }}
-
</span>
-
<span class="select-none before:content-['\00B7']"></span>
-
<a
-
href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Round }}.patch">
-
view raw
-
</a>
-
</div>
-
<div class="border-t border-gray-200 dark:border-gray-700 my-2"></div>
-
{{ template "repo/pulls/fragments/pullHeader" . }}
+
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"
+
>
+
<div class="flex gap-3 items-center mb-3">
+
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/" class="flex items-center gap-2 font-medium">
+
{{ i "arrow-left" "w-5 h-5" }}
+
back
+
</a>
+
<span class="select-none before:content-['\00B7']"></span>
+
round<span class="flex items-center">{{ i "hash" "w-4 h-4" }}{{ .Round }}</span>
+
<span class="select-none before:content-['\00B7']"></span>
+
<a href="/{{ .RepoInfo.FullName }}/pulls/{{ .Pull.PullId }}/round/{{ .Round }}.patch">
+
view raw
+
</a>
+
</div>
+
<div class="border-t border-gray-200 dark:border-gray-700 my-2"></div>
+
{{ template "repo/pulls/fragments/pullHeader" . }}
</section>
-
</section>
+
</section>
{{ end }}
{{ define "topbarLayout" }}
···
{{ end }}
{{ block "contentAfterLayout" . }}
-
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
-
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
-
{{ block "contentAfterLeft" . }}{{ end }}
-
</div>
-
<main class="col-span-1 md:col-span-10">
-
{{ block "contentAfter" . }}{{ end }}
-
</main>
+
<div class="flex-grow grid grid-cols-1 md:grid-cols-12 gap-4">
+
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
+
{{ block "contentAfterLeft" . }} {{ end }}
</div>
+
<main class="col-span-1 md:col-span-10">
+
{{ block "contentAfter" . }}{{ end }}
+
</main>
+
</div>
{{ end }}
</div>
{{ end }}
···
{{ define "contentAfter" }}
{{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }}
-
{{ end }}
+
{{end}}
{{ define "contentAfterLeft" }}
<div class="flex flex-col gap-4 col-span-1 md:col-span-2">
···
<div class="sticky top-0 flex-grow max-h-screen">
{{ template "repo/fragments/diffChangedFiles" .Diff }}
</div>
-
{{ end }}
+
{{end}}
+153 -204
appview/pages/templates/repo/pulls/pull.html
···
{{ define "title" }}
-
{{ .Pull.Title }} &middot; pull #{{ .Pull.PullId }} &middot;
-
{{ .RepoInfo.FullName }}
+
{{ .Pull.Title }} &middot; pull #{{ .Pull.PullId }} &middot; {{ .RepoInfo.FullName }}
{{ end }}
{{ define "extrameta" }}
-
{{ $title := printf "%s &middot; pull #%d &middot; %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/pulls/%d" .RepoInfo.FullName .Pull.PullId }}
+
{{ $title := printf "%s &middot; pull #%d &middot; %s" .Pull.Title .Pull.PullId .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/pulls/%d" .RepoInfo.FullName .Pull.PullId }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
+
{{ define "repoContent" }}
{{ template "repo/pulls/fragments/pullHeader" . }}
···
{{ end }}
{{ define "repoAfter" }}
-
<section id="submissions" class="mt-4">
-
<div class="flex flex-col gap-4">
-
{{ block "submissions" . }}{{ end }}
-
</div>
-
</section>
+
<section id="submissions" class="mt-4">
+
<div class="flex flex-col gap-4">
+
{{ block "submissions" . }} {{ end }}
+
</div>
+
</section>
-
<div id="pull-close"></div>
-
<div id="pull-reopen"></div>
+
<div id="pull-close"></div>
+
<div id="pull-reopen"></div>
{{ end }}
{{ define "submissions" }}
···
{{ $repoName := .RepoInfo.FullName }}
{{ range $idx, $item := .Pull.Submissions }}
{{ with $item }}
-
<details {{ if eq $idx $lastIdx }}open{{ end }}>
-
<summary
-
id="round-#{{ .RoundNumber }}"
-
class="list-none cursor-pointer">
+
<details {{ if eq $idx $lastIdx }}open{{ end }}>
+
<summary id="round-#{{ .RoundNumber }}" class="list-none cursor-pointer">
<div class="flex flex-wrap gap-2 items-center">
<!-- round number -->
-
<div
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-3 py-2 dark:text-white">
-
<span class="flex items-center">
-
{{ i "hash" "w-4 h-4" }}{{ .RoundNumber }}
-
</span>
+
<div class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-3 py-2 dark:text-white">
+
<span class="flex items-center">{{ i "hash" "w-4 h-4" }}{{ .RoundNumber }}</span>
</div>
<!-- round summary -->
-
<div
-
class="rounded drop-shadow-sm bg-white dark:bg-gray-800 p-2 text-gray-500 dark:text-gray-400">
+
<div class="rounded drop-shadow-sm bg-white dark:bg-gray-800 p-2 text-gray-500 dark:text-gray-400">
<span class="gap-1 flex items-center">
{{ $owner := resolve $.Pull.OwnerDid }}
{{ $re := "re" }}
{{ if eq .RoundNumber 0 }}
{{ $re = "" }}
{{ end }}
-
<span class="hidden md:inline">{{ $re }}submitted</span>
-
by
-
{{ template "user/fragments/picHandleLink" $.Pull.OwnerDid }}
+
<span class="hidden md:inline">{{$re}}submitted</span>
+
by {{ template "user/fragments/picHandleLink" $.Pull.OwnerDid }}
<span class="select-none before:content-['\00B7']"></span>
-
<a
-
class="text-gray-500 dark:text-gray-400 hover:text-gray-500"
-
href="#round-#{{ .RoundNumber }}">
-
{{ template "repo/fragments/shortTime" .Created }}
-
</a>
+
<a class="text-gray-500 dark:text-gray-400 hover:text-gray-500" href="#round-#{{ .RoundNumber }}">{{ template "repo/fragments/shortTime" .Created }}</a>
<span class="select-none before:content-['·']"></span>
{{ $s := "s" }}
{{ if eq (len .Comments) 1 }}
{{ $s = "" }}
{{ end }}
-
{{ len .Comments }}
-
comment{{ $s }}
+
{{ len .Comments }} comment{{$s}}
</span>
</div>
-
<a
-
class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
-
hx-boost="true"
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{ .RoundNumber }}">
+
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
+
hx-boost="true"
+
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}">
{{ i "file-diff" "w-4 h-4" }}
<span class="hidden md:inline">diff</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</a>
{{ if not (eq .RoundNumber 0) }}
-
<a
-
class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
-
hx-boost="true"
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{ .RoundNumber }}/interdiff">
-
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
-
<span class="hidden md:inline">interdiff</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</a>
-
<span id="interdiff-error-{{ .RoundNumber }}"></span>
+
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
+
hx-boost="true"
+
href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/round/{{.RoundNumber}}/interdiff">
+
{{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
+
<span class="hidden md:inline">interdiff</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</a>
+
<span id="interdiff-error-{{.RoundNumber}}"></span>
{{ end }}
</div>
</summary>
{{ if .IsFormatPatch }}
-
{{ $patches := .AsFormatPatch }}
-
{{ $round := .RoundNumber }}
-
<details
-
class="group py-2 md:ml-[3.5rem] text-gray-500 dark:text-gray-400 flex flex-col gap-2 relative text-sm">
-
<summary
-
class="py-1 list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
-
{{ $s := "s" }}
-
{{ if eq (len $patches) 1 }}
-
{{ $s = "" }}
-
{{ end }}
-
<div class="group-open:hidden flex items-center gap-2 ml-2">
-
{{ i "chevrons-up-down" "w-4 h-4" }} expand
-
{{ len $patches }}
-
commit{{ $s }}
-
</div>
-
<div class="hidden group-open:flex items-center gap-2 ml-2">
-
{{ i "chevrons-down-up" "w-4 h-4" }} hide
-
{{ len $patches }}
-
commit{{ $s }}
-
</div>
-
</summary>
-
{{ range $patches }}
-
<div
-
id="commit-{{ .SHA }}"
-
class="py-1 px-2 relative w-full md:max-w-3/5 md:w-fit flex flex-col">
-
<div class="flex items-center gap-2">
-
{{ i "git-commit-horizontal" "w-4 h-4" }}
-
<div class="text-sm text-gray-500 dark:text-gray-400">
-
<!-- attempt to resolve $fullRepo: this is possible only on non-deleted forks and branches -->
-
{{ $fullRepo := "" }}
-
{{ if and $.Pull.IsForkBased $.Pull.PullSource.Repo }}
-
{{ $fullRepo = printf "%s/%s" $owner $.Pull.PullSource.Repo.Name }}
-
{{ else if $.Pull.IsBranchBased }}
-
{{ $fullRepo = $.RepoInfo.FullName }}
-
{{ end }}
+
{{ $patches := .AsFormatPatch }}
+
{{ $round := .RoundNumber }}
+
<details class="group py-2 md:ml-[3.5rem] text-gray-500 dark:text-gray-400 flex flex-col gap-2 relative text-sm">
+
<summary class="py-1 list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
+
{{ $s := "s" }}
+
{{ if eq (len $patches) 1 }}
+
{{ $s = "" }}
+
{{ end }}
+
<div class="group-open:hidden flex items-center gap-2 ml-2">
+
{{ i "chevrons-up-down" "w-4 h-4" }} expand {{ len $patches }} commit{{$s}}
+
</div>
+
<div class="hidden group-open:flex items-center gap-2 ml-2">
+
{{ i "chevrons-down-up" "w-4 h-4" }} hide {{ len $patches }} commit{{$s}}
+
</div>
+
</summary>
+
{{ range $patches }}
+
<div id="commit-{{.SHA}}" class="py-1 px-2 relative w-full md:max-w-3/5 md:w-fit flex flex-col">
+
<div class="flex items-center gap-2">
+
{{ i "git-commit-horizontal" "w-4 h-4" }}
+
<div class="text-sm text-gray-500 dark:text-gray-400">
+
<!-- attempt to resolve $fullRepo: this is possible only on non-deleted forks and branches -->
+
{{ $fullRepo := "" }}
+
{{ if and $.Pull.IsForkBased $.Pull.PullSource.Repo }}
+
{{ $fullRepo = printf "%s/%s" $owner $.Pull.PullSource.Repo.Name }}
+
{{ else if $.Pull.IsBranchBased }}
+
{{ $fullRepo = $.RepoInfo.FullName }}
+
{{ end }}
-
-
<!-- if $fullRepo was resolved, link to it, otherwise just span without a link -->
-
{{ if $fullRepo }}
-
<a
-
href="/{{ $fullRepo }}/commit/{{ .SHA }}"
-
class="font-mono text-gray-500 dark:text-gray-400">
-
{{ slice .SHA 0 8 }}
-
</a>
-
{{ else }}
-
<span class="font-mono">{{ slice .SHA 0 8 }}</span>
-
{{ end }}
-
</div>
-
<div class="flex items-center">
-
<span>{{ .Title }}</span>
-
{{ if gt (len .Body) 0 }}
-
<button
-
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"
-
hx-on:click="document.getElementById('body-{{ $round }}-{{ .SHA }}').classList.toggle('hidden')">
-
{{ i "ellipsis" "w-3 h-3" }}
-
</button>
-
{{ end }}
-
</div>
-
</div>
-
{{ if gt (len .Body) 0 }}
-
<p
-
id="body-{{ $round }}-{{ .SHA }}"
-
class="hidden mt-1 text-sm pb-2">
-
{{ nl2br .Body }}
-
</p>
-
{{ end }}
-
</div>
-
{{ end }}
-
</details>
+
<!-- if $fullRepo was resolved, link to it, otherwise just span without a link -->
+
{{ if $fullRepo }}
+
<a href="/{{ $fullRepo }}/commit/{{ .SHA }}" class="font-mono text-gray-500 dark:text-gray-400">{{ slice .SHA 0 8 }}</a>
+
{{ else }}
+
<span class="font-mono">{{ slice .SHA 0 8 }}</span>
+
{{ end }}
+
</div>
+
<div class="flex items-center">
+
<span>{{ .Title }}</span>
+
{{ if gt (len .Body) 0 }}
+
<button
+
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"
+
hx-on:click="document.getElementById('body-{{$round}}-{{.SHA}}').classList.toggle('hidden')"
+
>
+
{{ i "ellipsis" "w-3 h-3" }}
+
</button>
+
{{ end }}
+
</div>
+
</div>
+
{{ if gt (len .Body) 0 }}
+
<p id="body-{{$round}}-{{.SHA}}" class="hidden mt-1 text-sm pb-2">
+
{{ nl2br .Body }}
+
</p>
+
{{ end }}
+
</div>
+
{{ end }}
+
</details>
{{ end }}
<div class="md:pl-[3.5rem] flex flex-col gap-2 mt-2 relative">
{{ range $cidx, $c := .Comments }}
-
<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">
+
<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">
{{ if gt $cidx 0 }}
-
<div
-
class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
+
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
{{ end }}
-
<div
-
class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
+
<div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
{{ template "user/fragments/picHandleLink" $c.OwnerDid }}
<span class="before:content-['·']"></span>
-
<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>
+
<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>
</div>
<div class="prose dark:prose-invert">
{{ $c.Body | markdown }}
···
</div>
{{ end }}
-
{{ block "pipelineStatus" (list $ .) }}{{ end }}
+
{{ block "pipelineStatus" (list $ .) }} {{ end }}
{{ if eq $lastIdx .RoundNumber }}
-
{{ block "mergeStatus" $ }}{{ end }}
-
{{ block "resubmitStatus" $ }}{{ end }}
+
{{ block "mergeStatus" $ }} {{ end }}
+
{{ block "resubmitStatus" $ }} {{ end }}
{{ end }}
{{ if $.LoggedInUser }}
{{ template "repo/pulls/fragments/pullActions" (dict "LoggedInUser" $.LoggedInUser "Pull" $.Pull "RepoInfo" $.RepoInfo "RoundNumber" .RoundNumber "MergeCheck" $.MergeCheck "ResubmitCheck" $.ResubmitCheck "Stack" $.Stack) }}
{{ else }}
-
<div
-
class="bg-white dark:bg-gray-800 rounded drop-shadow-sm px-6 py-4 w-fit dark:text-white">
-
<div
-
class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
-
<a href="/login" class="underline">login</a>
-
to join the discussion
+
<div class="bg-white dark:bg-gray-800 rounded drop-shadow-sm px-6 py-4 w-fit dark:text-white">
+
<div class="absolute left-8 -top-2 w-px h-2 bg-gray-300 dark:bg-gray-600"></div>
+
<a href="/login" class="underline">login</a> to join the discussion
</div>
{{ end }}
</div>
-
</details>
+
</details>
{{ end }}
{{ end }}
{{ end }}
{{ define "mergeStatus" }}
{{ if .Pull.State.IsClosed }}
-
<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">
-
<div class="flex items-center gap-2 text-black dark:text-white">
-
{{ i "ban" "w-4 h-4" }}
-
<span class="font-medium">closed without merging</span>
-
</div>
+
<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">
+
<div class="flex items-center gap-2 text-black dark:text-white">
+
{{ i "ban" "w-4 h-4" }}
+
<span class="font-medium">closed without merging</span
+
>
</div>
+
</div>
{{ else if .Pull.State.IsMerged }}
-
<div
-
class="bg-purple-50 dark:bg-purple-900 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
-
<div class="flex items-center gap-2 text-purple-500 dark:text-purple-300">
-
{{ i "git-merge" "w-4 h-4" }}
-
<span class="font-medium">pull request successfully merged</span>
-
</div>
+
<div class="bg-purple-50 dark:bg-purple-900 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
+
<div class="flex items-center gap-2 text-purple-500 dark:text-purple-300">
+
{{ i "git-merge" "w-4 h-4" }}
+
<span class="font-medium">pull request successfully merged</span
+
>
</div>
+
</div>
{{ else if .Pull.State.IsDeleted }}
-
<div
-
class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
-
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
-
{{ i "git-pull-request-closed" "w-4 h-4" }}
-
<span class="font-medium">
-
This pull has been deleted (possibly by jj abandon or jj squash)
-
</span>
-
</div>
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
+
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
+
{{ i "git-pull-request-closed" "w-4 h-4" }}
+
<span class="font-medium">This pull has been deleted (possibly by jj abandon or jj squash)</span>
</div>
+
</div>
{{ else if and .MergeCheck .MergeCheck.Error }}
-
<div
-
class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="flex items-center gap-2 text-red-500 dark:text-red-300">
{{ i "triangle-alert" "w-4 h-4" }}
<span class="font-medium">{{ .MergeCheck.Error }}</span>
</div>
</div>
{{ else if and .MergeCheck .MergeCheck.IsConflicted }}
-
<div
-
class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
+
<div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
<div class="flex flex-col gap-2 text-red-500 dark:text-red-300">
<div class="flex items-center gap-2">
{{ i "triangle-alert" "w-4 h-4" }}
···
<ul class="space-y-1">
{{ range .MergeCheck.Conflicts }}
{{ if .Filename }}
-
<li class="flex items-center">
-
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
-
<span class="font-mono">{{ .Filename }}</span>
-
</li>
+
<li class="flex items-center">
+
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
+
<span class="font-mono">{{ .Filename }}</span>
+
</li>
{{ else if .Reason }}
-
<li class="flex items-center">
-
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
-
<span>{{ .Reason }}</span>
-
</li>
+
<li class="flex items-center">
+
{{ i "file-warning" "w-4 h-4 mr-1.5 text-red-500 dark:text-red-300" }}
+
<span>{{.Reason}}</span>
+
</li>
{{ end }}
{{ end }}
</ul>
···
</div>
</div>
{{ else if .MergeCheck }}
-
<div
-
class="bg-green-50 dark:bg-green-900 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
-
<div class="flex items-center gap-2 text-green-500 dark:text-green-300">
-
{{ i "circle-check-big" "w-4 h-4" }}
-
<span class="font-medium">no conflicts, ready to merge</span>
-
</div>
+
<div class="bg-green-50 dark:bg-green-900 border border-green-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
+
<div class="flex items-center gap-2 text-green-500 dark:text-green-300">
+
{{ i "circle-check-big" "w-4 h-4" }}
+
<span class="font-medium">no conflicts, ready to merge</span>
</div>
+
</div>
{{ end }}
{{ end }}
{{ define "resubmitStatus" }}
{{ if .ResubmitCheck.Yes }}
-
<div
-
class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
-
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
-
{{ i "triangle-alert" "w-4 h-4" }}
-
<span class="font-medium">
-
this branch has been updated, consider resubmitting
-
</span>
-
</div>
+
<div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative w-fit">
+
<div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
+
{{ i "triangle-alert" "w-4 h-4" }}
+
<span class="font-medium">this branch has been updated, consider resubmitting</span>
</div>
+
</div>
{{ end }}
{{ end }}
···
{{ with $pipeline }}
{{ $id := .Id }}
{{ if .Statuses }}
-
<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">
+
<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">
{{ range $name, $all := .Statuses }}
-
<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">
-
<div class="flex gap-2 items-center justify-between p-2">
-
{{ $lastStatus := $all.Latest }}
-
{{ $kind := $lastStatus.Status.String }}
+
<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">
+
<div
+
class="flex gap-2 items-center justify-between p-2">
+
{{ $lastStatus := $all.Latest }}
+
{{ $kind := $lastStatus.Status.String }}
-
-
<div id="left" class="flex items-center gap-2 flex-shrink-0">
-
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
-
{{ $name }}
-
</div>
-
<div id="right" class="flex items-center gap-2 flex-shrink-0">
-
<span class="font-bold">{{ $kind }}</span>
-
{{ if .TimeTaken }}
-
{{ template "repo/fragments/duration" .TimeTaken }}
-
{{ else }}
-
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
-
{{ end }}
-
</div>
+
<div id="left" class="flex items-center gap-2 flex-shrink-0">
+
{{ template "repo/pipelines/fragments/workflowSymbol" $all }}
+
{{ $name }}
</div>
-
</a>
+
<div id="right" class="flex items-center gap-2 flex-shrink-0">
+
<span class="font-bold">{{ $kind }}</span>
+
{{ if .TimeTaken }}
+
{{ template "repo/fragments/duration" .TimeTaken }}
+
{{ else }}
+
{{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
+
{{ end }}
+
</div>
+
</div>
+
</a>
{{ end }}
</div>
{{ end }}
+113 -132
appview/pages/templates/repo/pulls/pulls.html
···
{{ define "title" }}pulls &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "extrameta" }}
-
{{ $title := "pulls" }}
-
{{ $url := printf "https://tangled.sh/%s/pulls" .RepoInfo.FullName }}
+
{{ $title := "pulls"}}
+
{{ $url := printf "https://tangled.sh/%s/pulls" .RepoInfo.FullName }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
{{ define "repoContent" }}
-
<div class="flex justify-between items-center">
-
<div class="flex gap-4">
-
<a
-
href="?state=open"
-
class="flex items-center gap-2 {{ if .FilteringBy.IsOpen }}
-
font-bold
-
{{ else }}
-
text-gray-500 dark:text-gray-400
-
{{ end }}">
-
{{ i "git-pull-request" "w-4 h-4" }}
-
<span>{{ .RepoInfo.Stats.PullCount.Open }} open</span>
-
</a>
-
<a
-
href="?state=merged"
-
class="flex items-center gap-2 {{ if .FilteringBy.IsMerged }}
-
font-bold
-
{{ else }}
-
text-gray-500 dark:text-gray-400
-
{{ end }}">
-
{{ i "git-merge" "w-4 h-4" }}
-
<span>{{ .RepoInfo.Stats.PullCount.Merged }} merged</span>
-
</a>
-
<a
-
href="?state=closed"
-
class="flex items-center gap-2 {{ if .FilteringBy.IsClosed }}
-
font-bold
-
{{ else }}
-
text-gray-500 dark:text-gray-400
-
{{ end }}">
-
{{ i "ban" "w-4 h-4" }}
-
<span>{{ .RepoInfo.Stats.PullCount.Closed }} closed</span>
-
</a>
+
<div class="flex justify-between items-center">
+
<div class="flex gap-4">
+
<a
+
href="?state=open"
+
class="flex items-center gap-2 {{ if .FilteringBy.IsOpen }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
+
>
+
{{ i "git-pull-request" "w-4 h-4" }}
+
<span>{{ .RepoInfo.Stats.PullCount.Open }} open</span>
+
</a>
+
<a
+
href="?state=merged"
+
class="flex items-center gap-2 {{ if .FilteringBy.IsMerged }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
+
>
+
{{ i "git-merge" "w-4 h-4" }}
+
<span>{{ .RepoInfo.Stats.PullCount.Merged }} merged</span>
+
</a>
+
<a
+
href="?state=closed"
+
class="flex items-center gap-2 {{ if .FilteringBy.IsClosed }}font-bold {{ else }}text-gray-500 dark:text-gray-400{{ end }}"
+
>
+
{{ i "ban" "w-4 h-4" }}
+
<span>{{ .RepoInfo.Stats.PullCount.Closed }} closed</span>
+
</a>
+
</div>
+
<a
+
href="/{{ .RepoInfo.FullName }}/pulls/new"
+
class="btn-create text-sm flex items-center gap-2 no-underline hover:no-underline hover:text-white"
+
>
+
{{ i "git-pull-request-create" "w-4 h-4" }}
+
<span>new</span>
+
</a>
</div>
-
<a
-
href="/{{ .RepoInfo.FullName }}/pulls/new"
-
class="btn-create text-sm flex items-center gap-2 no-underline hover:no-underline hover:text-white">
-
{{ i "git-pull-request-create" "w-4 h-4" }}
-
<span>new</span>
-
</a>
-
</div>
-
<div class="error" id="pulls"></div>
+
<div class="error" id="pulls"></div>
{{ end }}
{{ define "repoAfter" }}
-
<div class="flex flex-col gap-2 mt-2">
-
{{ range .Pulls }}
-
<div class="rounded bg-white dark:bg-gray-800">
-
<div class="px-6 py-4 z-5">
-
<div class="pb-2">
-
<a
-
href="/{{ $.RepoInfo.FullName }}/pulls/{{ .PullId }}"
-
class="dark:text-white">
-
{{ .Title }}
-
<span class="text-gray-500 dark:text-gray-400">
-
#{{ .PullId }}
-
</span>
-
</a>
-
</div>
-
<div
-
class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
-
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
-
{{ $icon := "ban" }}
+
<div class="flex flex-col gap-2 mt-2">
+
{{ range .Pulls }}
+
<div class="rounded bg-white dark:bg-gray-800">
+
<div class="px-6 py-4 z-5">
+
<div class="pb-2">
+
<a href="/{{ $.RepoInfo.FullName }}/pulls/{{ .PullId }}" class="dark:text-white">
+
{{ .Title }}
+
<span class="text-gray-500 dark:text-gray-400">#{{ .PullId }}</span>
+
</a>
+
</div>
+
<div class="text-sm text-gray-500 dark:text-gray-400 flex flex-wrap items-center gap-1">
+
{{ $bgColor := "bg-gray-800 dark:bg-gray-700" }}
+
{{ $icon := "ban" }}
-
{{ if .State.IsOpen }}
-
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
-
{{ $icon = "git-pull-request" }}
-
{{ else if .State.IsMerged }}
-
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
-
{{ $icon = "git-merge" }}
-
{{ end }}
+
{{ if .State.IsOpen }}
+
{{ $bgColor = "bg-green-600 dark:bg-green-700" }}
+
{{ $icon = "git-pull-request" }}
+
{{ else if .State.IsMerged }}
+
{{ $bgColor = "bg-purple-600 dark:bg-purple-700" }}
+
{{ $icon = "git-merge" }}
+
{{ end }}
-
<span
-
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm">
-
{{ i $icon "w-3 h-3 mr-1.5 text-white" }}
-
<span class="text-white">{{ .State.String }}</span>
-
</span>
+
<span
+
class="inline-flex items-center rounded px-2 py-[5px] {{ $bgColor }} text-sm"
+
>
+
{{ i $icon "w-3 h-3 mr-1.5 text-white" }}
+
<span class="text-white">{{ .State.String }}</span>
+
</span>
-
<span class="ml-1">
-
{{ template "user/fragments/picHandleLink" .OwnerDid }}
-
</span>
+
<span class="ml-1">
+
{{ template "user/fragments/picHandleLink" .OwnerDid }}
+
</span>
-
<span class="before:content-['·']">
-
{{ template "repo/fragments/time" .Created }}
-
</span>
+
<span class="before:content-['·']">
+
{{ template "repo/fragments/time" .Created }}
+
</span>
-
{{ $latestRound := .LastRoundNumber }}
-
{{ $lastSubmission := index .Submissions $latestRound }}
+
{{ $latestRound := .LastRoundNumber }}
+
{{ $lastSubmission := index .Submissions $latestRound }}
-
<span class="before:content-['·']">
-
{{ $commentCount := len $lastSubmission.Comments }}
-
{{ $s := "s" }}
-
{{ if eq $commentCount 1 }}
-
{{ $s = "" }}
-
{{ end }}
+
<span class="before:content-['·']">
+
{{ $commentCount := len $lastSubmission.Comments }}
+
{{ $s := "s" }}
+
{{ if eq $commentCount 1 }}
+
{{ $s = "" }}
+
{{ end }}
-
{{ len $lastSubmission.Comments }}
-
comment{{ $s }}
-
</span>
+
{{ len $lastSubmission.Comments}} comment{{$s}}
+
</span>
-
<span class="before:content-['·']">
-
round
-
<span class="font-mono">
-
#{{ .LastRoundNumber }}
-
</span>
-
</span>
+
<span class="before:content-['·']">
+
round
+
<span class="font-mono">
+
#{{ .LastRoundNumber }}
+
</span>
+
</span>
-
{{ $pipeline := index $.Pipelines .LatestSha }}
-
{{ if and $pipeline $pipeline.Id }}
-
<span class="before:content-['·']"></span>
-
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
-
{{ end }}
-
</div>
-
</div>
-
{{ if .StackId }}
-
{{ $otherPulls := index $.Stacks .StackId }}
-
{{ if gt (len $otherPulls) 0 }}
-
<details class="bg-white dark:bg-gray-800 group">
-
<summary
-
class="pb-4 px-6 text-xs list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
-
{{ $s := "s" }}
-
{{ if eq (len $otherPulls) 1 }}
-
{{ $s = "" }}
+
{{ $pipeline := index $.Pipelines .LatestSha }}
+
{{ if and $pipeline $pipeline.Id }}
+
<span class="before:content-['·']"></span>
+
{{ template "repo/pipelines/fragments/pipelineSymbol" $pipeline }}
+
{{ end }}
+
</div>
+
</div>
+
{{ if .StackId }}
+
{{ $otherPulls := index $.Stacks .StackId }}
+
{{ if gt (len $otherPulls) 0 }}
+
<details class="bg-white dark:bg-gray-800 group">
+
<summary class="pb-4 px-6 text-xs list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
+
{{ $s := "s" }}
+
{{ if eq (len $otherPulls) 1 }}
+
{{ $s = "" }}
+
{{ end }}
+
<div class="group-open:hidden flex items-center gap-2">
+
{{ i "chevrons-up-down" "w-4 h-4" }} expand {{ len $otherPulls }} pull{{$s}} in this stack
+
</div>
+
<div class="hidden group-open:flex items-center gap-2">
+
{{ i "chevrons-down-up" "w-4 h-4" }} hide {{ len $otherPulls }} pull{{$s}} in this stack
+
</div>
+
</summary>
+
{{ block "pullList" (list $otherPulls $) }} {{ end }}
+
</details>
{{ end }}
-
<div class="group-open:hidden flex items-center gap-2">
-
{{ i "chevrons-up-down" "w-4 h-4" }} expand
-
{{ len $otherPulls }} pull{{ $s }} in this stack
-
</div>
-
<div class="hidden group-open:flex items-center gap-2">
-
{{ i "chevrons-down-up" "w-4 h-4" }} hide
-
{{ len $otherPulls }} pull{{ $s }} in this stack
-
</div>
-
</summary>
-
{{ block "pullList" (list $otherPulls $) }}{{ end }}
-
</details>
-
{{ end }}
+
{{ end }}
+
</div>
{{ end }}
-
</div>
-
{{ end }}
-
</div>
+
</div>
{{ end }}
{{ define "pullList" }}
{{ $list := index . 0 }}
{{ $root := index . 1 }}
-
<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">
+
<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">
{{ range $pull := $list }}
{{ $pipeline := index $root.Pipelines $pull.LatestSha }}
-
<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">
+
<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">
<div class="flex gap-2 items-center px-6">
<div class="flex-grow min-w-0 w-full py-2">
{{ template "repo/pulls/fragments/summarizedHeader" (list $pull $pipeline) }}
+39 -45
appview/pages/templates/repo/settings/access.html
···
-
{{ define "title" }}
-
{{ .Tab }} settings &middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title" }}{{ .Tab }} settings &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "repoContent" }}
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2">
···
<div class="col-span-1">
<h2 class="text-sm pb-2 uppercase font-bold">Collaborators</h2>
<p class="text-gray-500 dark:text-gray-400">
-
Any user added as a collaborator will be able to push commits and tags
-
to this repository, upload releases, and workflows.
+
Any user added as a collaborator will be able to push commits and tags to this repository, upload releases, and workflows.
</p>
</div>
{{ template "collaboratorsGrid" . }}
···
<img
src="{{ fullAvatar .Handle }}"
alt="{{ .Handle }}"
-
class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0" />
+
class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0"/>
<div class="flex-1 min-w-0">
<a href="/{{ .Handle }}" class="block truncate">
···
popovertarget="add-collaborator-modal"
popovertargetaction="toggle">
<div class="flex items-center gap-3">
-
<div
-
class="w-10 h-10 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center">
+
<div class="w-10 h-10 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center">
{{ i "user-plus" "size-4" }}
</div>
···
{{ end }}
{{ define "addCollaboratorModal" }}
-
<form
-
hx-put="/{{ $.RepoInfo.FullName }}/settings/collaborator"
-
hx-indicator="#spinner"
-
hx-swap="none"
-
class="flex flex-col gap-2">
-
<label for="add-collaborator" class="uppercase p-0">ADD COLLABORATOR</label>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
-
Collaborators can push to this repository.
-
</p>
-
<input
-
type="text"
-
id="add-collaborator"
-
name="collaborator"
-
required
-
placeholder="@foo.bsky.social" />
-
<div class="flex gap-2 pt-2">
-
<button
-
type="button"
-
popovertarget="add-collaborator-modal"
-
popovertargetaction="hide"
-
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">
-
{{ i "x" "size-4" }} cancel
-
</button>
-
<button type="submit" class="btn w-1/2 flex items-center">
-
<span class="inline-flex gap-2 items-center">
-
{{ i "user-plus" "size-4" }} add
-
</span>
-
<span id="spinner" class="group">
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</div>
-
<div
-
id="add-collaborator-error"
-
class="text-red-500 dark:text-red-400"></div>
-
</form>
+
<form
+
hx-put="/{{ $.RepoInfo.FullName }}/settings/collaborator"
+
hx-indicator="#spinner"
+
hx-swap="none"
+
class="flex flex-col gap-2"
+
>
+
<label for="add-collaborator" class="uppercase p-0">
+
ADD COLLABORATOR
+
</label>
+
<p class="text-sm text-gray-500 dark:text-gray-400">Collaborators can push to this repository.</p>
+
<input
+
type="text"
+
id="add-collaborator"
+
name="collaborator"
+
required
+
placeholder="@foo.bsky.social"
+
/>
+
<div class="flex gap-2 pt-2">
+
<button
+
type="button"
+
popovertarget="add-collaborator-modal"
+
popovertargetaction="hide"
+
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"
+
>
+
{{ i "x" "size-4" }} cancel
+
</button>
+
<button type="submit" class="btn w-1/2 flex items-center">
+
<span class="inline-flex gap-2 items-center">{{ i "user-plus" "size-4" }} add</span>
+
<span id="spinner" class="group">
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</div>
+
<div id="add-collaborator-error" class="text-red-500 dark:text-red-400"></div>
+
</form>
{{ end }}
+8 -15
appview/pages/templates/repo/settings/fragments/secretListing.html
···
{{ define "repo/settings/fragments/secretListing" }}
{{ $root := index . 0 }}
{{ $secret := index . 1 }}
-
<div
-
id="secret-{{ $secret.Key }}"
-
class="flex items-center justify-between p-2">
-
<div
-
class="hover:no-underline flex flex-col gap-1 text-sm min-w-0 max-w-[80%]">
+
<div id="secret-{{$secret.Key}}" class="flex items-center justify-between p-2">
+
<div class="hover:no-underline flex flex-col gap-1 text-sm min-w-0 max-w-[80%]">
<span class="font-mono">
{{ $secret.Key }}
</span>
-
<div
-
class="flex flex-wrap text items-center gap-1 text-gray-500 dark:text-gray-400">
+
<div class="flex flex-wrap text items-center gap-1 text-gray-500 dark:text-gray-400">
<span>added by</span>
-
<span>
-
{{ template "user/fragments/picHandleLink" $secret.CreatedBy }}
-
</span>
+
<span>{{ template "user/fragments/picHandleLink" $secret.CreatedBy }}</span>
<span class="before:content-['·'] before:select-none"></span>
-
<span>
-
{{ template "repo/fragments/shortTimeAgo" $secret.CreatedAt }}
-
</span>
+
<span>{{ template "repo/fragments/shortTimeAgo" $secret.CreatedAt }}</span>
</div>
</div>
<button
···
hx-delete="/{{ $root.RepoInfo.FullName }}/settings/secrets"
hx-swap="none"
hx-vals='{"key": "{{ $secret.Key }}"}'
-
hx-confirm="Are you sure you want to delete the secret {{ $secret.Key }}?">
+
hx-confirm="Are you sure you want to delete the secret {{ $secret.Key }}?"
+
>
{{ i "trash-2" "w-5 h-5" }}
-
<span class="hidden md:inline">delete</span>
+
<span class="hidden md:inline">delete</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
</div>
+7 -15
appview/pages/templates/repo/settings/fragments/sidebar.html
···
{{ define "repo/settings/fragments/sidebar" }}
{{ $active := .Tab }}
{{ $tabs := .Tabs }}
-
<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 shadow-inner">
+
<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 shadow-inner">
{{ $activeTab := "bg-white dark:bg-gray-700 drop-shadow-sm" }}
{{ $inactiveTab := "bg-gray-100 dark:bg-gray-800" }}
{{ range $tabs }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/settings?tab={{ .Name }}"
-
class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
-
<div
-
class="flex gap-3 items-center p-2 {{ if eq .Name $active }}
-
{{ $activeTab }}
-
{{ else }}
-
{{ $inactiveTab }}
-
{{ end }}">
-
{{ i .Icon "size-4" }}
-
{{ .Name }}
-
</div>
-
</a>
+
<a href="/{{ $.RepoInfo.FullName }}/settings?tab={{.Name}}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
+
<div class="flex gap-3 items-center p-2 {{ if eq .Name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}">
+
{{ i .Icon "size-4" }}
+
{{ .Name }}
+
</div>
+
</a>
{{ end }}
</div>
{{ end }}
+23 -38
appview/pages/templates/repo/settings/general.html
···
-
{{ define "title" }}
-
{{ .Tab }} settings &middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title" }}{{ .Tab }} settings &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "repoContent" }}
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2">
···
unless you specify a different branch.
</p>
</div>
-
<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">
-
<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">
-
<option value="" disabled selected>Choose a default branch</option>
+
<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">
+
<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">
+
<option value="" disabled selected >
+
Choose a default branch
+
</option>
{{ range .Branches }}
-
<option
-
value="{{ .Name }}"
-
class="py-1"
-
{{ if .IsDefault }}selected{{ end }}>
+
<option value="{{ .Name }}" class="py-1" {{ if .IsDefault }}selected{{ end }} >
{{ .Name }}
</option>
{{ end }}
···
{{ define "deleteRepo" }}
{{ if .RepoInfo.Roles.RepoDeleteAllowed }}
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
-
<div class="col-span-1 md:col-span-2">
-
<h2
-
class="text-sm pb-2 uppercase text-red-500 dark:text-red-400 font-bold">
-
Delete Repository
-
</h2>
-
<p class="text-red-500 dark:text-red-400 ">
-
Deleting a repository is irreversible and permanent. Be certain before
-
deleting a repository.
-
</p>
-
</div>
-
<div class="col-span-1 md:col-span-1 md:justify-self-end">
-
<button
-
class="btn group text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
-
type="button"
-
hx-delete="/{{ $.RepoInfo.FullName }}/settings/delete"
-
hx-confirm="Are you sure you want to delete {{ $.RepoInfo.FullName }}?">
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
+
<div class="col-span-1 md:col-span-2">
+
<h2 class="text-sm pb-2 uppercase text-red-500 dark:text-red-400 font-bold">Delete Repository</h2>
+
<p class="text-red-500 dark:text-red-400 ">
+
Deleting a repository is irreversible and permanent. Be certain before deleting a repository.
+
</p>
+
</div>
+
<div class="col-span-1 md:col-span-1 md:justify-self-end">
+
<button
+
class="btn group text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
+
type="button"
+
hx-delete="/{{ $.RepoInfo.FullName }}/settings/delete"
+
hx-confirm="Are you sure you want to delete {{ $.RepoInfo.FullName }}?">
{{ i "trash-2" "size-4" }}
delete
-
<span
-
class="ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline">
+
<span class="ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline">
{{ i "loader-circle" "w-4 h-4" }}
</span>
-
</button>
-
</div>
+
</button>
</div>
+
</div>
{{ end }}
{{ end }}
+53 -72
appview/pages/templates/repo/settings/pipelines.html
···
-
{{ define "title" }}
-
{{ .Tab }} settings &middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title" }}{{ .Tab }} settings &middot; {{ .RepoInfo.FullName }}{{ end }}
{{ define "repoContent" }}
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-2">
···
<p class="text-gray-500 dark:text-gray-400">
Choose a spindle to execute your workflows on. Only repository owners
can configure spindles. Spindles can be selfhosted,
-
<a
-
class="text-gray-500 dark:text-gray-400 underline"
-
href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
+
<a class="text-gray-500 dark:text-gray-400 underline" href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
click to learn more.
</a>
</p>
</div>
{{ if not $.RepoInfo.Roles.IsOwner }}
-
<div
-
class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
+
<div class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch">
{{ or $.CurrentSpindle "No spindle configured" }}
</div>
{{ else }}
-
<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">
+
<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">
<select
id="spindle"
name="spindle"
required
class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700">
{{/* 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? */}}
-
<option
-
value="[[none]]"
-
class="py-1"
-
{{ if not $.CurrentSpindle }}selected{{ end }}>
+
<option value="[[none]]" class="py-1" {{ if not $.CurrentSpindle }}selected{{ end }}>
{{ if not $.CurrentSpindle }}
-
Choose a spindle
+
Choose a spindle
{{ else }}
-
Disable pipelines
+
Disable pipelines
{{ end }}
</option>
{{ range $.Spindles }}
-
<option
-
value="{{ . }}"
-
class="py-1"
-
{{ if eq . $.CurrentSpindle }}selected{{ end }}>
+
<option value="{{ . }}" class="py-1" {{ if eq . $.CurrentSpindle }}selected{{ end }}>
{{ . }}
</option>
{{ end }}
</select>
-
<button
-
class="btn flex gap-2 items-center"
-
type="submit"
-
{{ if not $.RepoInfo.Roles.IsOwner }}disabled{{ end }}>
+
<button class="btn flex gap-2 items-center" type="submit" {{ if not $.RepoInfo.Roles.IsOwner }}disabled{{ end }}>
{{ i "check" "size-4" }}
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
···
<div class="col-span-1 md:col-span-2">
<h2 class="text-sm pb-2 uppercase font-bold">SECRETS</h2>
<p class="text-gray-500 dark:text-gray-400">
-
Secrets are accessible in workflow runs via environment variables.
-
Anyone with collaborator access to this repository can add and use
-
secrets in workflow runs.
+
Secrets are accessible in workflow runs via environment variables. Anyone
+
with collaborator access to this repository can add and use secrets in
+
workflow runs.
</p>
</div>
<div class="col-span-1 md:col-span-1 md:justify-self-end">
{{ template "addSecretButton" . }}
</div>
</div>
-
<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">
+
<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">
{{ range .Secrets }}
{{ template "repo/settings/fragments/secretListing" (list $ .) }}
{{ else }}
···
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">
{{ template "addSecretModal" . }}
</div>
-
{{ end }}
+
{{ end}}
{{ define "addSecretModal" }}
-
<form
-
hx-put="/{{ $.RepoInfo.FullName }}/settings/secrets"
-
hx-indicator="#spinner"
-
hx-swap="none"
-
class="flex flex-col gap-2">
-
<p class="uppercase p-0">ADD SECRET</p>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
-
Secrets are available as environment variables in the workflow.
-
</p>
-
<input
-
type="text"
-
id="secret-key"
-
name="key"
-
required
-
placeholder="SECRET_NAME" />
-
<textarea
-
type="text"
-
id="secret-value"
-
name="value"
-
required
-
placeholder="secret value"></textarea>
-
<div class="flex gap-2 pt-2">
-
<button
-
type="button"
-
popovertarget="add-secret-modal"
-
popovertargetaction="hide"
-
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">
-
{{ i "x" "size-4" }} cancel
-
</button>
-
<button type="submit" class="btn w-1/2 flex items-center">
-
<span class="inline-flex gap-2 items-center">
-
{{ i "plus" "size-4" }} add
-
</span>
-
<span id="spinner" class="group">
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</div>
-
<div id="add-secret-error" class="text-red-500 dark:text-red-400"></div>
-
</form>
+
<form
+
hx-put="/{{ $.RepoInfo.FullName }}/settings/secrets"
+
hx-indicator="#spinner"
+
hx-swap="none"
+
class="flex flex-col gap-2"
+
>
+
<p class="uppercase p-0">ADD SECRET</p>
+
<p class="text-sm text-gray-500 dark:text-gray-400">Secrets are available as environment variables in the workflow.</p>
+
<input
+
type="text"
+
id="secret-key"
+
name="key"
+
required
+
placeholder="SECRET_NAME"
+
/>
+
<textarea
+
type="text"
+
id="secret-value"
+
name="value"
+
required
+
placeholder="secret value"></textarea>
+
<div class="flex gap-2 pt-2">
+
<button
+
type="button"
+
popovertarget="add-secret-modal"
+
popovertargetaction="hide"
+
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"
+
>
+
{{ i "x" "size-4" }} cancel
+
</button>
+
<button type="submit" class="btn w-1/2 flex items-center">
+
<span class="inline-flex gap-2 items-center">{{ i "plus" "size-4" }} add</span>
+
<span id="spinner" class="group">
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</div>
+
<div id="add-secret-error" class="text-red-500 dark:text-red-400"></div>
+
</form>
{{ end }}
+69 -101
appview/pages/templates/repo/tree.html
···
-
{{ define "title" }}
-
{{ range .BreadCrumbs }}{{ pathUnescape (index . 0) }}/{{ end }} at
-
{{ .Ref }}
-
&middot;
-
{{ .RepoInfo.FullName }}
-
{{ end }}
+
{{ define "title"}}{{ range .BreadCrumbs }}{{ pathUnescape (index . 0)}}/{{ end }} at {{ .Ref }} &middot; {{ .RepoInfo.FullName }}{{ end }}
+
{{ define "extrameta" }}
-
{{ $path := "" }}
-
{{ range .BreadCrumbs }}
+
{{ $path := "" }}
+
{{ range .BreadCrumbs }}
{{ $path = printf "%s/%s" $path (index . 0) }}
-
{{ end }}
+
{{ end }}
-
{{ template "repo/fragments/meta" . }}
-
{{ $title := printf "%s at %s &middot; %s" $path .Ref .RepoInfo.FullName }}
-
{{ $url := printf "https://tangled.sh/%s/tree/%s%s" .RepoInfo.FullName .Ref $path }}
+
{{ template "repo/fragments/meta" . }}
+
{{ $title := printf "%s at %s &middot; %s" $path .Ref .RepoInfo.FullName }}
+
{{ $url := printf "https://tangled.sh/%s/tree/%s%s" .RepoInfo.FullName .Ref $path }}
-
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
+
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
{{ end }}
-
{{ define "repoContent" }}
-
<main>
-
<div class="tree">
-
{{ $linkstyle := "no-underline hover:underline" }}
+
{{define "repoContent"}}
+
<main>
+
<div class="tree">
+
{{ $linkstyle := "no-underline hover:underline" }}
-
<div
-
class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
-
<div class="flex flex-col md:flex-row md:justify-between gap-2">
-
<div
-
id="breadcrumbs"
-
class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
-
{{ range .BreadCrumbs }}
-
<a
-
href="{{ index . 1 }}"
-
class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}">
-
{{ pathUnescape (index . 0) }}
-
</a>
-
/
-
{{ end }}
-
</div>
-
<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">
-
{{ $stats := .TreeStats }}
+
<div class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
+
<div class="flex flex-col md:flex-row md:justify-between gap-2">
+
<div id="breadcrumbs" class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
+
{{ range .BreadCrumbs }}
+
<a href="{{ index . 1}}" class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}">{{ pathUnescape (index . 0) }}</a> /
+
{{ end }}
+
</div>
+
<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">
+
{{ $stats := .TreeStats }}
-
-
<span>
-
at
-
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}">
-
{{ $.Ref }}
-
</a>
-
</span>
-
{{ if eq $stats.NumFolders 1 }}
-
<span
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<span>{{ $stats.NumFolders }} folder</span>
-
{{ else if gt $stats.NumFolders 1 }}
-
<span
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<span>{{ $stats.NumFolders }} folders</span>
-
{{ end }}
+
<span>at <a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}">{{ $.Ref }}</a></span>
+
{{ if eq $stats.NumFolders 1 }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ $stats.NumFolders }} folder</span>
+
{{ else if gt $stats.NumFolders 1 }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ $stats.NumFolders }} folders</span>
+
{{ end }}
-
{{ if eq $stats.NumFiles 1 }}
-
<span
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<span>{{ $stats.NumFiles }} file</span>
-
{{ else if gt $stats.NumFiles 1 }}
-
<span
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<span>{{ $stats.NumFiles }} files</span>
-
{{ end }}
+
{{ if eq $stats.NumFiles 1 }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ $stats.NumFiles }} file</span>
+
{{ else if gt $stats.NumFiles 1 }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ $stats.NumFiles }} files</span>
+
{{ end }}
-
</div>
</div>
</div>
+
</div>
-
{{ range .Files }}
-
<div class="grid grid-cols-12 gap-4 items-center py-1">
-
<div class="col-span-6 md:col-span-4">
-
{{ $link := printf "/%s/%s/%s/%s/%s" $.RepoInfo.FullName "tree" (urlquery $.Ref) $.TreePath .Name }}
-
{{ $icon := "folder" }}
-
{{ $iconStyle := "size-4 fill-current" }}
+
{{ range .Files }}
+
<div class="grid grid-cols-12 gap-4 items-center py-1">
+
<div class="col-span-6 md:col-span-4">
+
{{ $link := printf "/%s/%s/%s/%s/%s" $.RepoInfo.FullName "tree" (urlquery $.Ref) $.TreePath .Name }}
+
{{ $icon := "folder" }}
+
{{ $iconStyle := "size-4 fill-current" }}
-
{{ if .IsFile }}
-
{{ $icon = "file" }}
-
{{ $iconStyle = "size-4" }}
-
{{ end }}
-
<a href="{{ $link }}" class="{{ $linkstyle }}">
-
<div class="flex items-center gap-2">
-
{{ i $icon $iconStyle "flex-shrink-0" }}
-
<span class="truncate">{{ .Name }}</span>
-
</div>
-
</a>
-
</div>
+
{{ if .IsFile }}
+
{{ $icon = "file" }}
+
{{ $iconStyle = "size-4" }}
+
{{ end }}
+
<a href="{{ $link }}" class="{{ $linkstyle }}">
+
<div class="flex items-center gap-2">
+
{{ i $icon $iconStyle "flex-shrink-0" }}
+
<span class="truncate">{{ .Name }}</span>
+
</div>
+
</a>
+
</div>
-
<div class="col-span-0 md:col-span-6 hidden md:block overflow-hidden">
-
{{ with .LastCommit }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}"
-
class="text-gray-500 dark:text-gray-400 block truncate">
-
{{ .Message }}
-
</a>
-
{{ end }}
-
</div>
+
<div class="col-span-0 md:col-span-6 hidden md:block overflow-hidden">
+
{{ with .LastCommit }}
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400 block truncate">{{ .Message }}</a>
+
{{ end }}
+
</div>
-
<div class="col-span-6 md:col-span-2 text-right">
-
{{ with .LastCommit }}
-
<a
-
href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}"
-
class="text-gray-500 dark:text-gray-400">
-
{{ template "repo/fragments/time" .When }}
-
</a>
-
{{ end }}
-
</div>
+
<div class="col-span-6 md:col-span-2 text-right">
+
{{ with .LastCommit }}
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ .Hash }}" class="text-gray-500 dark:text-gray-400">{{ template "repo/fragments/time" .When }}</a>
+
{{ end }}
</div>
-
{{ end }}
+
</div>
+
{{ end }}
-
</div>
-
</main>
-
{{ end }}
+
</div>
+
</main>
+
{{end}}
+143 -174
appview/pages/templates/settings.html
···
<p class="text-xl font-bold dark:text-white">Settings</p>
</div>
<div class="flex flex-col">
-
{{ block "profile" . }}{{ end }}
-
{{ block "keys" . }}{{ end }}
-
{{ block "emails" . }}{{ end }}
+
{{ block "profile" . }} {{ end }}
+
{{ block "keys" . }} {{ end }}
+
{{ block "emails" . }} {{ end }}
</div>
{{ end }}
{{ define "profile" }}
-
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">
-
profile
-
</h2>
-
<section
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
-
<dl class="grid grid-cols-[auto_1fr] gap-x-4 dark:text-gray-200">
-
{{ if .LoggedInUser.Handle }}
-
<dt class="font-bold">handle</dt>
-
<dd>@{{ .LoggedInUser.Handle }}</dd>
-
{{ end }}
-
<dt class="font-bold">did</dt>
-
<dd>{{ .LoggedInUser.Did }}</dd>
-
<dt class="font-bold">pds</dt>
-
<dd>{{ .LoggedInUser.Pds }}</dd>
-
</dl>
-
</section>
+
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">profile</h2>
+
<section class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
+
<dl class="grid grid-cols-[auto_1fr] gap-x-4 dark:text-gray-200">
+
{{ if .LoggedInUser.Handle }}
+
<dt class="font-bold">handle</dt>
+
<dd>@{{ .LoggedInUser.Handle }}</dd>
+
{{ end }}
+
<dt class="font-bold">did</dt>
+
<dd>{{ .LoggedInUser.Did }}</dd>
+
<dt class="font-bold">pds</dt>
+
<dd>{{ .LoggedInUser.Pds }}</dd>
+
</dl>
+
</section>
{{ end }}
{{ define "keys" }}
-
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">
-
ssh keys
-
</h2>
-
<section
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
-
<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>
-
<div id="key-list" class="flex flex-col gap-6 mb-8">
-
{{ range $index, $key := .PubKeys }}
-
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
-
<div class="flex flex-col gap-1">
-
<div class="inline-flex items-center gap-4">
-
{{ i "key" "w-3 h-3 dark:text-gray-300" }}
-
<p class="font-bold dark:text-white">{{ .Name }}</p>
-
</div>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
-
added
-
{{ template "repo/fragments/time" .Created }}
-
</p>
-
<div class="overflow-x-auto whitespace-nowrap flex-1 max-w-full">
-
<code class="text-sm text-gray-500 dark:text-gray-400">
-
{{ .Key }}
-
</code>
-
</div>
-
</div>
-
<button
-
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
-
title="Delete key"
-
hx-delete="/settings/keys?name={{ urlquery .Name }}&rkey={{ urlquery .Rkey }}&key={{ urlquery .Key }}"
-
hx-confirm="Are you sure you want to delete the key '{{ .Name }}'?">
-
{{ i "trash-2" "w-5 h-5" }}
-
<span class="hidden md:inline">delete</span>
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
+
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">ssh keys</h2>
+
<section class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
+
<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>
+
<div id="key-list" class="flex flex-col gap-6 mb-8">
+
{{ range $index, $key := .PubKeys }}
+
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
+
<div class="flex flex-col gap-1">
+
<div class="inline-flex items-center gap-4">
+
{{ i "key" "w-3 h-3 dark:text-gray-300" }}
+
<p class="font-bold dark:text-white">{{ .Name }}</p>
+
</div>
+
<p class="text-sm text-gray-500 dark:text-gray-400">added {{ template "repo/fragments/time" .Created }}</p>
+
<div class="overflow-x-auto whitespace-nowrap flex-1 max-w-full">
+
<code class="text-sm text-gray-500 dark:text-gray-400">{{ .Key }}</code>
</div>
-
{{ end }}
+
</div>
+
<button
+
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
+
title="Delete key"
+
hx-delete="/settings/keys?name={{urlquery .Name}}&rkey={{urlquery .Rkey}}&key={{urlquery .Key}}"
+
hx-confirm="Are you sure you want to delete the key '{{ .Name }}'?"
+
>
+
{{ i "trash-2" "w-5 h-5" }}
+
<span class="hidden md:inline">delete</span>
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
</div>
-
<form
+
{{ end }}
+
</div>
+
<form
hx-put="/settings/keys"
hx-indicator="#add-sshkey-spinner"
hx-swap="none"
-
class="max-w-2xl mb-8 space-y-4">
+
class="max-w-2xl mb-8 space-y-4"
+
>
<input
-
type="text"
-
id="name"
-
name="name"
-
placeholder="key name"
-
required
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400" />
+
type="text"
+
id="name"
+
name="name"
+
placeholder="key name"
+
required
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"/>
<input
-
id="key"
-
name="key"
-
placeholder="ssh-rsa AAAAAA..."
-
required
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400" />
+
id="key"
+
name="key"
+
placeholder="ssh-rsa AAAAAA..."
+
required
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"/>
-
<button
-
class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center"
-
type="submit">
-
<span>add key</span>
-
<span id="add-sshkey-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
+
<button class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center" type="submit">
+
<span>add key</span>
+
<span id="add-sshkey-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
</button>
<div id="settings-keys" class="error dark:text-red-400"></div>
-
</form>
-
</section>
+
</form>
+
</section>
{{ end }}
{{ define "emails" }}
-
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">
-
email addresses
-
</h2>
-
<section
-
class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
-
<p class="mb-8 dark:text-gray-300">
-
Commits authored using emails listed here will be associated with your
-
Tangled profile.
-
</p>
-
<div id="email-list" class="flex flex-col gap-6 mb-8">
-
{{ range $index, $email := .Emails }}
-
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
-
<div class="flex flex-col gap-2">
-
<div class="inline-flex items-center gap-4">
-
{{ i "mail" "w-3 h-3 dark:text-gray-300" }}
-
<p class="font-bold dark:text-white">{{ .Address }}</p>
-
<div class="inline-flex items-center gap-1">
-
{{ if .Verified }}
-
<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>
-
{{ else }}
-
<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>
-
{{ end }}
-
{{ if .Primary }}
-
<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>
-
{{ end }}
-
</div>
-
</div>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
-
added
-
{{ template "repo/fragments/time" .CreatedAt }}
-
</p>
-
</div>
-
<div class="flex gap-2 items-center">
-
{{ if not .Verified }}
-
<button
-
class="btn flex gap-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600"
-
hx-post="/settings/emails/verify/resend"
-
hx-swap="none"
-
href="#"
-
hx-vals='{"email": "{{ .Address }}"}'>
-
{{ i "rotate-cw" "w-5 h-5" }}
-
<span class="hidden md:inline">resend</span>
-
</button>
+
<h2 class="text-sm font-bold py-2 px-6 uppercase dark:text-gray-300">email addresses</h2>
+
<section class="rounded bg-white dark:bg-gray-800 drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
+
<p class="mb-8 dark:text-gray-300">Commits authored using emails listed here will be associated with your Tangled profile.</p>
+
<div id="email-list" class="flex flex-col gap-6 mb-8">
+
{{ range $index, $email := .Emails }}
+
<div class="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-4">
+
<div class="flex flex-col gap-2">
+
<div class="inline-flex items-center gap-4">
+
{{ i "mail" "w-3 h-3 dark:text-gray-300" }}
+
<p class="font-bold dark:text-white">{{ .Address }}</p>
+
<div class="inline-flex items-center gap-1">
+
{{ if .Verified }}
+
<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>
+
{{ else }}
+
<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>
{{ end }}
-
{{ if and (not .Primary) .Verified }}
-
<a
-
class="text-sm dark:text-blue-400 dark:hover:text-blue-300"
-
hx-post="/settings/emails/primary"
-
hx-swap="none"
-
href="#"
-
hx-vals='{"email": "{{ .Address }}"}'>
-
set as primary
-
</a>
-
{{ end }}
-
{{ if not .Primary }}
-
<form
-
hx-delete="/settings/emails"
-
hx-confirm="Are you sure you wish to delete the email '{{ .Address }}'?"
-
hx-indicator="#delete-email-{{ $index }}-spinner">
-
<input type="hidden" name="email" value="{{ .Address }}" />
-
<button
-
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
-
title="Delete email"
-
type="submit">
-
{{ i "trash-2" "w-5 h-5" }}
-
<span class="hidden md:inline">delete</span>
-
<span id="delete-email-{{ $index }}-spinner" class="group">
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</form>
+
{{ if .Primary }}
+
<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>
{{ end }}
</div>
</div>
-
{{ end }}
+
<p class="text-sm text-gray-500 dark:text-gray-400">added {{ template "repo/fragments/time" .CreatedAt }}</p>
+
</div>
+
<div class="flex gap-2 items-center">
+
{{ if not .Verified }}
+
<button
+
class="btn flex gap-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600"
+
hx-post="/settings/emails/verify/resend"
+
hx-swap="none"
+
href="#"
+
hx-vals='{"email": "{{ .Address }}"}'>
+
{{ i "rotate-cw" "w-5 h-5" }}
+
<span class="hidden md:inline">resend</span>
+
</button>
+
{{ end }}
+
{{ if and (not .Primary) .Verified }}
+
<a
+
class="text-sm dark:text-blue-400 dark:hover:text-blue-300"
+
hx-post="/settings/emails/primary"
+
hx-swap="none"
+
href="#"
+
hx-vals='{"email": "{{ .Address }}"}'>
+
set as primary
+
</a>
+
{{ end }}
+
{{ if not .Primary }}
+
<form
+
hx-delete="/settings/emails"
+
hx-confirm="Are you sure you wish to delete the email '{{ .Address }}'?"
+
hx-indicator="#delete-email-{{ $index }}-spinner"
+
>
+
<input type="hidden" name="email" value="{{ .Address }}">
+
<button
+
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 flex gap-2 items-center"
+
title="Delete email"
+
type="submit"
+
>
+
{{ i "trash-2" "w-5 h-5" }}
+
<span class="hidden md:inline">delete</span>
+
<span id="delete-email-{{ $index }}-spinner" class="group">
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</form>
+
{{ end }}
+
</div>
</div>
-
<form
+
{{ end }}
+
</div>
+
<form
hx-put="/settings/emails"
hx-swap="none"
class="max-w-2xl mb-8 space-y-4"
-
hx-indicator="#add-email-spinner">
+
hx-indicator="#add-email-spinner"
+
>
<input
-
type="email"
-
id="email"
-
name="email"
-
placeholder="your@email.com"
-
required
-
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400" />
+
type="email"
+
id="email"
+
name="email"
+
placeholder="your@email.com"
+
required
+
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"
+
>
<button
class="btn dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 flex gap-2 items-center"
-
type="submit">
+
type="submit"
+
>
<span>add email</span>
<span id="add-email-spinner" class="group">
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
···
</button>
<div id="settings-emails-error" class="error dark:text-red-400"></div>
-
<div
-
id="settings-emails-success"
-
class="success dark:text-green-400"></div>
-
</form>
-
</section>
+
<div id="settings-emails-success" class="success dark:text-green-400"></div>
+
</form>
+
</section>
{{ end }}
+51 -51
appview/pages/templates/spindles/dashboard.html
···
-
{{ define "title" }}{{ .Spindle.Instance }} &middot; spindles{{ end }}
+
{{ define "title" }}{{.Spindle.Instance}} &middot; spindles{{ end }}
{{ define "content" }}
-
<div class="px-6 py-4">
-
<div class="flex justify-between items-center">
-
<h1 class="text-xl font-bold dark:text-white">{{ .Spindle.Instance }}</h1>
-
<div id="right-side" class="flex gap-2">
-
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }}
-
{{ $isOwner := and .LoggedInUser (eq .LoggedInUser.Did .Spindle.Owner) }}
-
{{ if .Spindle.Verified }}
-
<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>
-
{{ if $isOwner }}
-
{{ template "spindles/fragments/addMemberModal" .Spindle }}
-
{{ end }}
-
{{ else }}
-
<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>
-
{{ if $isOwner }}
-
{{ block "retryButton" .Spindle }}{{ end }}
-
{{ end }}
+
<div class="px-6 py-4">
+
<div class="flex justify-between items-center">
+
<h1 class="text-xl font-bold dark:text-white">{{ .Spindle.Instance }}</h1>
+
<div id="right-side" class="flex gap-2">
+
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }}
+
{{ $isOwner := and .LoggedInUser (eq .LoggedInUser.Did .Spindle.Owner) }}
+
{{ if .Spindle.Verified }}
+
<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>
+
{{ if $isOwner }}
+
{{ template "spindles/fragments/addMemberModal" .Spindle }}
{{ end }}
-
+
{{ else }}
+
<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>
{{ if $isOwner }}
-
{{ block "deleteButton" .Spindle }}{{ end }}
+
{{ block "retryButton" .Spindle }} {{ end }}
{{ end }}
-
</div>
+
{{ end }}
+
+
{{ if $isOwner }}
+
{{ block "deleteButton" .Spindle }} {{ end }}
+
{{ end }}
</div>
-
<div id="operation-error" class="dark:text-red-400"></div>
</div>
+
<div id="operation-error" class="dark:text-red-400"></div>
+
</div>
-
{{ if .Members }}
-
<section
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
-
<div class="flex flex-col gap-2">
-
{{ block "member" . }}{{ end }}
-
</div>
-
</section>
-
{{ end }}
+
{{ if .Members }}
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
+
<div class="flex flex-col gap-2">
+
{{ block "member" . }} {{ end }}
+
</div>
+
</section>
+
{{ end }}
{{ end }}
+
{{ define "member" }}
{{ range .Members }}
···
{{ template "user/fragments/picHandleLink" . }}
</div>
{{ if ne $.LoggedInUser.Did . }}
-
{{ block "removeMemberButton" (list $ . ) }}{{ end }}
+
{{ block "removeMemberButton" (list $ . ) }} {{ end }}
{{ end }}
</div>
<div class="ml-2 pl-2 pt-2 border-l border-gray-200 dark:border-gray-700">
···
hx-delete="/spindles/{{ .Instance }}"
hx-swap="outerHTML"
hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?"
-
hx-headers='{"shouldRedirect": "true"}'>
+
hx-headers='{"shouldRedirect": "true"}'
+
>
{{ i "trash-2" "w-5 h-5" }}
-
<span class="hidden md:inline">delete</span>
+
<span class="hidden md:inline">delete</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
{{ end }}
+
{{ define "retryButton" }}
<button
···
title="Retry spindle verification"
hx-post="/spindles/{{ .Instance }}/retry"
hx-swap="none"
-
hx-headers='{"shouldRefresh": "true"}'>
+
hx-headers='{"shouldRefresh": "true"}'
+
>
{{ i "rotate-ccw" "w-5 h-5" }}
-
<span class="hidden md:inline">retry</span>
+
<span class="hidden md:inline">retry</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
{{ end }}
+
{{ define "removeMemberButton" }}
{{ $root := index . 0 }}
{{ $member := index . 1 }}
-
<button
-
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
-
title="Remove member"
-
hx-post="/spindles/{{ $root.Spindle.Instance }}/remove"
-
hx-swap="none"
-
hx-vals='{"member": "{{ $member }}" }'
-
hx-confirm="Are you sure you want to remove {{ resolve $member }} from this instance?">
-
{{ i "user-minus" "w-4 h-4" }}
-
remove
-
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</button>
+
<button
+
class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group"
+
title="Remove member"
+
hx-post="/spindles/{{ $root.Spindle.Instance }}/remove"
+
hx-swap="none"
+
hx-vals='{"member": "{{$member}}" }'
+
hx-confirm="Are you sure you want to remove {{ resolve $member }} from this instance?"
+
>
+
{{ i "user-minus" "w-4 h-4" }}
+
remove
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</button>
{{ end }}
+
+39 -39
appview/pages/templates/spindles/fragments/addMemberModal.html
···
class="btn gap-2 group"
title="Add member to this spindle"
popovertarget="add-member-{{ .Instance }}"
-
popovertargetaction="toggle">
+
popovertargetaction="toggle"
+
>
{{ i "user-plus" "w-5 h-5" }}
-
<span class="hidden md:inline">add member</span>
+
<span class="hidden md:inline">add member</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
···
id="add-member-{{ .Instance }}"
popover
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">
-
{{ block "addMemberPopover" . }}{{ end }}
+
{{ block "addMemberPopover" . }} {{ end }}
</div>
{{ end }}
{{ define "addMemberPopover" }}
-
<form
-
hx-post="/spindles/{{ .Instance }}/add"
-
hx-indicator="#spinner"
-
hx-swap="none"
-
class="flex flex-col gap-2">
-
<label for="member-did-{{ .Id }}" class="uppercase p-0">ADD MEMBER</label>
-
<p class="text-sm text-gray-500 dark:text-gray-400">
-
Members can register repositories and run workflows on this spindle.
-
</p>
-
<input
-
type="text"
-
id="member-did-{{ .Id }}"
-
name="member"
-
required
-
placeholder="@foo.bsky.social" />
-
<div class="flex gap-2 pt-2">
-
<button
-
type="button"
-
popovertarget="add-member-{{ .Instance }}"
-
popovertargetaction="hide"
-
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">
-
{{ i "x" "size-4" }} cancel
-
</button>
-
<button type="submit" class="btn w-1/2 flex items-center">
-
<span class="inline-flex gap-2 items-center">
-
{{ i "user-plus" "size-4" }} add
-
</span>
-
<span id="spinner" class="group">
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</div>
-
<div
-
id="add-member-error-{{ .Id }}"
-
class="text-red-500 dark:text-red-400"></div>
-
</form>
+
<form
+
hx-post="/spindles/{{ .Instance }}/add"
+
hx-indicator="#spinner"
+
hx-swap="none"
+
class="flex flex-col gap-2"
+
>
+
<label for="member-did-{{ .Id }}" class="uppercase p-0">
+
ADD MEMBER
+
</label>
+
<p class="text-sm text-gray-500 dark:text-gray-400">Members can register repositories and run workflows on this spindle.</p>
+
<input
+
type="text"
+
id="member-did-{{ .Id }}"
+
name="member"
+
required
+
placeholder="@foo.bsky.social"
+
/>
+
<div class="flex gap-2 pt-2">
+
<button
+
type="button"
+
popovertarget="add-member-{{ .Instance }}"
+
popovertargetaction="hide"
+
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"
+
>
+
{{ i "x" "size-4" }} cancel
+
</button>
+
<button type="submit" class="btn w-1/2 flex items-center">
+
<span class="inline-flex gap-2 items-center">{{ i "user-plus" "size-4" }} add</span>
+
<span id="spinner" class="group">
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</div>
+
<div id="add-member-error-{{ .Id }}" class="text-red-500 dark:text-red-400"></div>
+
</form>
{{ end }}
+29 -36
appview/pages/templates/spindles/fragments/spindleListing.html
···
{{ define "spindles/fragments/spindleListing" }}
-
<div
-
id="spindle-{{ .Id }}"
-
class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
-
{{ block "leftSide" . }}{{ end }}
-
{{ block "rightSide" . }}{{ end }}
+
<div id="spindle-{{.Id}}" class="flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700">
+
{{ block "leftSide" . }} {{ end }}
+
{{ block "rightSide" . }} {{ end }}
</div>
{{ end }}
{{ define "leftSide" }}
{{ if .Verified }}
-
<a
-
href="/spindles/{{ .Instance }}"
-
class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
-
{{ i "hard-drive" "w-4 h-4" }}
-
{{ .Instance }}
-
<span class="text-gray-500">
-
{{ template "repo/fragments/shortTimeAgo" .Created }}
-
</span>
-
</a>
+
<a href="/spindles/{{ .Instance }}" class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
+
{{ i "hard-drive" "w-4 h-4" }}
+
{{ .Instance }}
+
<span class="text-gray-500">
+
{{ template "repo/fragments/shortTimeAgo" .Created }}
+
</span>
+
</a>
{{ else }}
-
<div class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
-
{{ i "hard-drive" "w-4 h-4" }}
-
{{ .Instance }}
-
<span class="text-gray-500">
-
{{ template "repo/fragments/shortTimeAgo" .Created }}
-
</span>
-
</div>
+
<div class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]">
+
{{ i "hard-drive" "w-4 h-4" }}
+
{{ .Instance }}
+
<span class="text-gray-500">
+
{{ template "repo/fragments/shortTimeAgo" .Created }}
+
</span>
+
</div>
{{ end }}
{{ end }}
···
<div id="right-side" class="flex gap-2">
{{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2 text-sm" }}
{{ if .Verified }}
-
<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>
+
<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>
{{ template "spindles/fragments/addMemberModal" . }}
{{ else }}
-
<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>
-
{{ block "retryButton" . }}{{ end }}
+
<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>
+
{{ block "retryButton" . }} {{ end }}
{{ end }}
-
{{ block "deleteButton" . }}{{ end }}
+
{{ block "deleteButton" . }} {{ end }}
</div>
{{ end }}
···
title="Delete spindle"
hx-delete="/spindles/{{ .Instance }}"
hx-swap="outerHTML"
-
hx-target="#spindle-{{ .Id }}"
-
hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?">
+
hx-target="#spindle-{{.Id}}"
+
hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?"
+
>
{{ i "trash-2" "w-5 h-5" }}
-
<span class="hidden md:inline">delete</span>
+
<span class="hidden md:inline">delete</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
{{ end }}
+
{{ define "retryButton" }}
<button
···
title="Retry spindle verification"
hx-post="/spindles/{{ .Instance }}/retry"
hx-swap="none"
-
hx-target="#spindle-{{ .Id }}">
+
hx-target="#spindle-{{.Id}}"
+
>
{{ i "rotate-ccw" "w-5 h-5" }}
-
<span class="hidden md:inline">retry</span>
+
<span class="hidden md:inline">retry</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
{{ end }}
+23 -29
appview/pages/templates/spindles/index.html
···
{{ define "title" }}spindles{{ end }}
{{ define "content" }}
-
<div class="px-6 py-4">
-
<h1 class="text-xl font-bold dark:text-white">Spindles</h1>
-
</div>
+
<div class="px-6 py-4">
+
<h1 class="text-xl font-bold dark:text-white">Spindles</h1>
+
</div>
-
<section
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
-
<div class="flex flex-col gap-6">
-
{{ block "about" . }}{{ end }}
-
{{ block "list" . }}{{ end }}
-
{{ block "register" . }}{{ end }}
-
</div>
-
</section>
+
<section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
+
<div class="flex flex-col gap-6">
+
{{ block "about" . }} {{ end }}
+
{{ block "list" . }} {{ end }}
+
{{ block "register" . }} {{ end }}
+
</div>
+
</section>
{{ end }}
{{ define "about" }}
<section class="rounded flex flex-col gap-2">
<p class="dark:text-gray-300">
Spindles are small CI runners.
-
<a
-
href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
+
<a href="https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/hosting.md">
Checkout the documentation if you're interested in self-hosting.
</a>
</p>
···
{{ define "list" }}
<section class="rounded w-full flex flex-col gap-2">
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
-
your spindles
-
</h2>
-
<div
-
class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">your spindles</h2>
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full">
{{ range $spindle := .Spindles }}
{{ template "spindles/fragments/spindleListing" . }}
{{ else }}
-
<div
-
class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
+
<div class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500">
no spindles registered yet
</div>
{{ end }}
···
{{ define "register" }}
<section class="rounded w-full lg:w-fit flex flex-col gap-2">
-
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">
-
register a spindle
-
</h2>
-
<p class="mb-2 dark:text-gray-300">
-
Enter the hostname of your spindle to get started.
-
</p>
+
<h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a spindle</h2>
+
<p class="mb-2 dark:text-gray-300">Enter the hostname of your spindle to get started.</p>
<form
hx-post="/spindles/register"
class="max-w-2xl mb-2 space-y-4"
hx-indicator="#register-button"
-
hx-swap="none">
+
hx-swap="none"
+
>
<div class="flex gap-2">
<input
type="text"
···
name="instance"
placeholder="spindle.example.com"
required
-
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" />
+
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"
+
>
<button
type="submit"
id="register-button"
-
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group">
+
class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group"
+
>
<span class="inline-flex items-center gap-2">
{{ i "plus" "w-4 h-4" }}
register
···
<div id="register-error" class="dark:text-red-400"></div>
</form>
+
</section>
{{ end }}
+14 -25
appview/pages/templates/strings/dashboard.html
···
-
{{ define "title" }}strings by {{ or .Card.UserHandle .Card.UserDid }}{{ end }}
+
{{ define "title" }}strings by {{ or .Card.UserHandle .Card.UserDid }}{{ end }}
{{ define "extrameta" }}
-
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
-
<meta property="og:type" content="profile" />
-
<meta
-
property="og:url"
-
content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
-
<meta
-
property="og:description"
-
content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
+
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
+
<meta property="og:type" content="profile" />
+
<meta property="og:url" content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
+
<meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
{{ end }}
+
{{ define "content" }}
-
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
+
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
<div class="md:col-span-3 order-1 md:order-1">
-
{{ template "user/fragments/profileCard" .Card }}
+
{{ template "user/fragments/profileCard" .Card }}
</div>
<div id="all-strings" class="md:col-span-8 order-2 md:order-2">
-
{{ block "allStrings" . }}{{ end }}
+
{{ block "allStrings" . }}{{ end }}
</div>
-
</div>
+
</div>
{{ end }}
{{ define "allStrings" }}
···
{{ range .Strings }}
{{ template "singleString" (list $ .) }}
{{ else }}
-
<p class="px-6 dark:text-white">
-
This user does not have any strings yet.
-
</p>
+
<p class="px-6 dark:text-white">This user does not have any strings yet.</p>
{{ end }}
</div>
{{ end }}
···
{{ $s := index . 1 }}
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800">
<div class="font-medium dark:text-white flex gap-2 items-center">
-
<a
-
href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">
-
{{ $s.Filename }}
-
</a>
+
<a href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a>
</div>
{{ with $s.Description }}
<div class="text-gray-600 dark:text-gray-300 text-sm">
-
{{ . }}
+
{{ . }}
</div>
{{ end }}
{{ $stat := $s.Stats }}
<div class="text-gray-400 pt-4 text-sm font-mono inline-flex gap-2 mt-auto">
-
<span>
-
{{ $stat.LineCount }}
-
line{{ if ne $stat.LineCount 1 }}s{{ end }}
-
</span>
+
<span>{{ $stat.LineCount }} line{{if ne $stat.LineCount 1}}s{{end}}</span>
<span class="select-none [&:before]:content-['·']"></span>
{{ with $s.Edited }}
<span>edited {{ template "repo/fragments/shortTimeAgo" . }}</span>
+20 -20
appview/pages/templates/strings/fragments/form.html
···
{{ if eq .Action "new" }}
hx-post="/strings/new"
{{ else }}
-
hx-post="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit"
+
hx-post="/strings/{{.String.Did}}/{{.String.Rkey}}/edit"
{{ end }}
hx-indicator="#new-button"
class="p-6 pb-4 dark:text-white flex flex-col gap-2 bg-white dark:bg-gray-800 drop-shadow-sm rounded"
···
placeholder="Filename with extension"
required
value="{{ .String.Filename }}"
-
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" />
+
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"
+
>
<input
type="text"
id="description"
name="description"
value="{{ .String.Description }}"
placeholder="Description ..."
-
class="flex-1 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded" />
+
class="flex-1 dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded"
+
>
</div>
<textarea
-
name="content"
+
name="content"
id="content-textarea"
wrap="off"
class="w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400"
rows="20"
placeholder="Paste your string here!"
-
required>
-
{{ .String.Contents }}</textarea
-
>
+
required>{{ .String.Contents }}</textarea>
<div class="flex justify-between items-center">
<div id="content-stats" class="text-sm text-gray-500 dark:text-gray-400">
<span id="line-count">0 lines</span>
···
</div>
<div id="actions" class="flex gap-2 items-center">
{{ if eq .Action "edit" }}
-
<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 "
-
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}">
+
<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 "
+
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}">
{{ i "x" "size-4" }}
<span class="hidden md:inline">cancel</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
···
<button
type="submit"
id="new-button"
-
class="w-fit btn-create rounded flex items-center py-0 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group">
+
class="w-fit btn-create rounded flex items-center py-0 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group"
+
>
<span class="inline-flex items-center gap-2">
{{ i "arrow-up" "w-4 h-4" }}
publish
···
</div>
</div>
<script>
-
(function () {
-
const textarea = document.getElementById("content-textarea");
-
const lineCount = document.getElementById("line-count");
-
const byteCount = document.getElementById("byte-count");
+
(function() {
+
const textarea = document.getElementById('content-textarea');
+
const lineCount = document.getElementById('line-count');
+
const byteCount = document.getElementById('byte-count');
function updateStats() {
const content = textarea.value;
-
const lines = content === "" ? 0 : content.split("\n").length;
+
const lines = content === '' ? 0 : content.split('\n').length;
const bytes = new TextEncoder().encode(content).length;
-
lineCount.textContent = `${lines} line${lines !== 1 ? "s" : ""}`;
-
byteCount.textContent = `${bytes} byte${bytes !== 1 ? "s" : ""}`;
+
lineCount.textContent = `${lines} line${lines !== 1 ? 's' : ''}`;
+
byteCount.textContent = `${bytes} byte${bytes !== 1 ? 's' : ''}`;
}
-
textarea.addEventListener("input", updateStats);
-
textarea.addEventListener("paste", () => {
+
textarea.addEventListener('input', updateStats);
+
textarea.addEventListener('paste', () => {
setTimeout(updateStats, 0);
});
updateStats();
+21 -40
appview/pages/templates/strings/string.html
···
-
{{ define "title" }}
-
{{ .String.Filename }} · by
-
{{ didOrHandle .Owner.DID.String .Owner.Handle.String }}
-
{{ end }}
+
{{ define "title" }}{{ .String.Filename }} · by {{ didOrHandle .Owner.DID.String .Owner.Handle.String }}{{ end }}
{{ define "extrameta" }}
{{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }}
-
<meta
-
property="og:title"
-
content="{{ .String.Filename }} · by {{ $ownerId }}" />
+
<meta property="og:title" content="{{ .String.Filename }} · by {{ $ownerId }}" />
<meta property="og:type" content="object" />
-
<meta
-
property="og:url"
-
content="https://tangled.sh/strings/{{ $ownerId }}/{{ .String.Rkey }}" />
+
<meta property="og:url" content="https://tangled.sh/strings/{{ $ownerId }}/{{ .String.Rkey }}" />
<meta property="og:description" content="{{ .String.Description }}" />
{{ end }}
···
{{ end }}
{{ define "content" }}
-
{{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }}
+
{{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }}
<section id="string-header" class="mb-4 py-2 px-6 dark:text-white">
<div class="text-lg flex items-center justify-between">
<div>
<a href="/strings/{{ $ownerId }}">{{ $ownerId }}</a>
<span class="select-none">/</span>
-
<a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}" class="font-bold">
-
{{ .String.Filename }}
-
</a>
+
<a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}" class="font-bold">{{ .String.Filename }}</a>
</div>
{{ if and .LoggedInUser (eq .LoggedInUser.Did .String.Did) }}
<div class="flex gap-2 text-base">
-
<a
-
class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
-
hx-boost="true"
-
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit">
+
<a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group"
+
hx-boost="true"
+
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit">
{{ i "pencil" "size-4" }}
-
<span class="hidden md:inline">edit</span>
+
<span class="hidden md:inline">edit</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</a>
<button
···
title="Delete string"
hx-delete="/strings/{{ .String.Did }}/{{ .String.Rkey }}/"
hx-swap="none"
-
hx-confirm="Are you sure you want to delete the gist `{{ .String.Filename }}`?">
+
hx-confirm="Are you sure you want to delete the gist `{{ .String.Filename }}`?"
+
>
{{ i "trash-2" "size-4" }}
-
<span class="hidden md:inline">delete</span>
+
<span class="hidden md:inline">delete</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
</div>
···
{{ end }}
</span>
</section>
-
<section
-
class="bg-white dark:bg-gray-800 px-6 py-4 rounded relative w-full dark:text-white">
-
<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">
+
<section class="bg-white dark:bg-gray-800 px-6 py-4 rounded relative w-full dark:text-white">
+
<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">
<span>
{{ .String.Filename }}
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
<span>
{{ with .String.Edited }}
-
edited
-
{{ template "repo/fragments/shortTimeAgo" . }}
+
edited {{ template "repo/fragments/shortTimeAgo" . }}
{{ else }}
{{ template "repo/fragments/shortTimeAgo" .String.Created }}
{{ end }}
···
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
<a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}/raw">view raw</a>
{{ if .RenderToggle }}
-
<span
-
class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
-
<a href="?code={{ .ShowRendered }}" hx-boost="true">
-
view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}
-
</a>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<a href="?code={{ .ShowRendered }}" hx-boost="true">
+
view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}
+
</a>
{{ end }}
</div>
</div>
<div class="overflow-auto relative">
{{ if .ShowRendered }}
-
<div id="blob-contents" class="prose dark:prose-invert">
-
{{ .RenderedContents }}
-
</div>
+
<div id="blob-contents" class="prose dark:prose-invert">{{ .RenderedContents }}</div>
{{ else }}
-
<div
-
id="blob-contents"
-
class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">
-
{{ .String.Contents | escapeHtml }}
-
</div>
+
<div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ .String.Contents | escapeHtml }}</div>
{{ end }}
</div>
</section>
+84 -119
appview/pages/templates/timeline.html
···
{{ define "title" }}timeline{{ end }}
{{ define "extrameta" }}
-
<meta property="og:title" content="timeline · tangled" />
-
<meta property="og:type" content="object" />
-
<meta property="og:url" content="https://tangled.sh" />
-
<meta property="og:description" content="see what's tangling" />
+
<meta property="og:title" content="timeline · tangled" />
+
<meta property="og:type" content="object" />
+
<meta property="og:url" content="https://tangled.sh" />
+
<meta property="og:description" content="see what's tangling" />
{{ end }}
{{ define "topbar" }}
···
{{ end }}
{{ define "content" }}
-
{{ with .LoggedInUser }}
-
{{ block "timeline" $ }}{{ end }}
-
{{ else }}
-
{{ block "hero" $ }}{{ end }}
-
{{ block "timeline" $ }}{{ end }}
-
{{ end }}
+
{{ with .LoggedInUser }}
+
{{ block "timeline" $ }}{{ end }}
+
{{ else }}
+
{{ block "hero" $ }}{{ end }}
+
{{ block "timeline" $ }}{{ end }}
+
{{ end }}
{{ end }}
{{ define "hero" }}
-
<div class="flex flex-col text-black dark:text-white p-6 gap-6 max-w-xl">
-
<div class="font-bold text-4xl">
-
tightly-knit
-
<br />
-
social coding.
-
</div>
+
<div class="flex flex-col text-black dark:text-white p-6 gap-6 max-w-xl">
+
<div class="font-bold text-4xl">tightly-knit<br>social coding.</div>
-
<p class="text-lg">
-
tangled is new social-enabled git collaboration platform built on
-
<a class="underline" href="https://atproto.com/">atproto</a>
-
.
-
</p>
-
<p class="text-lg">
-
we envision a place where developers have complete ownership of their
-
code, open source communities can freely self-govern and most importantly,
-
coding can be social and fun again.
-
</p>
+
<p class="text-lg">
+
tangled is new social-enabled git collaboration platform built on <a class="underline" href="https://atproto.com/">atproto</a>.
+
</p>
+
<p class="text-lg">
+
we envision a place where developers have complete ownership of their
+
code, open source communities can freely self-govern and most
+
importantly, coding can be social and fun again.
+
</p>
-
<div class="flex gap-6 items-center">
-
<a href="/signup" class="no-underline hover:no-underline ">
-
<button class="btn-create flex gap-2 px-4 items-center">
-
join now
-
{{ i "arrow-right" "size-4" }}
-
</button>
-
</a>
+
<div class="flex gap-6 items-center">
+
<a href="/signup" class="no-underline hover:no-underline ">
+
<button class="btn-create flex gap-2 px-4 items-center">
+
join now {{ i "arrow-right" "size-4" }}
+
</button>
+
</a>
+
</div>
</div>
-
</div>
{{ end }}
{{ define "timeline" }}
-
<div>
-
<div class="p-6">
-
<p class="text-xl font-bold dark:text-white">Timeline</p>
-
</div>
+
<div>
+
<div class="p-6">
+
<p class="text-xl font-bold dark:text-white">Timeline</p>
+
</div>
-
<div class="flex flex-col gap-4">
-
{{ range $i, $e := .Timeline }}
-
<div class="relative">
-
{{ if ne $i 0 }}
-
<div
-
class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
-
{{ end }}
-
{{ with $e }}
-
<div
-
class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
-
{{ if .Repo }}
-
{{ block "repoEvent" (list $ .Repo .Source) }}{{ end }}
-
{{ else if .Star }}
-
{{ block "starEvent" (list $ .Star) }}{{ end }}
-
{{ else if .Follow }}
-
{{ block "followEvent" (list $ .Follow .Profile .FollowStats) }}
-
{{ end }}
+
<div class="flex flex-col gap-4">
+
{{ range $i, $e := .Timeline }}
+
<div class="relative">
+
{{ if ne $i 0 }}
+
<div class="absolute left-8 -top-4 w-px h-4 bg-gray-300 dark:bg-gray-600"></div>
+
{{ end }}
+
{{ with $e }}
+
<div class="flex flex-col divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-sm">
+
{{ if .Repo }}
+
{{ block "repoEvent" (list $ .Repo .Source) }} {{ end }}
+
{{ else if .Star }}
+
{{ block "starEvent" (list $ .Star) }} {{ end }}
+
{{ else if .Follow }}
+
{{ block "followEvent" (list $ .Follow .Profile .FollowStats) }} {{ end }}
+
{{ end }}
+
</div>
{{ end }}
</div>
{{ end }}
</div>
-
{{ end }}
</div>
-
</div>
{{ end }}
{{ define "repoEvent" }}
···
{{ $repo := index . 1 }}
{{ $source := index . 2 }}
{{ $userHandle := resolve $repo.Did }}
-
<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">
-
{{ template "user/fragments/picHandleLink" $repo.Did }}
-
{{ with $source }}
-
{{ $sourceDid := resolve .Did }}
-
forked
-
<a
-
href="/{{ $sourceDid }}/{{ .Name }}"
-
class="no-underline hover:underline">
-
{{ $sourceDid }}/{{ .Name }}
-
</a>
-
to
-
<a
-
href="/{{ $userHandle }}/{{ $repo.Name }}"
-
class="no-underline hover:underline">
-
{{ $repo.Name }}
-
</a>
-
{{ else }}
-
created
-
<a
-
href="/{{ $userHandle }}/{{ $repo.Name }}"
-
class="no-underline hover:underline">
-
{{ $repo.Name }}
-
</a>
-
{{ end }}
-
<span class="text-gray-700 dark:text-gray-400 text-xs">
-
{{ template "repo/fragments/time" $repo.Created }}
-
</span>
-
</div>
+
<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">
+
{{ template "user/fragments/picHandleLink" $repo.Did }}
+
{{ with $source }}
+
{{ $sourceDid := resolve .Did }}
+
forked
+
<a href="/{{ $sourceDid }}/{{ .Name }}"class="no-underline hover:underline">
+
{{ $sourceDid }}/{{ .Name }}
+
</a>
+
to
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">{{ $repo.Name }}</a>
+
{{ else }}
+
created
+
<a href="/{{ $userHandle }}/{{ $repo.Name }}" class="no-underline hover:underline">
+
{{ $repo.Name }}
+
</a>
+
{{ end }}
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $repo.Created }}</span>
+
</div>
{{ with $repo }}
{{ template "user/fragments/repoCard" (list $root . true) }}
{{ end }}
···
{{ with $star }}
{{ $starrerHandle := resolve .StarredByDid }}
{{ $repoOwnerHandle := resolve .Repo.Did }}
-
<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">
-
{{ template "user/fragments/picHandleLink" $starrerHandle }}
-
starred
-
<a
-
href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}"
-
class="no-underline hover:underline">
-
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
-
</a>
-
<span class="text-gray-700 dark:text-gray-400 text-xs">
-
{{ template "repo/fragments/time" .Created }}
-
</span>
+
<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">
+
{{ template "user/fragments/picHandleLink" $starrerHandle }}
+
starred
+
<a href="/{{ $repoOwnerHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">
+
{{ $repoOwnerHandle | truncateAt30 }}/{{ .Repo.Name }}
+
</a>
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" .Created }}</span>
</div>
{{ with .Repo }}
{{ template "user/fragments/repoCard" (list $root . true) }}
{{ end }}
{{ end }}
{{ end }}
+
{{ define "followEvent" }}
{{ $root := index . 0 }}
···
{{ $userHandle := resolve $follow.UserDid }}
{{ $subjectHandle := resolve $follow.SubjectDid }}
-
<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">
-
{{ template "user/fragments/picHandleLink" $userHandle }}
-
followed
-
{{ template "user/fragments/picHandleLink" $subjectHandle }}
-
<span class="text-gray-700 dark:text-gray-400 text-xs">
-
{{ template "repo/fragments/time" $follow.FollowedAt }}
-
</span>
+
<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">
+
{{ template "user/fragments/picHandleLink" $userHandle }}
+
followed
+
{{ template "user/fragments/picHandleLink" $subjectHandle }}
+
<span class="text-gray-700 dark:text-gray-400 text-xs">{{ template "repo/fragments/time" $follow.FollowedAt }}</span>
</div>
-
<div
-
class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
+
<div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800 flex items-center gap-4">
<div class="flex-shrink-0 max-h-full w-24 h-24">
-
<img
-
class="object-cover rounded-full p-2"
-
src="{{ fullAvatar $subjectHandle }}" />
+
<img class="object-cover rounded-full p-2" src="{{ fullAvatar $subjectHandle }}" />
</div>
<div class="flex-1 min-h-0 justify-around flex flex-col">
<a href="/{{ $subjectHandle }}">
-
<span
-
class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
-
{{ $subjectHandle | truncateAt30 }}
-
</span>
+
<span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $subjectHandle | truncateAt30 }}</span>
</a>
{{ with $profile }}
{{ with .Description }}
-
<p class="text-sm pb-2 md:pb-2">{{ . }}</p>
+
<p class="text-sm pb-2 md:pb-2">{{.}}</p>
{{ end }}
{{ end }}
{{ with $stat }}
-
<div
-
class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
+
<div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
<span id="followers">{{ .Followers }} followers</span>
<span class="select-none after:content-['·']"></span>
-
<span id="following">{{ .Following }} following</span>
+
<span id="following">{{ .Following }} following</span>
</div>
{{ end }}
</div>
+99 -83
appview/pages/templates/user/completeSignup.html
···
{{ define "user/completeSignup" }}
-
<!doctype html>
-
<html lang="en" class="dark:bg-gray-900">
-
<head>
-
<meta charset="UTF-8" />
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-
<meta property="og:title" content="complete signup · tangled" />
-
<meta property="og:url" content="https://tangled.sh/complete-signup" />
-
<meta
-
property="og:description"
-
content="complete your signup for tangled" />
-
<script src="/static/htmx.min.js"></script>
-
<link
-
rel="stylesheet"
-
href="/static/tw.css?{{ cssContentHash }}"
-
type="text/css" />
-
<title>complete signup &middot; tangled</title>
-
</head>
-
<body class="flex items-center justify-center min-h-screen">
-
<main class="max-w-md px-6 -mt-4">
-
<h1 class="text-center text-2xl font-semibold italic dark:text-white">
-
tangled
-
</h1>
-
<h2 class="text-center text-xl italic dark:text-white">
-
tightly-knit social coding.
-
</h2>
-
<form
-
class="mt-4 max-w-sm mx-auto flex flex-col gap-4"
-
hx-post="/signup/complete"
-
hx-swap="none"
-
hx-disabled-elt="#complete-signup-button">
-
<div class="flex flex-col">
-
<label for="code">verification code</label>
-
<input
-
type="text"
-
id="code"
-
name="code"
-
tabindex="1"
-
required
-
placeholder="tngl-sh-foo-bar" />
-
<span class="text-sm text-gray-500 mt-1">
-
Enter the code sent to your email.
-
</span>
-
</div>
+
<!doctype html>
+
<html lang="en" class="dark:bg-gray-900">
+
<head>
+
<meta charset="UTF-8" />
+
<meta
+
name="viewport"
+
content="width=device-width, initial-scale=1.0"
+
/>
+
<meta
+
property="og:title"
+
content="complete signup · tangled"
+
/>
+
<meta
+
property="og:url"
+
content="https://tangled.sh/complete-signup"
+
/>
+
<meta
+
property="og:description"
+
content="complete your signup for tangled"
+
/>
+
<script src="/static/htmx.min.js"></script>
+
<link
+
rel="stylesheet"
+
href="/static/tw.css?{{ cssContentHash }}"
+
type="text/css"
+
/>
+
<title>complete signup &middot; tangled</title>
+
</head>
+
<body class="flex items-center justify-center min-h-screen">
+
<main class="max-w-md px-6 -mt-4">
+
<h1
+
class="text-center text-2xl font-semibold italic dark:text-white"
+
>
+
tangled
+
</h1>
+
<h2 class="text-center text-xl italic dark:text-white">
+
tightly-knit social coding.
+
</h2>
+
<form
+
class="mt-4 max-w-sm mx-auto flex flex-col gap-4"
+
hx-post="/signup/complete"
+
hx-swap="none"
+
hx-disabled-elt="#complete-signup-button"
+
>
+
<div class="flex flex-col">
+
<label for="code">verification code</label>
+
<input
+
type="text"
+
id="code"
+
name="code"
+
tabindex="1"
+
required
+
placeholder="tngl-sh-foo-bar"
+
/>
+
<span class="text-sm text-gray-500 mt-1">
+
Enter the code sent to your email.
+
</span>
+
</div>
-
<div class="flex flex-col">
-
<label for="username">username</label>
-
<input
-
type="text"
-
id="username"
-
name="username"
-
tabindex="2"
-
required
-
placeholder="jason" />
-
<span class="text-sm text-gray-500 mt-1">
-
Your complete handle will be of the form
-
<code>user.tngl.sh</code>
-
.
-
</span>
-
</div>
+
<div class="flex flex-col">
+
<label for="username">username</label>
+
<input
+
type="text"
+
id="username"
+
name="username"
+
tabindex="2"
+
required
+
placeholder="jason"
+
/>
+
<span class="text-sm text-gray-500 mt-1">
+
Your complete handle will be of the form <code>user.tngl.sh</code>.
+
</span>
+
</div>
-
<div class="flex flex-col">
-
<label for="password">password</label>
-
<input
-
type="password"
-
id="password"
-
name="password"
-
tabindex="3"
-
required />
-
<span class="text-sm text-gray-500 mt-1">
-
Choose a strong password for your account.
-
</span>
-
</div>
+
<div class="flex flex-col">
+
<label for="password">password</label>
+
<input
+
type="password"
+
id="password"
+
name="password"
+
tabindex="3"
+
required
+
/>
+
<span class="text-sm text-gray-500 mt-1">
+
Choose a strong password for your account.
+
</span>
+
</div>
-
<button
-
class="btn-create w-full my-2 mt-6 text-base"
-
type="submit"
-
id="complete-signup-button"
-
tabindex="4">
-
<span>complete signup</span>
-
</button>
-
</form>
-
<p id="signup-error" class="error w-full"></p>
-
<p id="signup-msg" class="dark:text-white w-full"></p>
-
</main>
-
</body>
-
</html>
+
<button
+
class="btn-create w-full my-2 mt-6 text-base"
+
type="submit"
+
id="complete-signup-button"
+
tabindex="4"
+
>
+
<span>complete signup</span>
+
</button>
+
</form>
+
<p id="signup-error" class="error w-full"></p>
+
<p id="signup-msg" class="dark:text-white w-full"></p>
+
</main>
+
</body>
+
</html>
{{ end }}
+4 -12
appview/pages/templates/user/fragments/bluesky.html
···
{{ define "user/fragments/bluesky" }}
-
<svg
-
class="{{ . }}"
-
xmlns="http://www.w3.org/2000/svg"
-
role="img"
-
viewBox="-3 -3 30 30">
-
<title>Bluesky</title>
-
<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" />
-
</svg>
+
<svg class="{{.}}" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="-3 -3 30 30">
+
<title>Bluesky</title>
+
<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"/>
+
</svg>
{{ end }}
+29 -61
appview/pages/templates/user/fragments/editBio.html
···
{{ $description = .Profile.Description }}
{{ end }}
<label class="m-0 p-0" for="description">bio</label>
-
<textarea
-
type="text"
-
class="py-1 px-1 w-full"
-
name="description"
+
<textarea
+
type="text"
+
class="py-1 px-1 w-full"
+
name="description"
rows="3"
-
placeholder="write a bio">
-
{{ $description }}</textarea
-
>
+
placeholder="write a bio">{{ $description }}</textarea>
</div>
<div class="flex flex-col gap-1">
···
{{ $location = .Profile.Location }}
{{ end }}
<span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span>
-
<input
-
type="text"
-
class="py-1 px-1 w-full"
-
name="location"
-
value="{{ $location }}" />
+
<input type="text" class="py-1 px-1 w-full" name="location" value="{{ $location }}">
</div>
</div>
···
{{ if and .Profile .Profile.IncludeBluesky }}
{{ $includeBsky = true }}
{{ end }}
-
<input
-
type="checkbox"
-
id="includeBluesky"
-
name="includeBluesky"
-
value="on"
-
{{ if $includeBsky }}checked{{ end }} />
-
<label for="includeBluesky" class="my-0 py-0 normal-case font-normal">
-
Link to Bluesky account
-
</label>
+
<input type="checkbox" id="includeBluesky" name="includeBluesky" value="on" {{if $includeBsky}}checked{{end}}>
+
<label for="includeBluesky" class="my-0 py-0 normal-case font-normal">Link to Bluesky account</label>
</div>
{{ $profile := .Profile }}
···
{{ end }}
{{ end }}
-
<div class="flex items-center gap-2 w-full">
<span class="flex-shrink-0">{{ i "link" "size-4" }}</span>
-
<input
-
type="text"
-
class="py-1 px-1 w-full"
-
name="link{{ $idx }}"
-
value="{{ $link }}"
-
placeholder="social link {{ add $idx 1 }}" />
+
<input type="text" class="py-1 px-1 w-full" name="link{{$idx}}" value="{{ $link }}" placeholder="social link {{add $idx 1}}">
</div>
{{ end }}
</div>
···
<div class="flex flex-col gap-1">
<label class="m-0 p-0">vanity stats</label>
{{ range $idx, $s := (sequence 2) }}
-
{{ $stat := "" }}
-
{{ if and $profile $profile.Stats }}
-
{{ if lt $idx (len $profile.Stats) }}
-
{{ $s := index $profile.Stats $idx }}
-
{{ $stat = $s.Kind }}
+
{{ $stat := "" }}
+
{{ if and $profile $profile.Stats }}
+
{{ if lt $idx (len $profile.Stats) }}
+
{{ $s := index $profile.Stats $idx }}
+
{{ $stat = $s.Kind }}
+
{{ end }}
{{ end }}
-
{{ end }}
-
{{ block "stat" (list $idx $stat) }}{{ end }}
+
{{ block "stat" (list $idx $stat) }} {{ end }}
{{ end }}
</div>
<div class="flex items-center gap-2 justify-between">
-
<button
-
id="save-btn"
-
type="submit"
-
class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
+
<button id="save-btn" type="submit" class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
{{ i "check" "size-4" }} save
<span id="spinner" class="group">
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</span>
</button>
-
<a
-
href="/{{ .LoggedInUser.Did }}"
-
class="w-full no-underline hover:no-underline">
-
<button
-
id="cancel-btn"
-
type="button"
-
class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
+
<a href="/{{.LoggedInUser.Did}}" class="w-full no-underline hover:no-underline">
+
<button id="cancel-btn" type="button" class="btn p-1 w-full flex items-center gap-2 no-underline text-sm">
{{ i "x" "size-4" }} cancel
</button>
</a>
···
{{ define "stat" }}
{{ $id := index . 0 }}
{{ $stat := index . 1 }}
-
<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 }}">
+
<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}}">
<option value="">choose stat</option>
{{ $stats := assoc
-
"merged-pull-request-count" "Merged PR Count"
-
"closed-pull-request-count" "Closed PR Count"
-
"open-pull-request-count" "Open PR Count"
-
"open-issue-count" "Open Issue Count"
-
"closed-issue-count" "Closed Issue Count"
-
"repository-count" "Repository Count"
+
"merged-pull-request-count" "Merged PR Count"
+
"closed-pull-request-count" "Closed PR Count"
+
"open-pull-request-count" "Open PR Count"
+
"open-issue-count" "Open Issue Count"
+
"closed-issue-count" "Closed Issue Count"
+
"repository-count" "Repository Count"
}}
{{ range $s := $stats }}
-
{{ $value := index $s 0 }}
-
{{ $label := index $s 1 }}
-
<option value="{{ $value }}" {{ if eq $stat $value }}selected{{ end }}>
-
{{ $label }}
-
</option>
+
{{ $value := index $s 0 }}
+
{{ $label := index $s 1 }}
+
<option value="{{ $value }}"{{ if eq $stat $value }} selected{{ end }}>{{ $label }}</option>
{{ end }}
</select>
{{ end }}
+29 -48
appview/pages/templates/user/fragments/editPins.html
···
{{ define "user/fragments/editPins" }}
{{ $profile := .Profile }}
-
<form
-
hx-post="/profile/pins"
-
hx-disabled-elt="#save-btn,#cancel-btn"
-
hx-swap="none"
-
hx-indicator="#spinner">
-
<div class="flex items-center justify-between mb-2">
-
<p class="text-sm font-bold p-2 dark:text-white">SELECT PINNED REPOS</p>
-
<div class="flex items-center gap-2">
-
<button
-
id="save-btn"
-
type="submit"
-
class="btn px-2 flex items-center gap-2 no-underline text-sm">
-
{{ i "check" "w-3 h-3" }} save
-
<span id="spinner" class="group">
-
{{ i "loader-circle" "w-3 h-3 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
<a
-
href="/{{ .LoggedInUser.Did }}"
-
class="w-full no-underline hover:no-underline">
-
<button
-
id="cancel-btn"
-
type="button"
-
class="btn px-2 w-full flex items-center gap-2 no-underline text-sm">
-
{{ i "x" "w-3 h-3" }} cancel
+
<form
+
hx-post="/profile/pins"
+
hx-disabled-elt="#save-btn,#cancel-btn"
+
hx-swap="none"
+
hx-indicator="#spinner">
+
<div class="flex items-center justify-between mb-2">
+
<p class="text-sm font-bold p-2 dark:text-white">SELECT PINNED REPOS</p>
+
<div class="flex items-center gap-2">
+
<button id="save-btn" type="submit" class="btn px-2 flex items-center gap-2 no-underline text-sm">
+
{{ i "check" "w-3 h-3" }} save
+
<span id="spinner" class="group">
+
{{ i "loader-circle" "w-3 h-3 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
</button>
-
</a>
+
<a href="/{{.LoggedInUser.Did}}" class="w-full no-underline hover:no-underline">
+
<button id="cancel-btn" type="button" class="btn px-2 w-full flex items-center gap-2 no-underline text-sm">
+
{{ i "x" "w-3 h-3" }} cancel
+
</button>
+
</a>
+
</div>
</div>
-
</div>
-
<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">
-
{{ range $idx, $r := .AllRepos }}
-
<div
-
class="flex items-center gap-2 text-base p-2 border-b border-gray-200 dark:border-gray-700">
-
<input
-
type="checkbox"
-
id="repo-{{ $idx }}"
-
name="pinnedRepo{{ $idx }}"
-
value="{{ .RepoAt }}"
-
{{ if .IsPinned }}checked{{ end }} />
-
<label
-
for="repo-{{ $idx }}"
-
class="my-0 py-0 normal-case font-normal w-full">
+
<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">
+
{{ range $idx, $r := .AllRepos }}
+
<div class="flex items-center gap-2 text-base p-2 border-b border-gray-200 dark:border-gray-700">
+
<input type="checkbox" id="repo-{{$idx}}" name="pinnedRepo{{$idx}}" value="{{.RepoAt}}" {{if .IsPinned}}checked{{end}}>
+
<label for="repo-{{$idx}}" class="my-0 py-0 normal-case font-normal w-full">
<div class="flex justify-between items-center w-full">
-
<span class="flex-shrink-0 overflow-hidden text-ellipsis ">
-
{{ resolve .Did }}/{{ .Name }}
-
</span>
+
<span class="flex-shrink-0 overflow-hidden text-ellipsis ">{{ resolve .Did }}/{{.Name}}</span>
<div class="flex gap-1 items-center">
{{ i "star" "size-4 fill-current" }}
<span>{{ .RepoStats.StarCount }}</span>
···
</div>
</label>
</div>
-
{{ end }}
-
</div>
-
</form>
+
{{ end }}
+
</div>
+
+
</form>
{{ end }}
+7 -10
appview/pages/templates/user/fragments/follow.html
···
{{ define "user/fragments/follow" }}
-
<button
-
id="followBtn"
+
<button id="followBtn"
class="btn mt-2 w-full flex gap-2 items-center group"
+
{{ if eq .FollowStatus.String "IsNotFollowing" }}
-
hx-post="/follow?subject={{ .UserDid }}"
+
hx-post="/follow?subject={{.UserDid}}"
{{ else }}
-
hx-delete="/follow?subject={{ .UserDid }}"
+
hx-delete="/follow?subject={{.UserDid}}"
{{ end }}
hx-trigger="click"
hx-target="#followBtn"
-
hx-swap="outerHTML">
-
{{ if eq .FollowStatus.String "IsNotFollowing" }}
-
Follow
-
{{ else }}
-
Unfollow
-
{{ end }}
+
hx-swap="outerHTML"
+
>
+
{{ if eq .FollowStatus.String "IsNotFollowing" }}Follow{{ else }}Unfollow{{ end }}
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
{{ end }}
+4 -3
appview/pages/templates/user/fragments/picHandle.html
···
{{ define "user/fragments/picHandle" }}
-
<img
+
<img
src="{{ tinyAvatar . }}"
alt="{{ . }}"
-
class="rounded-full h-6 w-6 mr-1 border border-gray-300 dark:border-gray-700" />
-
{{ . | truncateAt30 }}
+
class="rounded-full h-6 w-6 mr-1 border border-gray-300 dark:border-gray-700"
+
/>
+
{{ . | truncateAt30 }}
{{ end }}
+3 -3
appview/pages/templates/user/fragments/picHandleLink.html
···
{{ define "user/fragments/picHandleLink" }}
-
{{ $resolved := resolve . }}
-
<a href="/{{ $resolved }}" class="flex items-center">
+
{{ $resolved := resolve . }}
+
<a href="/{{ $resolved }}" class="flex items-center">
{{ template "user/fragments/picHandle" $resolved }}
-
</a>
+
</a>
{{ end }}
+44 -59
appview/pages/templates/user/fragments/profileCard.html
···
{{ define "user/fragments/profileCard" }}
-
<div
-
class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm max-h-fit">
+
<div class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm max-h-fit">
<div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center">
<div id="avatar" class="col-span-1 flex justify-center items-center">
<div class="w-3/4 aspect-square relative">
-
<img
-
class="absolute inset-0 w-full h-full object-cover rounded-full p-2"
-
src="{{ fullAvatar .UserDid }}" />
+
<img class="absolute inset-0 w-full h-full object-cover rounded-full p-2" src="{{ fullAvatar .UserDid }}" />
</div>
</div>
<div class="col-span-2">
<div class="flex items-center flex-row flex-nowrap gap-2">
-
<p
-
title="{{ didOrHandle .UserDid .UserHandle }}"
-
class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap">
+
<p title="{{ didOrHandle .UserDid .UserHandle }}"
+
class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap">
{{ didOrHandle .UserDid .UserHandle }}
</p>
-
<a href="/{{ didOrHandle .UserDid .UserHandle }}/feed.atom">
-
{{ i "rss" "size-4" }}
-
</a>
+
<a href="/{{ didOrHandle .UserDid .UserHandle }}/feed.atom">{{ i "rss" "size-4" }}</a>
</div>
<div class="md:hidden">
-
{{ block "followerFollowing" (list .Followers .Following) }}{{ end }}
+
{{ block "followerFollowing" (list .Followers .Following) }} {{ end }}
</div>
</div>
<div class="col-span-3 md:col-span-full">
<div id="profile-bio" class="text-sm">
{{ $profile := .Profile }}
{{ with .Profile }}
-
{{ if .Description }}
-
<p class="text-base pb-4 md:pb-2">{{ .Description }}</p>
-
{{ end }}
+
{{ if .Description }}
+
<p class="text-base pb-4 md:pb-2">{{ .Description }}</p>
+
{{ end }}
-
<div class="hidden md:block">
-
{{ block "followerFollowing" (list $.Followers $.Following) }}
-
{{ end }}
+
<div class="hidden md:block">
+
{{ block "followerFollowing" (list $.Followers $.Following) }} {{ end }}
+
</div>
+
+
<div class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
+
{{ if .Location }}
+
<div class="flex items-center gap-2">
+
<span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span>
+
<span>{{ .Location }}</span>
</div>
-
-
<div
-
class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full">
-
{{ if .Location }}
-
<div class="flex items-center gap-2">
-
<span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span>
-
<span>{{ .Location }}</span>
-
</div>
+
{{ end }}
+
{{ if .IncludeBluesky }}
+
<div class="flex items-center gap-2">
+
<span class="flex-shrink-0">{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" }}</span>
+
<a id="bluesky-link" href="https://bsky.app/profile/{{ $.UserDid }}">{{ didOrHandle $.UserDid $.UserHandle }}</a>
+
</div>
+
{{ end }}
+
{{ range $link := .Links }}
+
{{ if $link }}
+
<div class="flex items-center gap-2">
+
<span class="flex-shrink-0">{{ i "link" "size-4" }}</span>
+
<a href="{{ $link }}">{{ $link }}</a>
+
</div>
{{ end }}
-
{{ if .IncludeBluesky }}
-
<div class="flex items-center gap-2">
-
<span class="flex-shrink-0">
-
{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" }}
-
</span>
-
<a
-
id="bluesky-link"
-
href="https://bsky.app/profile/{{ $.UserDid }}">
-
{{ didOrHandle $.UserDid $.UserHandle }}
-
</a>
-
</div>
-
{{ end }}
-
{{ range $link := .Links }}
-
{{ if $link }}
-
<div class="flex items-center gap-2">
-
<span class="flex-shrink-0">{{ i "link" "size-4" }}</span>
-
<a href="{{ $link }}">{{ $link }}</a>
+
{{ end }}
+
{{ if not $profile.IsStatsEmpty }}
+
<div class="flex items-center justify-evenly gap-2 py-2">
+
{{ range $stat := .Stats }}
+
{{ if $stat.Kind }}
+
<div class="flex flex-col items-center gap-2">
+
<span class="text-xl font-bold">{{ $stat.Value }}</span>
+
<span>{{ $stat.Kind.String }}</span>
</div>
{{ end }}
{{ end }}
-
{{ if not $profile.IsStatsEmpty }}
-
<div class="flex items-center justify-evenly gap-2 py-2">
-
{{ range $stat := .Stats }}
-
{{ if $stat.Kind }}
-
<div class="flex flex-col items-center gap-2">
-
<span class="text-xl font-bold">{{ $stat.Value }}</span>
-
<span>{{ $stat.Kind.String }}</span>
-
</div>
-
{{ end }}
-
{{ end }}
-
</div>
-
{{ end }}
</div>
+
{{ end }}
+
</div>
{{ end }}
{{ if ne .FollowStatus.String "IsSelf" }}
{{ template "user/fragments/follow" . }}
{{ else }}
-
<button
-
id="editBtn"
+
<button id="editBtn"
class="btn mt-2 w-full flex items-center gap-2 group"
hx-target="#profile-bio"
hx-get="/profile/edit-bio"
···
{{ define "followerFollowing" }}
{{ $followers := index . 0 }}
{{ $following := index . 1 }}
-
<div
-
class="flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
+
<div class="flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full text-sm">
<span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
<span id="followers">{{ $followers }} followers</span>
<span class="select-none after:content-['·']"></span>
<span id="following">{{ $following }} following</span>
</div>
{{ end }}
+
+3 -7
appview/pages/templates/user/fragments/repoCard.html
···
{{ $fullName := index . 2 }}
{{ with $repo }}
-
<div
-
class="py-4 px-6 gap-2 flex flex-col drop-shadow-sm rounded bg-white dark:bg-gray-800">
+
<div class="py-4 px-6 gap-2 flex flex-col drop-shadow-sm rounded bg-white dark:bg-gray-800">
<div class="font-medium dark:text-white flex items-center">
{{ if .Source }}
{{ i "git-fork" "w-4 h-4 mr-1.5 shrink-0" }}
···
{{ $repoOwner := resolve .Did }}
{{- if $fullName -}}
-
<a href="/{{ $repoOwner }}/{{ .Name }}">
-
{{ $repoOwner }}/{{ .Name }}
-
</a>
+
<a href="/{{ $repoOwner }}/{{ .Name }}">{{ $repoOwner }}/{{ .Name }}</a>
{{- else -}}
<a href="/{{ $repoOwner }}/{{ .Name }}">{{ .Name }}</a>
{{- end -}}
···
<div class="text-gray-400 text-sm font-mono inline-flex gap-4 mt-auto">
{{ with .Language }}
<div class="flex gap-2 items-center text-sm">
-
<div
-
class="size-2 rounded-full"
+
<div class="size-2 rounded-full"
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>
<span>{{ . }}</span>
</div>
+59 -67
appview/pages/templates/user/login.html
···
{{ define "user/login" }}
-
<!doctype html>
-
<html lang="en" class="dark:bg-gray-900">
-
<head>
-
<meta charset="UTF-8" />
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-
<meta property="og:title" content="login · tangled" />
-
<meta property="og:url" content="https://tangled.sh/login" />
-
<meta property="og:description" content="login to for tangled" />
-
<script src="/static/htmx.min.js"></script>
-
<link
-
rel="stylesheet"
-
href="/static/tw.css?{{ cssContentHash }}"
-
type="text/css" />
-
<title>login &middot; tangled</title>
-
</head>
-
<body class="flex items-center justify-center min-h-screen">
-
<main class="max-w-md px-6 -mt-4">
-
<h1 class="text-center text-2xl font-semibold italic dark:text-white">
-
tangled
-
</h1>
-
<h2 class="text-center text-xl italic dark:text-white">
-
tightly-knit social coding.
-
</h2>
-
<form
-
class="mt-4 max-w-sm mx-auto"
-
hx-post="/login"
-
hx-swap="none"
-
hx-disabled-elt="#login-button">
-
<div class="flex flex-col">
-
<label for="handle">handle</label>
-
<input
-
type="text"
-
id="handle"
-
name="handle"
-
tabindex="1"
-
required
-
placeholder="akshay.tngl.sh" />
-
<span class="text-sm text-gray-500 mt-1">
-
Use your
-
<a href="https://atproto.com">ATProto</a>
-
handle to log in. If you're unsure, this is likely your Tangled (
-
<code>.tngl.sh</code>
-
) or
-
<a href="https://bsky.app">Bluesky</a>
-
(
-
<code>.bsky.social</code>
-
) account.
-
</span>
-
</div>
-
<input type="hidden" name="return_url" value="{{ .ReturnUrl }}" />
+
<!doctype html>
+
<html lang="en" class="dark:bg-gray-900">
+
<head>
+
<meta charset="UTF-8" />
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+
<meta property="og:title" content="login · tangled" />
+
<meta property="og:url" content="https://tangled.sh/login" />
+
<meta property="og:description" content="login to for tangled" />
+
<script src="/static/htmx.min.js"></script>
+
<link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" />
+
<title>login &middot; tangled</title>
+
</head>
+
<body class="flex items-center justify-center min-h-screen">
+
<main class="max-w-md px-6 -mt-4">
+
<h1 class="text-center text-2xl font-semibold italic dark:text-white" >
+
tangled
+
</h1>
+
<h2 class="text-center text-xl italic dark:text-white">
+
tightly-knit social coding.
+
</h2>
+
<form
+
class="mt-4 max-w-sm mx-auto"
+
hx-post="/login"
+
hx-swap="none"
+
hx-disabled-elt="#login-button"
+
>
+
<div class="flex flex-col">
+
<label for="handle">handle</label>
+
<input
+
type="text"
+
id="handle"
+
name="handle"
+
tabindex="1"
+
required
+
placeholder="akshay.tngl.sh"
+
/>
+
<span class="text-sm text-gray-500 mt-1">
+
Use your <a href="https://atproto.com">ATProto</a>
+
handle to log in. If you're unsure, this is likely
+
your Tangled (<code>.tngl.sh</code>) or <a href="https://bsky.app">Bluesky</a> (<code>.bsky.social</code>) account.
+
</span>
+
</div>
+
<input type="hidden" name="return_url" value="{{ .ReturnUrl }}">
-
<button
-
class="btn w-full my-2 mt-6 text-base "
-
type="submit"
-
id="login-button"
-
tabindex="3">
-
<span>login</span>
-
</button>
-
</form>
-
<p class="text-sm text-gray-500">
-
Don't have an account?
-
<a href="/signup" class="underline">Create an account</a>
-
on Tangled now!
-
</p>
+
<button
+
class="btn w-full my-2 mt-6 text-base "
+
type="submit"
+
id="login-button"
+
tabindex="3"
+
>
+
<span>login</span>
+
</button>
+
</form>
+
<p class="text-sm text-gray-500">
+
Don't have an account? <a href="/signup" class="underline">Create an account</a> on Tangled now!
+
</p>
-
<p id="login-msg" class="error w-full"></p>
-
</main>
-
</body>
-
</html>
+
<p id="login-msg" class="error w-full"></p>
+
</main>
+
</body>
+
</html>
{{ end }}
+66 -112
appview/pages/templates/user/profile.html
···
{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }}
{{ define "extrameta" }}
-
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
-
<meta property="og:type" content="profile" />
-
<meta
-
property="og:url"
-
content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
-
<meta
-
property="og:description"
-
content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
+
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" />
+
<meta property="og:type" content="profile" />
+
<meta property="og:url" content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}" />
+
<meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
{{ end }}
{{ define "content" }}
-
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
+
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
<div class="md:col-span-3 order-1 md:order-1">
<div class="grid grid-cols-1 gap-4">
{{ template "user/fragments/profileCard" .Card }}
-
{{ block "punchcard" .Punchcard }}{{ end }}
+
{{ block "punchcard" .Punchcard }} {{ end }}
</div>
</div>
<div id="all-repos" class="md:col-span-4 order-2 md:order-2">
···
</div>
</div>
<div class="md:col-span-4 order-3 md:order-3">
-
{{ block "profileTimeline" . }}{{ end }}
+
{{ block "profileTimeline" . }}{{ end }}
</div>
-
</div>
+
</div>
{{ end }}
{{ define "profileTimeline" }}
···
{{ with .ProfileTimeline }}
{{ range $idx, $byMonth := .ByMonth }}
{{ with $byMonth }}
-
<div
-
class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm">
-
{{ if eq $idx 0 }}
+
<div class="bg-white dark:bg-gray-800 px-6 py-4 rounded drop-shadow-sm">
+
{{ if eq $idx 0 }}
-
{{ else }}
-
{{ $s := "s" }}
-
{{ if eq $idx 1 }}
-
{{ $s = "" }}
-
{{ end }}
-
<p class="text-sm font-bold dark:text-white mb-2">
-
{{ $idx }} month{{ $s }} ago
-
</p>
+
{{ else }}
+
{{ $s := "s" }}
+
{{ if eq $idx 1 }}
+
{{ $s = "" }}
{{ end }}
+
<p class="text-sm font-bold dark:text-white mb-2">{{$idx}} month{{$s}} ago</p>
+
{{ end }}
-
{{ if .IsEmpty }}
-
<div class="text-gray-500 dark:text-gray-400">
-
No activity for this month
-
</div>
-
{{ else }}
-
<div class="flex flex-col gap-1">
-
{{ block "repoEvents" .RepoEvents }}{{ end }}
-
{{ block "issueEvents" .IssueEvents }}{{ end }}
-
{{ block "pullEvents" .PullEvents }}{{ end }}
-
</div>
-
{{ end }}
-
</div>
+
{{ if .IsEmpty }}
+
<div class="text-gray-500 dark:text-gray-400">
+
No activity for this month
+
</div>
+
{{ else }}
+
<div class="flex flex-col gap-1">
+
{{ block "repoEvents" .RepoEvents }} {{ end }}
+
{{ block "issueEvents" .IssueEvents }} {{ end }}
+
{{ block "pullEvents" .PullEvents }} {{ end }}
+
</div>
+
{{ end }}
+
</div>
+
{{ end }}
{{ else }}
<p class="dark:text-white">This user does not have any activity yet.</p>
···
{{ define "repoEvents" }}
{{ if gt (len .) 0 }}
<details>
-
<summary
-
class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
+
<summary class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
<div class="flex flex-wrap items-center gap-2">
{{ i "book-plus" "w-4 h-4" }}
-
created
-
{{ len . }}
-
{{ if eq (len .) 1 }}repository{{ else }}repositories{{ end }}
+
created {{ len . }} {{if eq (len .) 1 }}repository{{else}}repositories{{end}}
</div>
</summary>
<div class="py-2 text-sm flex flex-col gap-3 mb-2">
···
{{ i "book-plus" "w-4 h-4" }}
{{ end }}
</span>
-
<a
-
href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}"
-
class="no-underline hover:underline">
+
<a href="/{{ resolve .Repo.Did }}/{{ .Repo.Name }}" class="no-underline hover:underline">
{{- .Repo.Name -}}
</a>
</div>
···
{{ if gt (len $items) 0 }}
<details>
-
<summary
-
class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
+
<summary class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
<div class="flex flex-wrap items-center gap-2">
{{ i "circle-dot" "w-4 h-4" }}
-
<div>
-
created
-
{{ len $items }}
-
{{ if eq (len $items) 1 }}issue{{ else }}issues{{ end }}
+
created {{ len $items }} {{if eq (len $items) 1 }}issue{{else}}issues{{end}}
</div>
{{ if gt $stats.Open 0 }}
-
<span
-
class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
-
{{ $stats.Open }} open
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
+
{{$stats.Open}} open
</span>
{{ end }}
{{ if gt $stats.Closed 0 }}
-
<span
-
class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
-
{{ $stats.Closed }} closed
-
</span>
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
+
{{$stats.Closed}} closed
+
</span>
{{ end }}
</div>
···
{{ $repoName := .Metadata.Repo.Name }}
{{ $repoUrl := printf "%s/%s" $repoOwner $repoName }}
-
<div class="flex gap-2 text-gray-600 dark:text-gray-300">
{{ if .Open }}
<span class="text-green-600 dark:text-green-500">
···
</span>
{{ end }}
<div class="flex-none min-w-8 text-right">
-
<span class="text-gray-500 dark:text-gray-400">
-
#{{ .IssueId }}
-
</span>
+
<span class="text-gray-500 dark:text-gray-400">#{{ .IssueId }}</span>
</div>
<div class="break-words max-w-full">
-
<a
-
href="/{{ $repoUrl }}/issues/{{ .IssueId }}"
-
class="no-underline hover:underline">
+
<a href="/{{$repoUrl}}/issues/{{ .IssueId }}" class="no-underline hover:underline">
{{ .Title -}}
</a>
on
-
<a
-
href="/{{ $repoUrl }}"
-
class="no-underline hover:underline whitespace-nowrap">
-
{{ $repoUrl }}
+
<a href="/{{$repoUrl}}" class="no-underline hover:underline whitespace-nowrap">
+
{{$repoUrl}}
</a>
</div>
</div>
···
{{ $stats := .Stats }}
{{ if gt (len $items) 0 }}
<details>
-
<summary
-
class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
+
<summary class="list-none cursor-pointer hover:text-gray-500 hover:dark:text-gray-400">
<div class="flex flex-wrap items-center gap-2">
{{ i "git-pull-request" "w-4 h-4" }}
-
<div>
-
created
-
{{ len $items }}
-
{{ if eq (len $items) 1 }}
-
pull request
-
{{ else }}
-
pull requests
-
{{ end }}
+
created {{ len $items }} {{if eq (len $items) 1 }}pull request{{else}}pull requests{{end}}
</div>
{{ if gt $stats.Open 0 }}
-
<span
-
class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
-
{{ $stats.Open }} open
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-green-600 dark:bg-green-700">
+
{{$stats.Open}} open
</span>
{{ end }}
{{ if gt $stats.Merged 0 }}
-
<span
-
class="px-2 py-1/2 text-sm rounded text-white bg-purple-600 dark:bg-purple-700">
-
{{ $stats.Merged }} merged
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-purple-600 dark:bg-purple-700">
+
{{$stats.Merged}} merged
</span>
{{ end }}
+
{{ if gt $stats.Closed 0 }}
-
<span
-
class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
-
{{ $stats.Closed }} closed
-
</span>
+
<span class="px-2 py-1/2 text-sm rounded text-white bg-gray-800 dark:bg-gray-700">
+
{{$stats.Closed}} closed
+
</span>
{{ end }}
</div>
···
{{ $repoName := .Repo.Name }}
{{ $repoUrl := printf "%s/%s" $repoOwner $repoName }}
-
<div class="flex gap-2 text-gray-600 dark:text-gray-300">
{{ if .State.IsOpen }}
<span class="text-green-600 dark:text-green-500">
···
</span>
{{ end }}
<div class="flex-none min-w-8 text-right">
-
<span class="text-gray-500 dark:text-gray-400">
-
#{{ .PullId }}
-
</span>
+
<span class="text-gray-500 dark:text-gray-400">#{{ .PullId }}</span>
</div>
<div class="break-words max-w-full">
-
<a
-
href="/{{ $repoUrl }}/pulls/{{ .PullId }}"
-
class="no-underline hover:underline">
+
<a href="/{{$repoUrl}}/pulls/{{ .PullId }}" class="no-underline hover:underline">
{{ .Title -}}
</a>
on
-
<a
-
href="/{{ $repoUrl }}"
-
class="no-underline hover:underline whitespace-nowrap">
-
{{ $repoUrl }}
+
<a href="/{{$repoUrl}}" class="no-underline hover:underline whitespace-nowrap">
+
{{$repoUrl}}
</a>
</div>
</div>
···
{{ define "ownRepos" }}
<div>
-
<div
-
class="text-sm font-bold p-2 pr-0 dark:text-white flex items-center justify-between gap-2">
-
<a
-
href="/@{{ or $.Card.UserHandle $.Card.UserDid }}?tab=repos"
+
<div class="text-sm font-bold p-2 pr-0 dark:text-white flex items-center justify-between gap-2">
+
<a href="/@{{ or $.Card.UserHandle $.Card.UserDid }}?tab=repos"
class="flex text-black dark:text-white items-center gap-2 no-underline hover:no-underline group">
<span>PINNED REPOS</span>
-
<span
-
class="flex gap-1 items-center font-normal text-sm text-gray-500 dark:text-gray-400 ">
-
view all
-
{{ i "chevron-right" "w-4 h-4" }}
+
<span class="flex gap-1 items-center font-normal text-sm text-gray-500 dark:text-gray-400 ">
+
view all {{ i "chevron-right" "w-4 h-4" }}
</span>
</a>
{{ if and .LoggedInUser (eq .LoggedInUser.Did .Card.UserDid) }}
-
<button
+
<button
hx-get="profile/edit-pins"
hx-target="#all-repos"
class="btn py-0 font-normal text-sm flex gap-2 items-center group">
···
{{ range .Repos }}
{{ template "user/fragments/repoCard" (list $ . false) }}
{{ else }}
-
<p class="px-6 dark:text-white">
-
This user does not have any repos yet.
-
</p>
+
<p class="px-6 dark:text-white">This user does not have any repos yet.</p>
{{ end }}
</div>
</div>
···
{{ range .CollaboratingRepos }}
{{ template "user/fragments/repoCard" (list $ . true) }}
{{ else }}
-
<p class="px-6 dark:text-white">This user is not collaborating.</p>
+
<p class="px-6 dark:text-white">This user is not collaborating.</p>
{{ end }}
</div>
</div>
···
<div class="w-full h-full flex justify-center items-center">
<div
class="aspect-square rounded-full transition-all duration-300 {{ $theme }} max-w-full max-h-full"
-
title="{{ .Date.Format "2006-01-02" }}: {{ .Count }} commits"></div>
+
title="{{ .Date.Format "2006-01-02" }}: {{ .Count }} commits">
+
</div>
</div>
{{ end }}
</div>
+11 -17
appview/pages/templates/user/repos.html
···
-
{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos{{ end }}
+
{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos {{ end }}
{{ define "extrameta" }}
-
<meta
-
property="og:title"
-
content="{{ or .Card.UserHandle .Card.UserDid }}'s repos" />
-
<meta property="og:type" content="object" />
-
<meta
-
property="og:url"
-
content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}/repos" />
-
<meta
-
property="og:description"
-
content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
+
<meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}'s repos" />
+
<meta property="og:type" content="object" />
+
<meta property="og:url" content="https://tangled.sh/{{ or .Card.UserHandle .Card.UserDid }}/repos" />
+
<meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" />
{{ end }}
{{ define "content" }}
-
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
+
<div class="grid grid-cols-1 md:grid-cols-11 gap-4">
<div class="md:col-span-3 order-1 md:order-1">
-
{{ template "user/fragments/profileCard" .Card }}
+
{{ template "user/fragments/profileCard" .Card }}
</div>
<div id="all-repos" class="md:col-span-8 order-2 md:order-2">
-
{{ block "ownRepos" . }}{{ end }}
+
{{ block "ownRepos" . }}{{ end }}
</div>
-
</div>
+
</div>
{{ end }}
{{ define "ownRepos" }}
<p class="text-sm font-bold p-2 dark:text-white">ALL REPOSITORIES</p>
<div id="repos" class="grid grid-cols-1 gap-4 mb-6">
{{ range .Repos }}
-
{{ template "user/fragments/repoCard" (list $ . false) }}
+
{{ template "user/fragments/repoCard" (list $ . false) }}
{{ else }}
-
<p class="px-6 dark:text-white">This user does not have any repos yet.</p>
+
<p class="px-6 dark:text-white">This user does not have any repos yet.</p>
{{ end }}
</div>
{{ end }}
+50 -60
appview/pages/templates/user/signup.html
···
{{ define "user/signup" }}
-
<!doctype html>
-
<html lang="en" class="dark:bg-gray-900">
-
<head>
-
<meta charset="UTF-8" />
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-
<meta property="og:title" content="signup · tangled" />
-
<meta property="og:url" content="https://tangled.sh/signup" />
-
<meta property="og:description" content="sign up for tangled" />
-
<script src="/static/htmx.min.js"></script>
-
<link
-
rel="stylesheet"
-
href="/static/tw.css?{{ cssContentHash }}"
-
type="text/css" />
-
<title>sign up &middot; tangled</title>
-
</head>
-
<body class="flex items-center justify-center min-h-screen">
-
<main class="max-w-md px-6 -mt-4">
-
<h1 class="text-center text-2xl font-semibold italic dark:text-white">
-
tangled
-
</h1>
-
<h2 class="text-center text-xl italic dark:text-white">
-
tightly-knit social coding.
-
</h2>
-
<form
-
class="mt-4 max-w-sm mx-auto"
-
hx-post="/signup"
-
hx-swap="none"
-
hx-disabled-elt="#signup-button">
-
<div class="flex flex-col mt-2">
-
<label for="email">email</label>
-
<input
-
type="email"
-
id="email"
-
name="email"
-
tabindex="4"
-
required
-
placeholder="jason@bourne.co" />
-
</div>
-
<span class="text-sm text-gray-500 mt-1">
-
You will receive an email with an invite code. Enter your invite
-
code, desired username, and password in the next page to complete
-
your registration.
-
</span>
-
<button
-
class="btn text-base w-full my-2 mt-6"
-
type="submit"
-
id="signup-button"
-
tabindex="7">
-
<span>join now</span>
-
</button>
-
</form>
-
<p class="text-sm text-gray-500">
-
Already have an ATProto account?
-
<a href="/login" class="underline">Login to Tangled</a>
-
.
-
</p>
+
<!doctype html>
+
<html lang="en" class="dark:bg-gray-900">
+
<head>
+
<meta charset="UTF-8" />
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+
<meta property="og:title" content="signup · tangled" />
+
<meta property="og:url" content="https://tangled.sh/signup" />
+
<meta property="og:description" content="sign up for tangled" />
+
<script src="/static/htmx.min.js"></script>
+
<link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" />
+
<title>sign up &middot; tangled</title>
+
</head>
+
<body class="flex items-center justify-center min-h-screen">
+
<main class="max-w-md px-6 -mt-4">
+
<h1 class="text-center text-2xl font-semibold italic dark:text-white" >tangled</h1>
+
<h2 class="text-center text-xl italic dark:text-white">tightly-knit social coding.</h2>
+
<form
+
class="mt-4 max-w-sm mx-auto"
+
hx-post="/signup"
+
hx-swap="none"
+
hx-disabled-elt="#signup-button"
+
>
+
<div class="flex flex-col mt-2">
+
<label for="email">email</label>
+
<input
+
type="email"
+
id="email"
+
name="email"
+
tabindex="4"
+
required
+
placeholder="jason@bourne.co"
+
/>
+
</div>
+
<span class="text-sm text-gray-500 mt-1">
+
You will receive an email with an invite code. Enter your
+
invite code, desired username, and password in the next
+
page to complete your registration.
+
</span>
+
<button class="btn text-base w-full my-2 mt-6" type="submit" id="signup-button" tabindex="7" >
+
<span>join now</span>
+
</button>
+
</form>
+
<p class="text-sm text-gray-500">
+
Already have an ATProto account? <a href="/login" class="underline">Login to Tangled</a>.
+
</p>
-
<p id="signup-msg" class="error w-full"></p>
-
</main>
-
</body>
-
</html>
+
<p id="signup-msg" class="error w-full"></p>
+
</main>
+
</body>
+
</html>
{{ end }}
+