Builded new structure.

Now with remote setup and management Server
more than one Node can be connected
added user auth
This commit is contained in:
Philipp committed 2026-05-21 09:51:07 +02:00
1 parent 4c98d14352
commit aae54167a1
25 files changed
+1942 -52

No files matched your search

+26 -8
View File
@@ -1,10 +1,11 @@
import { Eye, EyeOff, Save } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import { api, errorMessage, setApiToken } from '../api.js';
import { api, errorMessage } from '../api.js';
export function Settings({ onChanged }) {
export function Settings({ nodes, onChanged }) {
const [fields, setFields] = useState([]);
const [values, setValues] = useState({});
const [nodeId, setNodeId] = useState(nodes[0]?.id || '');
const [visibleSecrets, setVisibleSecrets] = useState({});
const [saving, setSaving] = useState(false);
const [message, setMessage] = useState('');
@@ -16,9 +17,10 @@ export function Settings({ onChanged }) {
);
async function loadSettings() {
if (!nodeId) return;
setError('');
try {
const result = await api.get('/settings');
const result = await api.get(`/settings/${encodeURIComponent(nodeId)}`);
setFields(result.data.fields || []);
setValues(Object.fromEntries((result.data.fields || []).map((field) => [field.key, field.value || ''])));
} catch (requestError) {
@@ -28,7 +30,11 @@ export function Settings({ onChanged }) {
useEffect(() => {
loadSettings();
}, []);
}, [nodeId]);
useEffect(() => {
if (!nodeId && nodes[0]?.id) setNodeId(nodes[0].id);
}, [nodeId, nodes]);
async function saveSettings(event) {
event.preventDefault();
@@ -36,8 +42,7 @@ export function Settings({ onChanged }) {
setMessage('');
setError('');
try {
setApiToken(values.API_TOKEN);
const result = await api.put('/settings', { values });
const result = await api.put(`/settings/${encodeURIComponent(nodeId)}`, { values });
setFields(result.data.fields || []);
setValues(Object.fromEntries((result.data.fields || []).map((field) => [field.key, field.value || ''])));
setMessage('Settings saved. Running jobs use the updated values; a changed PORT still needs a backend restart.');
@@ -54,7 +59,7 @@ export function Settings({ onChanged }) {
<div className="border-b border-zinc-800 pb-5">
<h1 className="text-2xl font-semibold text-zinc-100">Settings</h1>
<p className="mt-2 max-w-3xl text-sm leading-6 text-zinc-500">
Values are written to <span className="font-mono text-zinc-400">backend/.env</span>. Keep access to this UI restricted because secrets are editable here.
Values are written to the selected node agent. Keep access to this UI restricted because secrets are editable here.
</p>
</div>
@@ -65,6 +70,19 @@ export function Settings({ onChanged }) {
) : null}
<form className="rounded-md border border-zinc-800 bg-zinc-900/70" onSubmit={saveSettings}>
<div className="border-b border-zinc-800 p-4">
<label className="block max-w-sm text-sm text-zinc-300">
Node
<select
className="mt-2 h-10 w-full rounded-md border border-zinc-700 bg-zinc-950 px-3 text-zinc-100 outline-none"
onChange={(event) => setNodeId(event.target.value)}
value={nodeId}
>
<option value="">Select node</option>
{nodes.map((node) => <option key={node.id} value={node.id}>{node.name}</option>)}
</select>
</label>
</div>
<div className="grid gap-4 p-4 lg:grid-cols-2">
{fields.map((field) => {
const secretVisible = visibleSecrets[field.key];
@@ -102,7 +120,7 @@ export function Settings({ onChanged }) {
<div className="flex justify-end border-t border-zinc-800 px-4 py-3">
<button
className="inline-flex h-9 items-center gap-2 rounded-md border border-cyan-800 bg-cyan-950 px-3 text-sm text-cyan-100 hover:bg-cyan-900"
disabled={saving}
disabled={saving || !nodeId}
type="submit"
>
<Save className="h-4 w-4" />