feat: integrate SvelteKit for seamless navigation and improved data loading
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { _ as escape_html, X as store_get, Y as unsubscribe_stores } from "../../chunks/index2.js";
|
||||
import { p as page } from "../../chunks/stores.js";
|
||||
function _error($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
var $$store_subs;
|
||||
$$renderer2.push(`<div class="container mx-auto p-4 text-center mt-20"><h1 class="text-6xl font-bold text-gray-800 mb-4">${escape_html(store_get($$store_subs ??= {}, "$page", page).status)}</h1> <p class="text-2xl text-gray-600 mb-8">${escape_html(store_get($$store_subs ??= {}, "$page", page).error?.message || "Page not found")}</p> <a href="/" class="bg-blue-500 text-white px-6 py-3 rounded-lg hover:bg-blue-600 transition-colors">Back to Dashboard</a></div>`);
|
||||
if ($$store_subs) unsubscribe_stores($$store_subs);
|
||||
});
|
||||
}
|
||||
export {
|
||||
_error as default
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
import { V as attr_class, W as stringify, X as store_get, Y as unsubscribe_stores, Z as ensure_array_like, _ as escape_html, $ as slot } from "../../chunks/index2.js";
|
||||
import { p as page } from "../../chunks/stores.js";
|
||||
import "clsx";
|
||||
import { t as toasts } from "../../chunks/toasts.js";
|
||||
function Navbar($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
var $$store_subs;
|
||||
$$renderer2.push(`<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="/"${attr_class(`text-gray-600 hover:text-blue-600 font-medium ${stringify(store_get($$store_subs ??= {}, "$page", page).url.pathname === "/" ? "text-blue-600 border-b-2 border-blue-600" : "")}`)}>Dashboard</a> <a href="/settings"${attr_class(`text-gray-600 hover:text-blue-600 font-medium ${stringify(store_get($$store_subs ??= {}, "$page", page).url.pathname === "/settings" ? "text-blue-600 border-b-2 border-blue-600" : "")}`)}>Settings</a></nav></header>`);
|
||||
if ($$store_subs) unsubscribe_stores($$store_subs);
|
||||
});
|
||||
}
|
||||
function Footer($$renderer) {
|
||||
$$renderer.push(`<footer class="bg-white border-t p-4 mt-8 text-center text-gray-500 text-sm">© 2025 Superset Tools. All rights reserved.</footer>`);
|
||||
}
|
||||
function Toast($$renderer) {
|
||||
var $$store_subs;
|
||||
$$renderer.push(`<div class="fixed bottom-0 right-0 p-4 space-y-2"><!--[-->`);
|
||||
const each_array = ensure_array_like(store_get($$store_subs ??= {}, "$toasts", toasts));
|
||||
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
||||
let toast = each_array[$$index];
|
||||
$$renderer.push(`<div${attr_class(`p-4 rounded-md shadow-lg text-white ${stringify(toast.type === "info" && "bg-blue-500")} ${stringify(toast.type === "success" && "bg-green-500")} ${stringify(toast.type === "error" && "bg-red-500")} `)}>${escape_html(toast.message)}</div>`);
|
||||
}
|
||||
$$renderer.push(`<!--]--></div>`);
|
||||
if ($$store_subs) unsubscribe_stores($$store_subs);
|
||||
}
|
||||
function _layout($$renderer, $$props) {
|
||||
Toast($$renderer);
|
||||
$$renderer.push(`<!----> <main class="bg-gray-50 min-h-screen flex flex-col">`);
|
||||
Navbar($$renderer);
|
||||
$$renderer.push(`<!----> <div class="p-4 flex-grow"><!--[-->`);
|
||||
slot($$renderer, $$props, "default", {});
|
||||
$$renderer.push(`<!--]--></div> `);
|
||||
Footer($$renderer);
|
||||
$$renderer.push(`<!----></main>`);
|
||||
}
|
||||
export {
|
||||
_layout as default
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
const ssr = false;
|
||||
const prerender = false;
|
||||
export {
|
||||
prerender,
|
||||
ssr
|
||||
};
|
||||
132
frontend/.svelte-kit/output/server/entries/pages/_page.svelte.js
Normal file
132
frontend/.svelte-kit/output/server/entries/pages/_page.svelte.js
Normal file
@@ -0,0 +1,132 @@
|
||||
import { a1 as ssr_context, X as store_get, _ as escape_html, Z as ensure_array_like, V as attr_class, Y as unsubscribe_stores, a2 as attr, a3 as bind_props } from "../../chunks/index2.js";
|
||||
import { w as writable } from "../../chunks/index.js";
|
||||
import "clsx";
|
||||
function onDestroy(fn) {
|
||||
/** @type {SSRContext} */
|
||||
ssr_context.r.on_destroy(fn);
|
||||
}
|
||||
const plugins = writable([]);
|
||||
const selectedPlugin = writable(null);
|
||||
const selectedTask = writable(null);
|
||||
const taskLogs = writable([]);
|
||||
function TaskRunner($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
var $$store_subs;
|
||||
onDestroy(() => {
|
||||
});
|
||||
$$renderer2.push(`<div class="p-4 border rounded-lg bg-white shadow-md">`);
|
||||
if (store_get($$store_subs ??= {}, "$selectedTask", selectedTask)) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<h2 class="text-xl font-semibold mb-2">Task: ${escape_html(store_get($$store_subs ??= {}, "$selectedTask", selectedTask).plugin_id)}</h2> <div class="bg-gray-900 text-white font-mono text-sm p-4 rounded-md h-96 overflow-y-auto"><!--[-->`);
|
||||
const each_array = ensure_array_like(store_get($$store_subs ??= {}, "$taskLogs", taskLogs));
|
||||
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
||||
let log = each_array[$$index];
|
||||
$$renderer2.push(`<div><span class="text-gray-400">${escape_html(new Date(log.timestamp).toLocaleTimeString())}</span> <span${attr_class(log.level === "ERROR" ? "text-red-500" : "text-green-400")}>[${escape_html(log.level)}]</span> <span>${escape_html(log.message)}</span></div>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
$$renderer2.push(`<p>No task selected.</p>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div>`);
|
||||
if ($$store_subs) unsubscribe_stores($$store_subs);
|
||||
});
|
||||
}
|
||||
function DynamicForm($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
let schema = $$props["schema"];
|
||||
let formData = {};
|
||||
function initializeForm() {
|
||||
if (schema && schema.properties) {
|
||||
for (const key in schema.properties) {
|
||||
formData[key] = schema.properties[key].default || "";
|
||||
}
|
||||
}
|
||||
}
|
||||
initializeForm();
|
||||
$$renderer2.push(`<form class="space-y-4">`);
|
||||
if (schema && schema.properties) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<!--[-->`);
|
||||
const each_array = ensure_array_like(Object.entries(schema.properties));
|
||||
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
||||
let [key, prop] = each_array[$$index];
|
||||
$$renderer2.push(`<div class="flex flex-col"><label${attr("for", key)} class="mb-1 font-semibold text-gray-700">${escape_html(prop.title || key)}</label> `);
|
||||
if (prop.type === "string") {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<input type="text"${attr("id", key)}${attr("value", formData[key])}${attr("placeholder", prop.description || "")} class="p-2 border rounded-md"/>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
if (prop.type === "number" || prop.type === "integer") {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<input type="number"${attr("id", key)}${attr("value", formData[key])}${attr("placeholder", prop.description || "")} class="p-2 border rounded-md"/>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
if (prop.type === "boolean") {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<input type="checkbox"${attr("id", key)}${attr("checked", formData[key], true)} class="h-5 w-5"/>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]-->`);
|
||||
}
|
||||
$$renderer2.push(`<!--]-->`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--> <button type="submit" class="w-full bg-green-500 text-white p-2 rounded-md hover:bg-green-600">Run Task</button>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--></form>`);
|
||||
bind_props($$props, { schema });
|
||||
});
|
||||
}
|
||||
function _page($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
var $$store_subs;
|
||||
let data = $$props["data"];
|
||||
if (data.plugins) {
|
||||
plugins.set(data.plugins);
|
||||
}
|
||||
$$renderer2.push(`<div class="container mx-auto p-4">`);
|
||||
if (store_get($$store_subs ??= {}, "$selectedTask", selectedTask)) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
TaskRunner($$renderer2);
|
||||
$$renderer2.push(`<!----> <button class="mt-4 bg-blue-500 text-white p-2 rounded">Back to Task List</button>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
if (store_get($$store_subs ??= {}, "$selectedPlugin", selectedPlugin)) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<h2 class="text-2xl font-bold mb-4">${escape_html(store_get($$store_subs ??= {}, "$selectedPlugin", selectedPlugin).name)}</h2> `);
|
||||
DynamicForm($$renderer2, {
|
||||
schema: store_get($$store_subs ??= {}, "$selectedPlugin", selectedPlugin).schema
|
||||
});
|
||||
$$renderer2.push(`<!----> <button class="mt-4 bg-gray-500 text-white p-2 rounded">Back to Dashboard</button>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
$$renderer2.push(`<h1 class="text-2xl font-bold mb-4">Available Tools</h1> `);
|
||||
if (data.error) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">${escape_html(data.error)}</div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"><!--[-->`);
|
||||
const each_array = ensure_array_like(data.plugins);
|
||||
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
||||
let plugin = each_array[$$index];
|
||||
$$renderer2.push(`<div class="border rounded-lg p-4 cursor-pointer hover:bg-gray-100" role="button" tabindex="0"><h2 class="text-xl font-semibold">${escape_html(plugin.name)}</h2> <p class="text-gray-600">${escape_html(plugin.description)}</p> <span class="text-sm text-gray-400">v${escape_html(plugin.version)}</span></div>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]-->`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div>`);
|
||||
if ($$store_subs) unsubscribe_stores($$store_subs);
|
||||
bind_props($$props, { data });
|
||||
});
|
||||
}
|
||||
export {
|
||||
_page as default
|
||||
};
|
||||
18
frontend/.svelte-kit/output/server/entries/pages/_page.ts.js
Normal file
18
frontend/.svelte-kit/output/server/entries/pages/_page.ts.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { a as api } from "../../chunks/api.js";
|
||||
async function load() {
|
||||
try {
|
||||
const plugins = await api.getPlugins();
|
||||
return {
|
||||
plugins
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Failed to load plugins:", error);
|
||||
return {
|
||||
plugins: [],
|
||||
error: "Failed to load plugins"
|
||||
};
|
||||
}
|
||||
}
|
||||
export {
|
||||
load
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import { _ as escape_html, a2 as attr, Z as ensure_array_like, a3 as bind_props } from "../../../chunks/index2.js";
|
||||
function _page($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
let data = $$props["data"];
|
||||
let settings = data.settings;
|
||||
let newEnv = {
|
||||
id: "",
|
||||
name: "",
|
||||
url: "",
|
||||
username: "",
|
||||
password: "",
|
||||
is_default: false
|
||||
};
|
||||
settings = data.settings;
|
||||
$$renderer2.push(`<div class="container mx-auto p-4"><h1 class="text-2xl font-bold mb-6">Settings</h1> `);
|
||||
if (data.error) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">${escape_html(data.error)}</div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--> <section class="mb-8 bg-white p-6 rounded shadow"><h2 class="text-xl font-semibold mb-4">Global Settings</h2> <div class="grid grid-cols-1 gap-4"><div><label for="backup_path" class="block text-sm font-medium text-gray-700">Backup Storage Path</label> <input type="text" id="backup_path"${attr("value", settings.settings.backup_path)} class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"/></div> <button class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 w-max">Save Global Settings</button></div></section> <section class="mb-8 bg-white p-6 rounded shadow"><h2 class="text-xl font-semibold mb-4">Superset Environments</h2> `);
|
||||
if (settings.environments.length === 0) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
$$renderer2.push(`<div class="mb-4 p-4 bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700"><p class="font-bold">Warning</p> <p>No Superset environments configured. You must add at least one environment to perform backups or migrations.</p></div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--> <div class="mb-6 overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead class="bg-gray-50"><tr><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">URL</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Username</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Default</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th></tr></thead><tbody class="bg-white divide-y divide-gray-200"><!--[-->`);
|
||||
const each_array = ensure_array_like(settings.environments);
|
||||
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
||||
let env = each_array[$$index];
|
||||
$$renderer2.push(`<tr><td class="px-6 py-4 whitespace-nowrap">${escape_html(env.name)}</td><td class="px-6 py-4 whitespace-nowrap">${escape_html(env.url)}</td><td class="px-6 py-4 whitespace-nowrap">${escape_html(env.username)}</td><td class="px-6 py-4 whitespace-nowrap">${escape_html(env.is_default ? "Yes" : "No")}</td><td class="px-6 py-4 whitespace-nowrap"><button class="text-green-600 hover:text-green-900 mr-4">Test</button> <button class="text-indigo-600 hover:text-indigo-900 mr-4">Edit</button> <button class="text-red-600 hover:text-red-900">Delete</button></td></tr>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--></tbody></table></div> <div class="bg-gray-50 p-4 rounded"><h3 class="text-lg font-medium mb-4">${escape_html("Add")} Environment</h3> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label for="env_id" class="block text-sm font-medium text-gray-700">ID</label> <input type="text" id="env_id"${attr("value", newEnv.id)}${attr("disabled", false, true)} class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"/></div> <div><label for="env_name" class="block text-sm font-medium text-gray-700">Name</label> <input type="text" id="env_name"${attr("value", newEnv.name)} class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"/></div> <div><label for="env_url" class="block text-sm font-medium text-gray-700">URL</label> <input type="text" id="env_url"${attr("value", newEnv.url)} class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"/></div> <div><label for="env_user" class="block text-sm font-medium text-gray-700">Username</label> <input type="text" id="env_user"${attr("value", newEnv.username)} class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"/></div> <div><label for="env_pass" class="block text-sm font-medium text-gray-700">Password</label> <input type="password" id="env_pass"${attr("value", newEnv.password)} class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"/></div> <div class="flex items-center"><input type="checkbox" id="env_default"${attr("checked", newEnv.is_default, true)} class="h-4 w-4 text-blue-600 border-gray-300 rounded"/> <label for="env_default" class="ml-2 block text-sm text-gray-900">Default Environment</label></div></div> <div class="mt-4 flex gap-2"><button class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600">${escape_html("Add")} Environment</button> `);
|
||||
{
|
||||
$$renderer2.push("<!--[!-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div></div></section></div>`);
|
||||
bind_props($$props, { data });
|
||||
});
|
||||
}
|
||||
export {
|
||||
_page as default
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import { a as api } from "../../../chunks/api.js";
|
||||
async function load() {
|
||||
try {
|
||||
const settings = await api.getSettings();
|
||||
return {
|
||||
settings
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Failed to load settings:", error);
|
||||
return {
|
||||
settings: {
|
||||
environments: [],
|
||||
settings: {
|
||||
backup_path: "",
|
||||
default_environment_id: null
|
||||
}
|
||||
},
|
||||
error: "Failed to load settings"
|
||||
};
|
||||
}
|
||||
}
|
||||
export {
|
||||
load
|
||||
};
|
||||
Reference in New Issue
Block a user