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

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
108 lines · 3.5 KB Raw History
<script lang="ts">
	import type * as listItems from '#lib/lexicons/dev/knotless/listItems.ts';
	import type { Answer } from '#lib/data.ts';
	import type { ItemView } from '#lib/lexicons/dev/knotless/defs.ts';
	import type { Paged } from '#lib/pages.svelte.ts';
	import { stateIcon } from '#lib/icons.ts';
	import { closed, filtered, filterHref, has, toggled, withState, withTerm } from '#lib/query.ts';
	import Icon from '#lib/atoms/Icon.svelte';
	import More from '#lib/atoms/More.svelte';
	import FilterMenu from '#lib/molecules/FilterMenu.svelte';
	import ItemRow from '#lib/molecules/ItemRow.svelte';
	import Empty from '#lib/molecules/Empty.svelte';
	/**
	 * A page of the pulls or issues of the repository whose page is at
	 * `base`, the `open` ones or the closed, that the filter `q` matches:
	 * the filter to change, a switch between open and closed, menus of the
	 * labels and authors to filter by, the `pages` shown so far and the way
	 * to the next, and for pulls the way to the merge queue; and the way to
	 * open another.
	 */
	let {
		items: list,
		pages,
		kind,
		open,
		base,
		queue,
		q = ''
	}: {
		items: Answer<typeof listItems.main>;
		pages: Paged<ItemView>;
		kind: 'pull' | 'issue';
		open: boolean;
		base: string;
		queue?: string;
		q?: string;
	} = $props();
	const label = $derived(kind === 'pull' ? 'pulls' : 'issues');
	// The filter as the page shows it, with its state when only `?state=` said it.
	const here = $derived(open || closed(q) ? q : withState(q, 'closed'));
	const labels = $derived(
		(list.labels ?? []).map((l) => ({
			name: l.name,
			color: l.color ?? '',
			on: has(q, 'label', l.name),
			href: filterHref(toggled(here, 'label', l.name))
		}))
	);
	const authors = $derived(
		(list.authors ?? []).map((a) => {
			const name = a.handle ?? a.did;
			return { name, on: has(q, 'author', name), href: filterHref(toggled(here, 'author', name)) };
		})
	);
</script>

<div class="list-top">
	<form class="query" role="search">
		<Icon name="search" /><input
			type="search"
			name="q"
			value={q}
			placeholder="label:kind/bug crash"
			aria-label="Filter {label}"
		/>
	</form>
	<a class="btn primary" href="{base}/{label}/new">{kind === 'pull' ? 'New pull' : 'New issue'}</a>
</div>
<div class="box items">
	<div class="boxhead" data-sveltekit-reset="false">
		<nav class="filter">
			<a href={filterHref(withState(here, 'open'))} aria-current={open ? 'page' : undefined}
				><Icon name={stateIcon(kind, 'open')} />{list.openCount} Open</a
			>
			<a href={filterHref(withState(here, 'closed'))} aria-current={open ? undefined : 'page'}
				><Icon name="done" />{list.closedCount} Closed</a
			>
		</nav>
		<div class="menus">
			{#if authors.length}<FilterMenu title="Author" options={authors} />{/if}
			{#if labels.length}<FilterMenu title="Labels" options={labels} />{/if}
		</div>
		{#if queue}<a class="end queue-link" href={queue} aria-label="Merge queue"
				><Icon name="queue" /><span>Merge queue</span></a
			>{/if}
	</div>
	<ul class="list">
		{#each pages.items as i (i.uri)}
			<ItemRow
				item={i}
				{kind}
				{base}
				labelHref={(name) => filterHref(withTerm(here, 'label', name))}
			/>
		{:else}
			<li class="blank">
				{#if filtered(q)}
					<Empty title="No {open ? 'open' : 'closed'} {label} match"
						><a href={filterHref(open ? '' : withState('', 'closed'))}>Clear the filter</a></Empty
					>
				{:else}
					<Empty title="No {open ? 'open' : 'closed'} {label}" />
				{/if}
			</li>
		{/each}
	</ul>
</div>
<More {pages} label="More {label}" />