diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 9e5a452..49de2f8 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -213,6 +213,24 @@ export async function fetchEntities(filters: EntityFilters = {}): Promise { + const all: Entity[] = [] + let cursor: string | undefined + do { + const params = new URLSearchParams({ limit: '200' }) + if (cursor) params.set('cursor', cursor) + const res = await fetchWithAuth(`${API}/entities?${params}`) + if (!res.ok) break + const data = await res.json() + all.push(...(data.items ?? [])) + cursor = data.next_cursor ?? undefined + } while (cursor) + return all +} + export type OntologyLayer = 'meta' | 'infrastructure' | 'governance' | 'cognition' export interface EntityType { diff --git a/web/src/lib/categories.ts b/web/src/lib/categories.ts index 4850ca1..86e7566 100644 --- a/web/src/lib/categories.ts +++ b/web/src/lib/categories.ts @@ -3,18 +3,11 @@ // which lumps very different things (an LXC and a DNS record and a storage // volume) into one "infrastructure" bucket. Built from the ontology's // `domain` field instead, which already draws these lines; this just -// groups the domains into browsing-sized buckets. -import type { EntityFilters } from './api' - +// groups the domains into browsing-sized buckets. The Knowledge Base shows +// every entity at once now (filtered by the type multiselect, not by a +// fetch-time category), but "fleet" still names the default type selection. export type Category = 'network' | 'fleet' | 'identity' | 'knowledge' -export const categories: { id: Category; label: string }[] = [ - { id: 'fleet', label: 'Fleet' }, - { id: 'network', label: 'Network' }, - { id: 'identity', label: 'Identity' }, - { id: 'knowledge', label: 'Knowledge' } -] - // entity_types.domain -> Category. `external` folds into Network (isp-link, // domain-registration are network-adjacent); `physical`, `software`, and // `storage` fold into Fleet (ups/sensor/site support compute, services/apps @@ -49,15 +42,3 @@ export function typeToCategory(type: string, domain: string): Category | undefin if (domain === 'cognition') return undefined return DOMAIN_TO_CATEGORY[domain] } - -// Filter sets to fetch and merge for a category's table view. Most -// categories are one or two `domain` values; Knowledge is a handful of -// specific `type`s carved out of the (otherwise excluded) cognition domain. -export function filtersForCategory(category: Category): EntityFilters[] { - if (category === 'knowledge') { - return Array.from(KNOWLEDGE_TYPES).map((type) => ({ type })) - } - return Object.entries(DOMAIN_TO_CATEGORY) - .filter(([, c]) => c === category) - .map(([domain]) => ({ domain })) -} diff --git a/web/src/lib/components/EntityGraph.svelte b/web/src/lib/components/EntityGraph.svelte index e827b1b..64ff304 100644 --- a/web/src/lib/components/EntityGraph.svelte +++ b/web/src/lib/components/EntityGraph.svelte @@ -1,13 +1,11 @@
- -
-
- {#each categories as c} - - {/each} -
+ +
+ + + + {#if view === 'table'} +
+ + +
+ {filteredEntities.length} of {allEntities.length} + {:else} + + + + + + {graphInfo.visibleCount} nodes{graphInfo.truncated ? ' · truncated' : ''} · {graphInfo.zoomPct}% + + {/if}
- {#if view === 'table'} -
- - - - {typeFilter === 'all' ? 'All types' : typeFilter} - - - All types - {#each tableTypes as type} - {type} - {/each} - - -
- - -
- {filteredEntities.length} of {tableEntities.length} -
- {:else} -
- - - - - - - - {graphInfo.visibleCount} nodes{graphInfo.truncated ? ' · truncated' : ''} · {graphInfo.zoomPct}% - -
- {/if} -
{#if view === 'graph'} {:else} - + {/if}