mirror of
https://github.com/bybrooklyn/alchemist.git
synced 2026-04-18 09:53:33 -04:00
updated UI to remove odd flashing
This commit is contained in:
@@ -432,7 +432,17 @@ export default function JobManager() {
|
||||
}
|
||||
|
||||
const data = await apiJson<Job[]>(`/api/jobs/table?${params}`);
|
||||
setJobs(data);
|
||||
setJobs((prev) =>
|
||||
data.map((serverJob) => {
|
||||
const local = prev.find((j) => j.id === serverJob.id);
|
||||
const terminal = ["completed", "skipped", "failed", "cancelled"];
|
||||
if (local && terminal.includes(local.status)) {
|
||||
// Keep the terminal state from SSE to prevent flickering back to a stale poll state.
|
||||
return { ...serverJob, status: local.status };
|
||||
}
|
||||
return serverJob;
|
||||
})
|
||||
);
|
||||
setActionError(null);
|
||||
} catch (e) {
|
||||
const message = isApiError(e) ? e.message : "Failed to fetch jobs";
|
||||
|
||||
@@ -74,9 +74,9 @@ export default function SettingsPanel() {
|
||||
navItemRefs.current[tab.id] = node;
|
||||
}}
|
||||
onClick={() => paginate(tab.id)}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 rounded-md text-sm font-bold transition-all duration-200 group ${isActive
|
||||
? "text-helios-ink bg-helios-surface-soft shadow-sm border border-helios-line/20"
|
||||
: "text-helios-slate hover:text-helios-ink hover:bg-helios-surface-soft/50"
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 rounded-md text-sm font-bold border transition-all duration-200 group ${isActive
|
||||
? "text-helios-ink bg-helios-surface-soft shadow-sm border-helios-line/20"
|
||||
: "text-helios-slate border-transparent hover:text-helios-ink hover:bg-helios-surface-soft/50"
|
||||
}`}
|
||||
>
|
||||
<span className="flex items-center gap-3">
|
||||
|
||||
@@ -169,33 +169,26 @@ export default function WatchFolders() {
|
||||
}
|
||||
|
||||
try {
|
||||
// Add to BOTH config (canonical) and DB (profiles)
|
||||
const bundle = await apiJson<SettingsBundleResponse>("/api/settings/bundle");
|
||||
if (!bundle.settings.scanner.directories.includes(normalized)) {
|
||||
await apiAction("/api/settings/bundle", {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
...bundle.settings,
|
||||
scanner: {
|
||||
...bundle.settings.scanner,
|
||||
directories: [...bundle.settings.scanner.directories, normalized],
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await apiAction("/api/settings/watch-dirs", {
|
||||
const currentDirs = bundle.settings.scanner.directories;
|
||||
|
||||
if (currentDirs.includes(normalized)) {
|
||||
// Even if it's in config, sync it to ensure it's in DB for profiles
|
||||
await apiAction("/api/settings/folders", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ path: normalized, is_recursive: true }),
|
||||
body: JSON.stringify({
|
||||
dirs: currentDirs.map(d => ({ path: d, is_recursive: true }))
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
await apiAction("/api/settings/folders", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
dirs: [...currentDirs, normalized].map(d => ({ path: d, is_recursive: true }))
|
||||
}),
|
||||
});
|
||||
} catch (innerE) {
|
||||
// If it's just a duplicate DB error we can ignore it since we successfully added to canonical
|
||||
if (!(isApiError(innerE) && innerE.status === 409)) {
|
||||
throw innerE;
|
||||
}
|
||||
}
|
||||
|
||||
setDirInput("");
|
||||
@@ -214,30 +207,16 @@ export default function WatchFolders() {
|
||||
if (!dir) return;
|
||||
|
||||
try {
|
||||
// Remove from canonical config if present
|
||||
const bundle = await apiJson<SettingsBundleResponse>("/api/settings/bundle");
|
||||
const filteredDirs = bundle.settings.scanner.directories.filter(candidate => candidate !== dir.path);
|
||||
const filteredDirs = bundle.settings.scanner.directories.filter(candidate => candidate !== dirPath);
|
||||
|
||||
if (filteredDirs.length !== bundle.settings.scanner.directories.length) {
|
||||
await apiAction("/api/settings/bundle", {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
...bundle.settings,
|
||||
scanner: {
|
||||
...bundle.settings.scanner,
|
||||
directories: filteredDirs,
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
// Remove from DB if it has a real ID
|
||||
if (dir.id > 0) {
|
||||
await apiAction(`/api/settings/watch-dirs/${dir.id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
}
|
||||
await apiAction("/api/settings/folders", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
dirs: filteredDirs.map(d => ({ path: d, is_recursive: true }))
|
||||
}),
|
||||
});
|
||||
|
||||
setError(null);
|
||||
await fetchDirs();
|
||||
|
||||
@@ -15,7 +15,7 @@ interface LibraryStepProps {
|
||||
}
|
||||
|
||||
interface FsBreadcrumb {
|
||||
name: string;
|
||||
label: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ export default function LibraryStep({
|
||||
</div>
|
||||
|
||||
{pickerOpen ? (
|
||||
<div className="flex h-[420px] flex-col gap-4 overflow-hidden rounded-lg border border-helios-line/30 bg-helios-surface p-4">
|
||||
<div className="flex h-[540px] flex-col gap-4 overflow-hidden rounded-lg border border-helios-line/30 bg-helios-surface p-4">
|
||||
<div className="shrink-0 flex items-start justify-between gap-4">
|
||||
<div className="min-w-0 space-y-3">
|
||||
<div className="space-y-1">
|
||||
@@ -245,7 +245,7 @@ export default function LibraryStep({
|
||||
: "rounded-lg px-2 py-1 transition-colors hover:bg-helios-surface-soft hover:text-helios-ink"
|
||||
}
|
||||
>
|
||||
{crumb.name.replace(/^\//, "")}
|
||||
{crumb.label.replace(/^\//, "")}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@@ -316,7 +316,7 @@ export default function LibraryStep({
|
||||
..
|
||||
</span>
|
||||
<span className="block truncate text-xs text-helios-slate">
|
||||
Go up to {parentBreadcrumb.name.replace(/^\//, "")}
|
||||
Go up to {parentBreadcrumb.label.replace(/^\//, "")}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@@ -117,7 +117,7 @@ export default function ServerDirectoryPicker({
|
||||
/>
|
||||
|
||||
<div className="absolute inset-0 flex items-center justify-center px-4 py-6">
|
||||
<div className="w-full max-w-5xl rounded-xl border border-helios-line/30 bg-helios-surface shadow-2xl overflow-hidden flex flex-col max-h-[min(90vh,800px)]">
|
||||
<div className="w-full max-w-7xl rounded-xl border border-helios-line/30 bg-helios-surface shadow-2xl overflow-hidden flex flex-col max-h-[min(95vh,1000px)]">
|
||||
<div className="border-b border-helios-line/20 px-6 py-5 flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
Reference in New Issue
Block a user