upend/webui/src/components/EntryView.svelte

150 lines
3.5 KiB
Svelte
Raw Normal View History

2023-06-16 16:30:17 +02:00
<script lang="ts" context="module">
export interface WidgetComponent {
component: ComponentType;
props: { [key: string]: unknown };
}
export interface Widget {
name: string;
icon?: string;
components: (input: {
entries: UpEntry[];
group?: string;
}) => Array<WidgetComponent>;
2023-06-16 16:30:17 +02:00
}
</script>
2021-11-11 23:37:42 +01:00
<script lang="ts">
2022-09-04 23:29:41 +02:00
import EntryList from "./widgets/EntryList.svelte";
import type { UpEntry } from "upend";
import Icon from "./utils/Icon.svelte";
import IconButton from "./utils/IconButton.svelte";
2023-06-16 16:30:17 +02:00
import { createEventDispatcher, type ComponentType } from "svelte";
import UpObject from "./display/UpObject.svelte";
2022-03-22 20:35:01 +01:00
const dispatch = createEventDispatcher();
2021-11-11 23:37:42 +01:00
export let entries: UpEntry[];
2022-09-06 00:10:24 +02:00
export let widgets: Widget[] | undefined = undefined;
2022-03-22 20:35:01 +01:00
export let initialWidget: string | undefined = undefined;
2023-06-16 16:30:17 +02:00
export let title: string | undefined = undefined;
export let group: string | undefined = undefined;
2023-06-16 16:30:17 +02:00
export let icon: string | undefined = undefined;
export let highlighted = false;
2023-06-16 16:30:17 +02:00
export let editable = false;
2021-11-11 23:37:42 +01:00
let currentWidget: string | undefined;
2021-11-11 23:37:42 +01:00
2022-03-22 20:35:01 +01:00
function switchWidget(widget: string) {
currentWidget = widget;
dispatch("widgetSwitched", currentWidget);
}
2021-11-11 23:37:42 +01:00
let availableWidgets: Widget[] = [];
$: {
availableWidgets = [
2022-01-28 22:27:02 +01:00
{
2023-06-16 16:30:17 +02:00
name: "Entry List",
2021-11-11 23:37:42 +01:00
icon: "table",
2023-06-16 16:30:17 +02:00
components: (entries) => [
2021-11-11 23:37:42 +01:00
{
2022-09-04 23:29:41 +02:00
component: EntryList,
2023-06-16 16:30:17 +02:00
props: { entries, columns: "entity, attribute, value" },
2021-11-11 23:37:42 +01:00
},
],
},
];
2022-09-04 23:29:41 +02:00
if (widgets?.length) {
availableWidgets = [...widgets, ...availableWidgets];
}
2022-03-22 20:35:01 +01:00
if (availableWidgets.map((w) => w.name).includes(initialWidget)) {
currentWidget = initialWidget;
} else {
currentWidget = availableWidgets[0].name;
}
2021-11-11 23:37:42 +01:00
}
2023-06-16 16:30:17 +02:00
let components: WidgetComponent[] = [];
2021-11-11 23:37:42 +01:00
$: {
2023-06-16 16:30:17 +02:00
components = availableWidgets
.find((w) => w.name === currentWidget)
.components({ entries, group });
2021-11-11 23:37:42 +01:00
}
</script>
2023-06-16 16:30:17 +02:00
<section class="entry-view labelborder" class:highlighted>
2021-11-11 23:37:42 +01:00
<header>
<h3>
{#if group}
{#if icon}
<div class="icon">
<Icon name={icon} />
</div>
{/if}
<UpObject link address={group} labels={title ? [title] : undefined} />
2023-07-09 19:28:15 +02:00
{:else}
{#if icon}
<div class="icon">
<Icon name={icon} />
</div>
{/if}
{title || ""}
2021-11-11 23:37:42 +01:00
{/if}
</h3>
{#if currentWidget && (availableWidgets.length > 1 || editable)}
2021-11-11 23:37:42 +01:00
<div class="views">
{#each availableWidgets as widget (widget.name)}
<IconButton
2023-06-16 16:30:17 +02:00
name={widget.icon || "cube"}
title={widget.name}
active={widget.name === currentWidget}
--active-color="var(--foreground)"
2023-07-29 16:45:35 +02:00
on:click={() => switchWidget(widget.name)}
2023-06-16 16:30:17 +02:00
>
2023-07-29 16:45:35 +02:00
{widget.name}
</IconButton>
2021-11-11 23:37:42 +01:00
{/each}
</div>
{/if}
</header>
2022-01-28 22:27:02 +01:00
<div class="content">
2023-06-16 16:30:17 +02:00
{#each components as component}
2022-10-22 17:25:45 +02:00
<svelte:component
2023-06-16 16:30:17 +02:00
this={component.component}
{...component.props || {}}
{editable}
on:change
2022-10-22 17:25:45 +02:00
/>
2023-06-16 16:30:17 +02:00
{/each}
2022-01-28 22:27:02 +01:00
</div>
2021-11-11 23:37:42 +01:00
</section>
<style scoped lang="scss">
@use "./util";
2021-11-11 23:37:42 +01:00
2023-06-16 16:30:17 +02:00
section.entry-view {
.icon {
display: inline-block;
font-size: 1.25em;
margin-top: -0.3em;
position: relative;
bottom: -2px;
}
h3 {
transition: text-shadow 0.2s;
}
2023-06-16 16:30:17 +02:00
&.highlighted h3 {
text-shadow: #cb4b16 0 0 0.5em;
}
}
2021-11-11 23:37:42 +01:00
.views {
display: flex;
font-size: 16px;
2021-11-11 23:37:42 +01:00
}
</style>