| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- <script lang="ts">
- import { Toolbox } from '@lucide/svelte';
- import { SvelteSet } from 'svelte/reactivity';
- import { resolve } from '$app/paths';
- import { FilterList } from '$lib/components/common/filter-list';
- import * as Filters from '$lib/components/common/filters';
- import { ToolCard } from '$lib/components/tools/card';
- import { getBreadcrumbContext } from '$lib/stores/breadcrumb.svelte';
- import { toolsStore } from '$lib/stores/tools.svelte';
- import type { PageData } from './$types';
- const { data }: { data: PageData } = $props();
- let query = $state('');
- const allTags = $derived([...new Set(toolsStore.list.flatMap((m) => m.tags ?? []))].sort());
- const selectedTags = new SvelteSet<string>();
- let filters: Filters.FilterRow[] = $derived([
- {
- id: 'mode',
- type: 'single',
- label: 'Mode',
- options: [
- { value: 'all', label: 'All' },
- { value: 'external', label: 'External' },
- { value: 'managed', label: 'Managed' },
- ],
- selected: 'all',
- default: 'all',
- },
- ...(allTags.length > 0
- ? [
- {
- id: 'tags',
- type: 'multi' as const,
- label: 'Tags',
- options: allTags.map((t) => ({ value: t, label: t })),
- selected: selectedTags,
- },
- ]
- : []),
- ]);
- const filtered = $derived.by(() => {
- let list = toolsStore.list;
- const q = query.trim().toLowerCase();
- if (q) list = list.filter((t) => t.name.toLowerCase().includes(q));
- for (const filter of filters) {
- if (filter.id === 'mode') {
- list = list.filter((t) => (filter.selected === 'all' ? true : t.mode === filter.selected));
- } else if (filter.id === 'tags' && filter.type === 'multi') {
- if (filter.selected.size > 0)
- list = list.filter((t) => t.tags?.some((tag) => filter.selected.has(tag)));
- }
- }
- return list;
- });
- $effect.root(() => {
- toolsStore.hydrate(data.tools);
- });
- const breadcrumb = getBreadcrumbContext();
- $effect(() => {
- breadcrumb.set({ module: 'Tools', pages: [] });
- });
- </script>
- <svelte:head>
- <title>Tools - LocoStack</title>
- </svelte:head>
- <div class="mx-auto max-w-400">
- <FilterList
- creationLink={resolve('/workloads/tools/new')}
- itemCount={toolsStore.list.length}
- itemIcon={Toolbox}
- itemKey={(m) => m.id}
- itemName="tool"
- itemNamePlural="tools"
- items={filtered}
- bind:query
- bind:filters
- >
- {#snippet itemRenderer(tool)}
- <ToolCard {selectedTags} {tool} />
- {/snippet}
- </FilterList>
- </div>
|