feat: integrate SvelteKit for seamless navigation and improved data loading
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- [DEF:DynamicForm:Component] -->
|
||||
<!--
|
||||
[DEF:DynamicForm:Component]
|
||||
@SEMANTICS: form, schema, dynamic, json-schema
|
||||
@PURPOSE: Generates a form dynamically based on a JSON schema.
|
||||
@LAYER: UI
|
||||
@@ -11,7 +11,9 @@
|
||||
- submit: Object - Dispatched when the form is submitted, containing the form data.
|
||||
-->
|
||||
<script>
|
||||
// [SECTION: IMPORTS]
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
// [/SECTION]
|
||||
|
||||
export let schema;
|
||||
let formData = {};
|
||||
@@ -19,7 +21,9 @@
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
// [DEF:handleSubmit:Function]
|
||||
// @PURPOSE: Dispatches the submit event with the form data.
|
||||
/**
|
||||
* @purpose Dispatches the submit event with the form data.
|
||||
*/
|
||||
function handleSubmit() {
|
||||
console.log("[DynamicForm][Action] Submitting form data.", { formData });
|
||||
dispatch('submit', formData);
|
||||
@@ -27,7 +31,9 @@
|
||||
// [/DEF:handleSubmit]
|
||||
|
||||
// [DEF:initializeForm:Function]
|
||||
// @PURPOSE: Initialize form data with default values from the schema.
|
||||
/**
|
||||
* @purpose Initialize form data with default values from the schema.
|
||||
*/
|
||||
function initializeForm() {
|
||||
if (schema && schema.properties) {
|
||||
for (const key in schema.properties) {
|
||||
@@ -40,6 +46,7 @@
|
||||
initializeForm();
|
||||
</script>
|
||||
|
||||
<!-- [SECTION: TEMPLATE] -->
|
||||
<form on:submit|preventDefault={handleSubmit} class="space-y-4">
|
||||
{#if schema && schema.properties}
|
||||
{#each Object.entries(schema.properties) as [key, prop]}
|
||||
@@ -76,4 +83,6 @@
|
||||
</button>
|
||||
{/if}
|
||||
</form>
|
||||
<!-- [/DEF:DynamicForm] -->
|
||||
<!-- [/SECTION] -->
|
||||
|
||||
<!-- [/DEF:DynamicForm] -->
|
||||
|
||||
3
frontend/src/components/Footer.svelte
Normal file
3
frontend/src/components/Footer.svelte
Normal file
@@ -0,0 +1,3 @@
|
||||
<footer class="bg-white border-t p-4 mt-8 text-center text-gray-500 text-sm">
|
||||
© 2025 Superset Tools. All rights reserved.
|
||||
</footer>
|
||||
26
frontend/src/components/Navbar.svelte
Normal file
26
frontend/src/components/Navbar.svelte
Normal file
@@ -0,0 +1,26 @@
|
||||
<script>
|
||||
import { page } from '$app/stores';
|
||||
</script>
|
||||
|
||||
<header class="bg-white shadow-md p-4 flex justify-between items-center">
|
||||
<a
|
||||
href="/"
|
||||
class="text-3xl font-bold text-gray-800 focus:outline-none"
|
||||
>
|
||||
Superset Tools
|
||||
</a>
|
||||
<nav class="space-x-4">
|
||||
<a
|
||||
href="/"
|
||||
class="text-gray-600 hover:text-blue-600 font-medium {$page.url.pathname === '/' ? 'text-blue-600 border-b-2 border-blue-600' : ''}"
|
||||
>
|
||||
Dashboard
|
||||
</a>
|
||||
<a
|
||||
href="/settings"
|
||||
class="text-gray-600 hover:text-blue-600 font-medium {$page.url.pathname === '/settings' ? 'text-blue-600 border-b-2 border-blue-600' : ''}"
|
||||
>
|
||||
Settings
|
||||
</a>
|
||||
</nav>
|
||||
</header>
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- [DEF:TaskRunner:Component] -->
|
||||
<!--
|
||||
[DEF:TaskRunner:Component]
|
||||
@SEMANTICS: task, runner, logs, websocket
|
||||
@PURPOSE: Connects to a WebSocket to display real-time logs for a running task.
|
||||
@LAYER: UI
|
||||
@@ -9,19 +9,25 @@
|
||||
@EVENTS: None
|
||||
-->
|
||||
<script>
|
||||
// [SECTION: IMPORTS]
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import { selectedTask, taskLogs } from '../lib/stores.js';
|
||||
// [/SECTION]
|
||||
|
||||
let ws;
|
||||
|
||||
// [DEF:onMount:Function]
|
||||
// @PURPOSE: Initialize WebSocket connection for task logs.
|
||||
/**
|
||||
* @purpose Initialize WebSocket connection for task logs.
|
||||
*/
|
||||
onMount(() => {
|
||||
if ($selectedTask) {
|
||||
console.log(`[TaskRunner][Entry] Connecting to logs for task: ${$selectedTask.id}`);
|
||||
const task = get(selectedTask);
|
||||
if (task) {
|
||||
console.log(`[TaskRunner][Entry] Connecting to logs for task: ${task.id}`);
|
||||
taskLogs.set([]); // Clear previous logs
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/logs/${$selectedTask.id}`;
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/logs/${task.id}`;
|
||||
ws = new WebSocket(wsUrl);
|
||||
|
||||
ws.onopen = () => {
|
||||
@@ -45,7 +51,9 @@
|
||||
// [/DEF:onMount]
|
||||
|
||||
// [DEF:onDestroy:Function]
|
||||
// @PURPOSE: Close WebSocket connection when the component is destroyed.
|
||||
/**
|
||||
* @purpose Close WebSocket connection when the component is destroyed.
|
||||
*/
|
||||
onDestroy(() => {
|
||||
if (ws) {
|
||||
console.log("[TaskRunner][Action] Closing WebSocket connection.");
|
||||
@@ -55,6 +63,7 @@
|
||||
// [/DEF:onDestroy]
|
||||
</script>
|
||||
|
||||
<!-- [SECTION: TEMPLATE] -->
|
||||
<div class="p-4 border rounded-lg bg-white shadow-md">
|
||||
{#if $selectedTask}
|
||||
<h2 class="text-xl font-semibold mb-2">Task: {$selectedTask.plugin_id}</h2>
|
||||
@@ -71,4 +80,6 @@
|
||||
<p>No task selected.</p>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- [/DEF:TaskRunner] -->
|
||||
<!-- [/SECTION] -->
|
||||
|
||||
<!-- [/DEF:TaskRunner] -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- [DEF:Toast:Component] -->
|
||||
<!--
|
||||
[DEF:Toast:Component]
|
||||
@SEMANTICS: toast, notification, feedback, ui
|
||||
@PURPOSE: Displays transient notifications (toasts) in the bottom-right corner.
|
||||
@LAYER: UI
|
||||
@@ -9,9 +9,12 @@
|
||||
@EVENTS: None
|
||||
-->
|
||||
<script>
|
||||
// [SECTION: IMPORTS]
|
||||
import { toasts } from '../lib/toasts.js';
|
||||
// [/SECTION]
|
||||
</script>
|
||||
|
||||
<!-- [SECTION: TEMPLATE] -->
|
||||
<div class="fixed bottom-0 right-0 p-4 space-y-2">
|
||||
{#each $toasts as toast (toast.id)}
|
||||
<div class="p-4 rounded-md shadow-lg text-white
|
||||
@@ -23,4 +26,6 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<!-- [/DEF:Toast] -->
|
||||
<!-- [/SECTION] -->
|
||||
|
||||
<!-- [/DEF:Toast] -->
|
||||
|
||||
Reference in New Issue
Block a user