👱♂️ Adds layout manager
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { WidgetComponents, type WidgetContainerConfig, isWidgetConfig } from './LayoutManager';
|
||||||
|
import Widget from './Widget.svelte';
|
||||||
|
|
||||||
|
export let container: WidgetContainerConfig;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="w-full h-full flex flex-col">
|
||||||
|
{#if container.header}
|
||||||
|
<div class="bg-base-300">
|
||||||
|
<div class="bg-base-100 p-2 w-min">{container.header}</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex w-full h-full"
|
||||||
|
class:flex-row={container.layout === 'column'}
|
||||||
|
class:flex-col={container.layout === 'row'}
|
||||||
|
>
|
||||||
|
{#each container.widgets as widget, index (widget.id + '-' + index)}
|
||||||
|
<Widget size={widget.size ?? 1}>
|
||||||
|
{#if isWidgetConfig(widget)}
|
||||||
|
<svelte:component this={WidgetComponents[widget.component]} {...widget.props} />
|
||||||
|
{:else if widget.widgets}
|
||||||
|
<svelte:self container={widget} />
|
||||||
|
{/if}
|
||||||
|
</Widget>
|
||||||
|
{#if index !== container.widgets.length - 1}
|
||||||
|
<div
|
||||||
|
class="divider bg-base-300 m-0"
|
||||||
|
class:divider-horizontal={container.layout === 'column'}
|
||||||
|
></div>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { persistentStore } from '$lib/utilities';
|
||||||
|
import Visualization from '$lib/components/Visualization.svelte';
|
||||||
|
import Stream from '$lib/components/Stream.svelte';
|
||||||
|
import CpuUsageChart from '$lib/components/widget/CpuUsageChart.svelte';
|
||||||
|
import type { Writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export interface WidgetConfig {
|
||||||
|
id: string | number;
|
||||||
|
component: keyof typeof WidgetComponents;
|
||||||
|
size?: number;
|
||||||
|
props?: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WidgetContainerConfig {
|
||||||
|
id: string | number;
|
||||||
|
layout: 'row' | 'column';
|
||||||
|
header?: string;
|
||||||
|
size?: number;
|
||||||
|
widgets: Array<WidgetConfig | WidgetContainerConfig>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isWidgetConfig = (
|
||||||
|
widget: WidgetConfig | WidgetContainerConfig
|
||||||
|
): widget is WidgetConfig => 'component' in widget;
|
||||||
|
|
||||||
|
export const WidgetComponents = {
|
||||||
|
Visualization,
|
||||||
|
Stream,
|
||||||
|
CpuUsageChart
|
||||||
|
};
|
||||||
|
|
||||||
|
export const controllerLayout: Writable<WidgetContainerConfig> = persistentStore(
|
||||||
|
'controller_layout',
|
||||||
|
{
|
||||||
|
id: 'root',
|
||||||
|
layout: 'column',
|
||||||
|
widgets: [
|
||||||
|
{
|
||||||
|
id: 'visualization',
|
||||||
|
layout: 'column',
|
||||||
|
header: 'Visualization',
|
||||||
|
size: 2,
|
||||||
|
widgets: [
|
||||||
|
{ id: 1, component: 'Visualization', size: 2, props: { debug: true } },
|
||||||
|
{ id: 2, component: 'Stream' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'charts',
|
||||||
|
layout: 'row',
|
||||||
|
header: 'Charts',
|
||||||
|
widgets: [
|
||||||
|
{ id: 3, component: 'CpuUsageChart' },
|
||||||
|
{ id: 4, component: 'CpuUsageChart' },
|
||||||
|
{ id: 5, component: 'CpuUsageChart' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} as WidgetContainerConfig
|
||||||
|
);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
export let size = 1;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="box-border overflow-hidden" style="flex: {size}">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { daisyColor } from "$lib/DaisyUiHelper";
|
||||||
|
import { Chart, registerables } from "chart.js";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { cubicOut } from "svelte/easing";
|
||||||
|
import { slide } from "svelte/transition";
|
||||||
|
|
||||||
|
let chartElement: HTMLCanvasElement;
|
||||||
|
let chart: Chart;
|
||||||
|
|
||||||
|
export let label
|
||||||
|
export let data:number[]
|
||||||
|
export let title
|
||||||
|
|
||||||
|
Chart.register(...registerables);
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
chart = new Chart(chartElement, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: data,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label,
|
||||||
|
borderColor: daisyColor('--p'),
|
||||||
|
backgroundColor: daisyColor('--p', 50),
|
||||||
|
borderWidth: 2,
|
||||||
|
data,
|
||||||
|
yAxisID: 'y'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
responsive: true,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: true
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
mode: 'index',
|
||||||
|
intersect: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
point: {
|
||||||
|
radius: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
grid: {
|
||||||
|
color: daisyColor('--bc', 10)
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
color: daisyColor('--bc')
|
||||||
|
},
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
type: 'linear',
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: title,
|
||||||
|
color: daisyColor('--bc'),
|
||||||
|
font: {
|
||||||
|
size: 16,
|
||||||
|
weight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
position: 'left',
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
grid: { color: daisyColor('--bc', 10) },
|
||||||
|
ticks: {
|
||||||
|
color: daisyColor('--bc')
|
||||||
|
},
|
||||||
|
border: { color: daisyColor('--bc', 10) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
chart.data.labels = data
|
||||||
|
chart.data.datasets[0].data = data
|
||||||
|
}, 500);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="w-full h-full overflow-x-auto">
|
||||||
|
<div
|
||||||
|
class="flex w-full flex-col space-y-1 h-60"
|
||||||
|
transition:slide|local={{ duration: 300, easing: cubicOut }}
|
||||||
|
>
|
||||||
|
<canvas bind:this={chartElement} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import ChartBase from "./ChartBase.svelte";
|
||||||
|
|
||||||
|
let CpuData:number[] = [1,2,3,4,5,6,7,8,9,]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<ChartBase data={CpuData} label="CPU usage" title="CPU usage"></ChartBase>
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Controls from './Controls.svelte';
|
import Controls from './Controls.svelte';
|
||||||
import { socket } from '$lib/stores';
|
import WidgetContainer from '$lib/components/layout/DynamicLayout.svelte';
|
||||||
import Spinner from '$lib/components/Spinner.svelte';
|
import { controllerLayout} from '$lib/components/layout/LayoutManager';
|
||||||
</script>
|
</script>
|
||||||
<div class="select-none">
|
|
||||||
{#if !$socket}
|
<div class="absolute top-0 select-none w-screen h-screen">
|
||||||
<div class="absolute left-0 flex flex-col w-screen h-screen justify-center items-center backdrop-blur-sm z-10">
|
<Controls />
|
||||||
<Spinner/>
|
<!-- <button class="absolute z-20 btn" on:click={addWidget}>Add Widget</button> -->
|
||||||
<h2>Waiting for connection</h2>
|
<div class="absolute w-full h-screen top-0 overflow-hidden lg:pt-16 pt-12">
|
||||||
</div>
|
<WidgetContainer container={$controllerLayout} />
|
||||||
{/if}
|
</div>
|
||||||
<Controls />
|
|
||||||
<slot/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import Visualization from "$lib/components/Visualization.svelte";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="grow flex">
|
|
||||||
<div class="absolute h-screen w-full top-0">
|
|
||||||
<Visualization debug />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
Reference in New Issue
Block a user