Add panel feature updates across API, daemon, and web
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { Settings2, FileText, Save } from 'lucide-react';
|
||||
@@ -30,6 +30,24 @@ interface ConfigDetail {
|
||||
raw: string;
|
||||
}
|
||||
|
||||
function mergeConfigEntries(
|
||||
entries: ConfigEntry[],
|
||||
editableKeys: string[] | null,
|
||||
): ConfigEntry[] {
|
||||
if (!editableKeys || editableKeys.length === 0) return entries;
|
||||
|
||||
const existing = new Map(entries.map((entry) => [entry.key, entry]));
|
||||
const merged = [...entries];
|
||||
|
||||
for (const key of editableKeys) {
|
||||
if (!existing.has(key)) {
|
||||
merged.push({ key, value: '' });
|
||||
}
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
export function ConfigPage() {
|
||||
const { orgId, serverId } = useParams();
|
||||
const queryClient = useQueryClient();
|
||||
@@ -102,13 +120,11 @@ function ConfigEditor({
|
||||
});
|
||||
|
||||
const [entries, setEntries] = useState<ConfigEntry[]>([]);
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
|
||||
// Initialize entries from server data
|
||||
if (detail && !initialized) {
|
||||
setEntries(detail.entries);
|
||||
setInitialized(true);
|
||||
}
|
||||
useEffect(() => {
|
||||
if (!detail) return;
|
||||
setEntries(mergeConfigEntries(detail.entries, configFile.editableKeys));
|
||||
}, [detail, configFile.editableKeys]);
|
||||
|
||||
const saveMutation = useMutation({
|
||||
mutationFn: (data: { entries: ConfigEntry[] }) =>
|
||||
@@ -129,14 +145,6 @@ function ConfigEditor({
|
||||
);
|
||||
};
|
||||
|
||||
const displayEntries = configFile.editableKeys
|
||||
? entries.filter((e) => configFile.editableKeys!.includes(e.key))
|
||||
: entries;
|
||||
|
||||
const entriesToSave = configFile.editableKeys
|
||||
? entries.filter((e) => configFile.editableKeys!.includes(e.key))
|
||||
: entries;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
@@ -147,13 +155,13 @@ function ConfigEditor({
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
{configFile.editableKeys
|
||||
? `${configFile.editableKeys.length} editable keys`
|
||||
: 'All keys editable'}
|
||||
? `${configFile.editableKeys.length} allowed additions, plus existing keys`
|
||||
: 'All detected keys editable'}
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => saveMutation.mutate({ entries: entriesToSave })}
|
||||
onClick={() => saveMutation.mutate({ entries })}
|
||||
disabled={saveMutation.isPending}
|
||||
>
|
||||
<Save className="h-4 w-4" />
|
||||
@@ -161,13 +169,13 @@ function ConfigEditor({
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{displayEntries.length === 0 ? (
|
||||
{entries.length === 0 ? (
|
||||
<p className="py-8 text-center text-sm text-muted-foreground">
|
||||
{detail ? 'No entries found. The server may need to be started first to generate config files.' : 'Loading...'}
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{displayEntries.map((entry) => (
|
||||
{entries.map((entry) => (
|
||||
<div key={entry.key} className="grid gap-1.5">
|
||||
<Label className="font-mono text-xs text-muted-foreground">
|
||||
{entry.key}
|
||||
|
||||
Reference in New Issue
Block a user