johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<script lang="ts">
import type * as getQueue from '#lib/lexicons/dev/knotless/getQueue.ts';
import type { QueueTypicalView } from '#lib/lexicons/dev/knotless/defs.ts';
import { ago, landsAt, landsIn, plural } from '#lib/format.ts';
import { zone } from '#lib/zone.svelte.ts';
import Icon from '#lib/atoms/Icon.svelte';
import Ref from '#lib/atoms/Ref.svelte';
import Time from '#lib/atoms/Time.svelte';
import CheckMark from '#lib/molecules/CheckMark.svelte';
import ItemRow from '#lib/molecules/ItemRow.svelte';
import Person from '#lib/molecules/Person.svelte';
/**
* A branch's merge queue, of the repository whose page is at `base`, in
* the order it lands: each batch being checked or landing, with its
* checks and its pulls, then the pulls waiting for one, each saying
* where it stands, with its own checks, and when it should land, by
* `typical`, how long the queue takes.
*/
let {
line,
base,
typical
}: { line: getQueue.BranchView; base: string; typical?: QueueTypicalView } = $props();
const waiting = $derived(line.pulls.filter((q) => q.batch === undefined));
const inBatch = (i: number) => line.pulls.filter((q) => q.batch === i);
/** When the newest batch being checked started: those waiting land after it. */
const ahead = $derived(
line.batches
.filter((b) => b.state === 'checking')
.map((b) => b.startedAt)
.filter((t) => t !== undefined)
.sort()
.at(-1)
);
/** When a pull waiting for a batch should land, before the rest of its line. */
const lands = (q: getQueue.QueuedView) => {
const at = q.batch === undefined ? landsAt(q, typical, undefined, ahead, zone.now) : null;
return at === null ? '' : `${landsIn(at)} · `;
};
/** When a batch should land, all its pulls together, after what is said of it. */
const batchLands = (b: getQueue.BatchView) => {
const at =
b.state === 'checking'
? landsAt({ stage: 'checking' }, typical, b.startedAt, undefined, zone.now)
: null;
return at === null ? '' : `, ${landsIn(at)}`;
};
</script>
{#snippet row(q: getQueue.QueuedView)}
<ItemRow item={q.pull} kind="pull" {base}>
{#snippet meta()}{#if q.batch === undefined}<span class="said">{q.said}</span
>{/if}{#if q.checks?.length}<CheckMark checks={q.checks} />{/if}<span
>{`${lands(q)}queued `}<Time
at={q.queuedAt}
show={(t) => ago(t, 'on ')}
/>{' · opened by'}</span
><Person handle={q.pull.author.handle} bot={q.pull.author.bot} />{/snippet}
</ItemRow>
{/snippet}
<div class="box queue-line">
<div class="boxhead">
<Icon name="queue" /><span>Into <Ref name={line.branch} /></span><span class="end mute"
>{plural(line.pulls.length, 'pull', 'pulls')} queued</span
>
</div>
{#each line.batches as b, i (b.commit)}
<div class="queue-group {b.state}">
<Icon name={b.state === 'landing' ? 'passed' : 'running'} />
<b>{b.state === 'landing' ? 'Landing' : 'Being checked'}</b>
<code class="sha">{b.commit.slice(0, 7)}</code>
{#if b.startedAt}<span class="mute"
>{`${plural(b.size, 'pull', 'pulls')}, started `}<Time
at={b.startedAt}
show={ago}
/>{batchLands(b)}</span
>{:else}<span class="mute">{plural(b.size, 'pull', 'pulls')}</span>{/if}
<span class="end"><CheckMark checks={b.checks} /></span>
</div>
<ul class="list">
{#each inBatch(i) as q (q.pull.uri)}{@render row(q)}{/each}
</ul>
{/each}
{#if waiting.length}
{#if line.batches.length}<div class="queue-group">
<Icon name="clock" /><b>Not in a batch yet</b>
</div>{/if}
<ul class="list">
{#each waiting as q (q.pull.uri)}{@render row(q)}{/each}
</ul>
{/if}
</div>