Add frontend support for settings
This commit is contained in:
@@ -1,5 +1,15 @@
|
||||
export const API_URL = 'http://127.0.0.1:8000';
|
||||
|
||||
/**
|
||||
* Type definitions for Settings
|
||||
*/
|
||||
export interface Settings {
|
||||
id: number;
|
||||
requirements: string;
|
||||
environment: string;
|
||||
user: string;
|
||||
}
|
||||
|
||||
export async function checkHealth(): Promise<'healthy' | 'unhealthy'> {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/health`);
|
||||
@@ -58,6 +68,42 @@ export async function addScript(
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Fetch all settings
|
||||
export async function fetchSettings(): Promise<Settings[]> {
|
||||
const response = await fetch(`${API_URL}/settings`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch settings ' + response.statusText);
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Fetch a single setting by ID
|
||||
export async function fetchSettingById(id: number): Promise<Settings> {
|
||||
const response = await fetch(`${API_URL}/settings/${id}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch setting');
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Update an existing setting
|
||||
export async function updateSetting(
|
||||
id: number,
|
||||
updatedSetting: Partial<Settings>
|
||||
): Promise<Settings> {
|
||||
const response = await fetch(`${API_URL}/settings/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(updatedSetting)
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to update setting');
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Fetch a single script by ID
|
||||
export async function fetchScriptById(id: number): Promise<Script> {
|
||||
const response = await fetch(`${API_URL}/script/${id}`);
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
<div class="flex space-x-6">
|
||||
<a href="/" class="text-lg hover:text-gray-400">Home</a>
|
||||
<a href="/scripts" class="text-lg hover:text-gray-400">Scripts</a>
|
||||
<a href="/settings" class="text-lg hover:text-gray-400">
|
||||
<Icon icon="material-symbols:settings" width="24" height="24" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { updateScript, deleteScript, addLog, deleteLog, executeScript } from '$lib/api';
|
||||
import {
|
||||
updateScript,
|
||||
deleteScript,
|
||||
addLog,
|
||||
deleteLog,
|
||||
executeScript,
|
||||
fetchLogs
|
||||
} from '$lib/api';
|
||||
import type { Script, Log } from '$lib/api';
|
||||
import CodeMirror from 'svelte-codemirror-editor';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
@@ -29,12 +36,14 @@
|
||||
selectedLog = null;
|
||||
}
|
||||
|
||||
// Notifications are now handled globally via the layout
|
||||
|
||||
async function handleExecuteScript() {
|
||||
try {
|
||||
await executeScript(script.id);
|
||||
window.showNotification('success', 'Script executed successfully!');
|
||||
// Reload the list of logs after execution
|
||||
logs = (await fetchLogs(script.id)).sort(
|
||||
(a, b) => new Date(b.created_at!).getTime() - new Date(a.created_at!).getTime()
|
||||
);
|
||||
} catch (err) {
|
||||
window.showNotification('error', 'Failed to execute script. ' + err);
|
||||
}
|
||||
@@ -252,7 +261,7 @@
|
||||
<div
|
||||
class="fixed inset-0 bg-opacity-30 backdrop-blur-sm flex items-center justify-center z-50"
|
||||
>
|
||||
<div class="bg-white p-6 rounded shadow-lg w-3/4 max-w-2xl">
|
||||
<div class="bg-white p-6 rounded shadow-lg w-3/4 max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<h3 class="text-lg font-bold mb-4">Log Details</h3>
|
||||
<div class="mb-4">
|
||||
<p class="font-semibold">Message:</p>
|
||||
|
||||
83
frontend/src/routes/settings/+page.svelte
Normal file
83
frontend/src/routes/settings/+page.svelte
Normal file
@@ -0,0 +1,83 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { fetchSettings, updateSetting } from '$lib/api';
|
||||
import type { Settings } from '$lib/api';
|
||||
import { writable } from 'svelte/store';
|
||||
import CodeMirror from 'svelte-codemirror-editor';
|
||||
|
||||
let settings = writable<Settings[]>([]);
|
||||
let isLoading = writable(false);
|
||||
let error = writable<string | null>(null);
|
||||
|
||||
async function loadSettings() {
|
||||
isLoading.set(true);
|
||||
error.set(null);
|
||||
try {
|
||||
const data = await fetchSettings();
|
||||
settings.set(data);
|
||||
} catch (err) {
|
||||
error.set('Failed to load settings');
|
||||
} finally {
|
||||
isLoading.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSetting(setting: Settings) {
|
||||
isLoading.set(true);
|
||||
error.set(null);
|
||||
try {
|
||||
await updateSetting(setting.id, setting);
|
||||
loadSettings(); // Refresh settings after update
|
||||
} catch (err) {
|
||||
error.set('Failed to save setting');
|
||||
} finally {
|
||||
isLoading.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
loadSettings();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="container mx-auto p-4">
|
||||
<h1 class="text-2xl font-bold mb-4">Settings</h1>
|
||||
|
||||
{#if $isLoading}
|
||||
<p>Loading...</p>
|
||||
{:else if $error}
|
||||
<p class="text-red-500">{$error}</p>
|
||||
{:else}
|
||||
<div class="space-y-4">
|
||||
{#each $settings as setting (setting.id)}
|
||||
<div class="p-4 border rounded shadow">
|
||||
<label class="block mb-2 font-bold">Requirements</label>
|
||||
<div class="w-full border rounded">
|
||||
<CodeMirror bind:value={setting.requirements} />
|
||||
</div>
|
||||
|
||||
<label class="block mt-4 mb-2 font-bold">Environment</label>
|
||||
<div class="w-full border rounded">
|
||||
<CodeMirror bind:value={setting.environment} />
|
||||
</div>
|
||||
|
||||
<label class="block mt-4 mb-2 font-bold">User</label>
|
||||
<input type="text" class="w-full p-2 border rounded" bind:value={setting.user} readonly />
|
||||
|
||||
<button
|
||||
class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
on:click={() => saveSetting(setting)}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
max-width: 800px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user