Improve catalog studio UX and aggressive docker cleanup
CI / check (push) Failing after 1m25s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
CI / publish-container (push) Skipped

Catalog Studio:
- Cross-parent drag & drop now uses optimistic updates with rollback
  on failure (no more full tree reload / visible delay)
- Subpage creation adds the node optimistically then refreshes parent
  only (was full tree reload)
- Single page deletion refreshes only the affected parent (was full
  tree reload)
- Root page creation replaces native prompt() with an inline input
  in the root tab bar
- Escape key no longer closes the dialog when an input field is focused
- TreeNodeUpdate type now supports parentId and orderNum for
  optimistic structural changes

Docker:
- docker-prune.sh default mode now aggressively cleans all unreferenced
  build cache, images >1h old, and stopped containers >1h old
  (was 72h/7d/24h which let cache grow past 80% on every push)
This commit is contained in:
openhands committed 2026-09-14 16:52:04 +02:00
1 parent 349188af10
commit 1a9e1e791a
6 files changed
+217 -40

No files matched your search

@@ -200,6 +200,9 @@ function CatalogManagerInner({
const onKey = (event: KeyboardEvent) => {
if (embedded || event.key !== "Escape" || event.defaultPrevented) return;
const target = event.target as HTMLElement;
// Never steal Escape from inputs/comboboxes (e.g. root name field).
const tag = target?.tagName;
if (tag === "INPUT" || tag === "TEXTAREA") return;
const focusedDialog = target.closest?.("[role=dialog]");
if (
focusedDialog &&
@@ -282,26 +285,26 @@ function CatalogManagerInner({
dispatch({ type: "SET_ACTIVE_TAB", id });
};
const handleCreateRoot = async () => {
if (!canEdit) return;
const caption = prompt("Root page name:");
if (!caption?.trim()) return;
const handleCreateRoot = async (caption: string): Promise<boolean> => {
if (!canEdit) return false;
try {
const result =
catalogType === "bc"
? await createBcPage({
parentId: -1,
caption: caption.trim(),
caption,
})
: await createCatalogPage({
parentId: -1,
caption: caption.trim(),
caption,
});
if (!result.ok) throw new Error(result.error);
await loadRootPages();
toast.success("Root page created");
return true;
} catch {
toast.error("Failed to create root page");
return false;
}
};