Files
os.semilabs.org/src/routes/packages/+page.svelte
T
sisungo d5a4a2a4da initial commit
Signed-off-by: sisungo <[email protected]>
2026-08-07 16:25:11 +08:00

96 lines
4.1 KiB
Svelte

<script lang="ts">
import { Button } from "$lib/components/ui/button/index.js";
import * as Card from "$lib/components/ui/card/index.js";
import Checkbox from "$lib/components/ui/checkbox/checkbox.svelte";
import { Input } from "$lib/components/ui/input/index.js";
import * as Select from "$lib/components/ui/select/index.js";
import * as Table from "$lib/components/ui/table/index.js";
import { SvelteMap } from "svelte/reactivity";
import * as m from "$lib/paraglide/messages";
import { getRepoDb, searchPackages, type PkgIdent, baseUrlForMirror, strPkgIdent } from "./helper.ts";
let showLatestOnly = $state(false);
let filterArchitecture = $state("");
let selectedMirror = $state("mirror1.semilabs.org");
let searchKeyword = $state("");
let results = $state<Array<PkgIdent>>([]);
async function search() {
const baseUrl = baseUrlForMirror(selectedMirror);
const repo = await getRepoDb(`${baseUrl}/repo.db`);
results = searchPackages(repo, searchKeyword);
if (filterArchitecture) {
results = results.filter((item) => item.arch === filterArchitecture || item.arch === "any");
}
if (showLatestOnly) {
const latestResults = new SvelteMap<string, PkgIdent>();
for (const item of results) {
const existing = latestResults.get(item.name);
if (!existing || item.version > existing.version) {
latestResults.set(item.name, item);
}
}
results = Array.from(latestResults.values());
}
}
</script>
<div class="ml-4 mr-4">
<Card.Root>
<Card.Header>
<Card.Title>{m.packages_search_title()}</Card.Title>
</Card.Header>
<Card.Content class="flex flex-col gap-4">
<Select.Root type="single" bind:value={selectedMirror}>
<Select.Trigger class="w-[180px]">{m.packages_mirror_select()}</Select.Trigger>
<Select.Content>
<Select.Item value="mirror1.semilabs.org">mirror1.semilabs.org</Select.Item>
<Select.Item value="mirror2.semilabs.org">mirror2.semilabs.org</Select.Item>
</Select.Content>
</Select.Root>
<Input placeholder={m.packages_search_keyword()} bind:value={searchKeyword} class="w-1/2" />
<div class="flex items-center gap-4">
<Select.Root type="single" bind:value={filterArchitecture}>
<Select.Trigger class="w-[180px]">{m.packages_arch_select()}</Select.Trigger>
<Select.Content>
<Select.Item value="aarch64-semios-linux">aarch64-semios-linux</Select.Item>
<Select.Item value="x86_64-semios-linux">x86_64-semios-linux</Select.Item>
</Select.Content>
</Select.Root>
<div class="flex items-center gap-2">
<Checkbox bind:checked={showLatestOnly} />
<span>{m.packages_show_latest_only()}</span>
</div>
</div>
</Card.Content>
<Card.Footer>
<Button variant="default" onclick={search}>
{m.packages_search_action()}
</Button>
</Card.Footer>
</Card.Root>
<div class="mt-4 overflow-x-auto">
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head>{m.packages_name()}</Table.Head>
<Table.Head>{m.packages_version()}</Table.Head>
<Table.Head>{m.packages_arch()}</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each results as item}
<Table.Row>
<Table.Cell><a href={`/packages/pkginfo/?pkgIdent=${strPkgIdent(item)}&mirrorName=${selectedMirror}`}>{item.name}</a></Table.Cell>
<Table.Cell>{item.version}</Table.Cell>
<Table.Cell>{item.arch}</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</div>
</div>