Skip to content

Commit

Permalink
feat: create device modal
Browse files Browse the repository at this point in the history
  • Loading branch information
MSchmoecker committed Jan 17, 2024
1 parent 3a37ee6 commit 5ccbc78
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 53 deletions.
50 changes: 50 additions & 0 deletions frontend/src/lib/CreateDeviceModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script lang="ts">
import type { SvelteComponent } from 'svelte';
import { getModalStore } from '@skeletonlabs/skeleton';
export let parent: SvelteComponent;
const modalStore = getModalStore();
const formData = {
displayName: '',
hostname: ''
};
function onFormSubmit(): void {
if ($modalStore[0].response) $modalStore[0].response(formData);
modalStore.close();
}
</script>

{#if $modalStore[0]}
<div class="modal-example-form card p-4 w-modal shadow-xl space-y-4">
<header class="text-2xl font-bold">{$modalStore[0].title ?? '(title missing)'}</header>
<!-- <article>{$modalStore[0].body ?? '(body missing)'}</article> -->
<form class="modal-form space-y-4">
<label class="label">
<span>Name</span>
<input
class="input"
type="text"
bind:value={formData.displayName}
placeholder="Enter name..."
/>
</label>
<label class="label">
<span>Hostname</span>
<input
class="input"
type="text"
bind:value={formData.hostname}
placeholder="Enter hostname..."
/>
</label>
</form>
<footer class="modal-footer {parent.regionFooter}">
<button class="btn {parent.buttonNeutral}" on:click={parent.onClose}
>{parent.buttonTextCancel}</button
>
<button class="btn {parent.buttonPositive}" on:click={onFormSubmit}>Create</button>
</footer>
</div>
{/if}
45 changes: 45 additions & 0 deletions frontend/src/lib/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { invalidate } from '$app/navigation';

export type SettingTypes = {
type: 'bool';
value: boolean;
} | {
type: 'string';
value: string;
} | {
type: 'path';
value: string;
};

export type Setting = SettingTypes & {
name: string;
// value: unknown;
default: string;
description: string;
example: string | null;
// type: string;
};

export type Module = { name: string } & Record<string, Setting>;

export type SettingValue = { value: SettingTypes }
export type ModuleSettings = { type: string, settings: { [key: string]: SettingValue } };
export type Device = { hostname: string, displayName: string, modules: ModuleSettings[], tags: string[] };

export type State = {
modules: Module[];
devices: Device[];
tags: string[];
};

export async function saveState(state: State) {
await fetch('http://localhost:8000/state', {
method: 'PATCH',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(state)
});
await invalidate('http://localhost:8000/state');
await invalidate('http://localhost:8000/available_modules');
}
17 changes: 16 additions & 1 deletion frontend/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
<script lang="ts">
import '../app.postcss';
import { AppShell, AppRail, AppRailAnchor, AppBar } from '@skeletonlabs/skeleton';
import {
AppShell,
AppRail,
AppRailAnchor,
AppBar,
type ModalComponent
} from '@skeletonlabs/skeleton';
import { Grid2x2Icon, SettingsIcon, HistoryIcon, LayoutDashboard } from 'lucide-svelte';
import { page } from '$app/stores';
import Logo from '$lib/Logo.svelte';
import { Modal, initializeStores } from '@skeletonlabs/skeleton';
import CreateDeviceModal from '$lib/CreateDeviceModal.svelte';
const modalRegistry: Record<string, ModalComponent> = {
CreateDeviceModal: { ref: CreateDeviceModal }
};
initializeStores();
</script>

<Modal components={modalRegistry} />
<AppShell>
<svelte:fragment slot="header">
<AppBar>
Expand Down
20 changes: 4 additions & 16 deletions frontend/src/routes/config/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,15 @@
import ConfigString from '$lib/config/ConfigString.svelte';
import type { PageData } from './$types';
import { queryParam } from 'sveltekit-search-params';
import { invalidate } from '$app/navigation';
import { saveState } from '$lib/state';
const selected = queryParam<number>('selected', {
decode: (value) => (value ? parseInt(value, 10) : 0),
encode: (value) => value.toString()
});
export let data: PageData;
export let data: PageData;
$: state = data.state;
async function saveConfig() {
await fetch('http://localhost:8000/state', {
method: 'PATCH',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(state)
});
await invalidate('http://localhost:8000/state');
await invalidate('http://localhost:8000/available_modules');
}
$: console.log(selected);
</script>

Expand Down Expand Up @@ -70,7 +58,7 @@
</ListBoxItem>
{/each}
</ListBox>
<button type="button" class="btn variant-filled mt-8" on:click={() => saveConfig()}>
<button type="button" class="btn variant-filled mt-8" on:click={() => saveState(state)}>
save
</button>
</div>
Expand Down
30 changes: 1 addition & 29 deletions frontend/src/routes/config/+page.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,6 @@
import type { Module, State } from '$lib/state';
import type { PageLoad } from './$types';

type SettingTypes =
| {
type: 'bool';
value: boolean;
}
| {
type: 'string';
value: string;
}
| {
type: 'path';
value: string;
};

type Setting = SettingTypes & {
name: string;
// value: unknown;
default: string;
description: string;
example: string | null;
// type: string;
};

type Module = { name: string } & Record<string, Setting>;

type State = {
modules: Module[];
};

export const load = (async ({ fetch }) => {
const stateResponse = await fetch('http://localhost:8000/state', {
method: 'GET',
Expand Down
21 changes: 19 additions & 2 deletions frontend/src/routes/overview/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
<script lang="ts">
import type { PageData } from '../$types';
import type { PageData } from './$types';
import { getModalStore } from '@skeletonlabs/skeleton';
import { saveState } from '$lib/state';
export let data: PageData;
$: devices = data.devices;
$: state = data.state;
const modalStore = getModalStore();
</script>

<button
class="btn variant-filled mb-8"
on:click={() =>
modalStore.trigger({
type: 'component',
component: 'CreateDeviceModal',
title: 'Create a new device',
response: (r) => {
devices.push({ ...r, tags: [], modules: [] });
saveState(state);
}
})}>Create New Device</button
>
<div class="border rounded-lg p-4 pb-2 bg-surface-100">
<table class="table-auto w-full text-left">
<thead>
Expand Down
11 changes: 6 additions & 5 deletions frontend/src/routes/overview/+page.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import type { PageLoad } from './$types';

type SettingValue = { value: any }
type ModuleSettings = { type: string, settings: { [key: string]: SettingValue } };
type Device = { hostname: string, displayName: string, modules: ModuleSettings[], tags: string[] };
import type { State, Device } from '$lib/state';

export const load = (async ({ fetch }) => {
const stateResponse = await fetch('http://localhost:8000/state', {
Expand All @@ -11,8 +8,12 @@ export const load = (async ({ fetch }) => {
'content-type': 'application/json'
}
});
const devices = (await stateResponse.json())["devices"] as Device[];

const state = (await stateResponse.json()) as State;
const devices = state.devices as Device[];

return {
state: state,
devices: devices,
};
}) satisfies PageLoad;

0 comments on commit 5ccbc78

Please sign in to comment.