~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
97 lines · 3.1 KB Raw History
<script lang="ts">
	import type { ActorView } from '#lib/lexicons/dev/knotless/defs.ts';
	import type * as addRunner from '#lib/lexicons/dev/knotless/addRunner.ts';
	import type * as removeRunner from '#lib/lexicons/dev/knotless/removeRunner.ts';
	import type { AtIdentifierString, AtUriString } from '@atproto/lex';
	import { call } from '#lib/data.ts';
	import Avatar from '#lib/atoms/Avatar.svelte';
	import Person from '#lib/molecules/Person.svelte';
	import Empty from '#lib/molecules/Empty.svelte';
	/**
	 * The runners the repository `repo` names: the accounts whose checks of
	 * it show, and who land its merge queue. Its owner, who `owns` it, adds
	 * and removes them, as `knotless runner list` does.
	 */
	let { repo, runners, owns }: { repo: AtUriString; runners: ActorView[]; owns: boolean } =
		$props();
	let named = $state<ActorView[] | null>(null);
	const shown = $derived(named ?? runners);
	let handle = $state('');
	let problem = $state('');
	let warning = $state('');
	// What is under way: 'add', or the runner being removed.
	let busy = $state('');
	async function change(runner: AtIdentifierString, add: boolean) {
		busy = add ? 'add' : runner;
		problem = '';
		warning = '';
		try {
			const nsid = add ? 'dev.knotless.addRunner' : 'dev.knotless.removeRunner';
			const after = await call<typeof addRunner.main | typeof removeRunner.main>(nsid, {
				repo,
				runner
			});
			named = after.runners;
			warning = after.warning ?? '';
			if (add) handle = '';
		} catch (e) {
			problem = (e as Error).message;
		}
		busy = '';
	}
	function submit(e: SubmitEvent) {
		e.preventDefault();
		if (handle.trim()) change(handle.trim() as AtIdentifierString, true);
	}
</script>

<div class="box runner-list">
	<div class="boxhead">
		<b>Runners</b><span class="mute"
			>The accounts a knotless runner reports as: their checks of this repository show, and they
			land its merge queue.</span
		>
	</div>
	{#if shown.length}
		<ul class="list">
			{#each shown as r (r.did)}
				<li>
					<Avatar name={r.handle} did={r.did} src={r.avatar} /><Person handle={r.handle} /><code
						class="mute clip">{r.did}</code
					>{#if owns}<button
							class="btn end"
							type="button"
							disabled={!!busy}
							aria-busy={busy === r.did}
							onclick={() => change(r.did as AtIdentifierString, false)}
							>{busy === r.did ? 'Removing…' : 'Remove'}</button
						>{/if}
				</li>
			{/each}
		</ul>
	{:else}
		<Empty title="No runners yet"
			>Nothing checks this repository's pushes and pulls, and merges wait for no checks.</Empty
		>
	{/if}
	{#if owns}
		<form class="boxhead boxfoot add-runner" onsubmit={submit}>
			<input
				name="runner"
				placeholder="runner.example.com"
				aria-label="The runner's handle or DID"
				autocapitalize="none"
				spellcheck="false"
				bind:value={handle}
			/>
			<button
				class="btn primary"
				type="submit"
				disabled={!!busy || !handle.trim()}
				aria-busy={busy === 'add'}>{busy === 'add' ? 'Adding…' : 'Add runner'}</button
			>
		</form>
	{/if}
	{#if problem}<p class="problem" role="alert">{problem}</p>{/if}
	{#if warning}<p class="warning" role="status">{warning}</p>{/if}
</div>