1
0
Fork 0
forked from 2sys/phonograph
phonograph/svelte/src/table-viewer.webc/index.svelte

79 lines
1.9 KiB
Svelte
Raw Normal View History

<svelte:options
customElement={{
props: {
columns: { type: "Array" },
subfilter: { type: "String" },
},
shadow: "none",
tag: "table-viewer",
}}
/>
<!--
@component
Top-level web component for the tabular viewing and editing interface for
Phonograph portals. Parses HTML attributes, fetches data, and renders the
interactive interface implemented by the `<HydratedTableViewer>` Svelte
component.
-->
<script lang="ts">
import { z } from "zod";
import { datum_schema } from "../datum.svelte";
import { type Row, type FieldInfo, field_info_schema } from "../field.svelte";
import HydratedTableViewer from "./hydrated-table-viewer.svelte";
type Props = {
columns?: {
name: string;
regtype: string;
}[];
subfilter?: string;
};
let { columns = [], subfilter = "null" }: Props = $props();
type LazyData = {
count: number;
rows: Row[];
fields: FieldInfo[];
};
let lazy_data = $state<LazyData | undefined>();
(async function () {
const get_data_response_schema = z.object({
count: z.number().int(),
rows: z.array(
z.object({
pkey: z.string(),
data: z.array(datum_schema),
}),
),
fields: z.array(field_info_schema),
});
const resp = await fetch(
`get-data?subfilter=${encodeURIComponent(subfilter)}`,
);
const body = get_data_response_schema.parse(await resp.json());
lazy_data = {
count: body.count,
fields: body.fields,
rows: body.rows.map(({ data, pkey }) => ({ data, key: pkey })),
};
})().catch(console.error);
</script>
<div class="table-viewer__layout">
{#if lazy_data}
<HydratedTableViewer
{columns}
fields={lazy_data.fields}
rows_main={lazy_data.rows}
subfilter_active={!!subfilter && subfilter !== "null"}
total_count={lazy_data.count}
/>
{/if}
</div>