feat: improve session naming, project display, rename support, tab titles
Backend:
- sessions.py: include workspace_name in session response
- instance_service.py: auto-generate display names as
'Project / Workspace / Tool #N' instead of 'Workspace / Tool #N'
- instance_service.py: add rename_tool_instance() service function
- tool_instances.py: add PATCH /instances/{id} endpoint for renaming
display_name
Frontend:
- api/sessions.ts: add workspace_name to Session type, add renameInstance()
- use-instance-actions.ts: add handleRename, set document.title when opening
- session-card.tsx: click-to-edit display_name inline; always show project
context line (Project / Workspace or Repo / Tool)
- session-list.tsx: pass through onRename prop
- SessionsPage.tsx: wire handleRename to SessionCard and SessionList
- app-shell.tsx: sidebar tooltip includes workspace or repo name
- use-terminal-page.ts: set document.title based on active terminal session
Quality gates: py_compile all backend files pass, tsc --noEmit pass,
npm run build pass, 82/82 tests pass
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
deleteInstance,
|
||||
startInstance,
|
||||
recreateInstanceTunnel,
|
||||
renameInstance,
|
||||
} from "../api/sessions";
|
||||
import type { Session } from "../api/sessions";
|
||||
|
||||
@@ -21,6 +22,7 @@ interface UseInstanceActionsReturn {
|
||||
handleDelete: (session: Session) => Promise<void>;
|
||||
handleForceDelete: (session: Session) => Promise<void>;
|
||||
handleRecreateTunnel: (session: Session) => Promise<void>;
|
||||
handleRename: (session: Session, newName: string) => Promise<void>;
|
||||
clearDirtyDelete: () => void;
|
||||
}
|
||||
|
||||
@@ -52,6 +54,7 @@ export function useInstanceActions(
|
||||
url = `/projects/${session.project_id}`;
|
||||
}
|
||||
|
||||
document.title = `${session.display_name} — Headquarter`;
|
||||
const w = window.open(url, `session-${session.id}`);
|
||||
tabRefs.current.set(key, w);
|
||||
}, []);
|
||||
@@ -177,6 +180,27 @@ export function useInstanceActions(
|
||||
[loadingSessionId, onRefresh],
|
||||
);
|
||||
|
||||
const handleRename = useCallback(
|
||||
async (session: Session, newName: string) => {
|
||||
if (!newName.trim()) return;
|
||||
setLoadingSessionId(session.id);
|
||||
try {
|
||||
await renameInstance(
|
||||
session.project_id,
|
||||
session.repository_id,
|
||||
session.id,
|
||||
newName.trim(),
|
||||
);
|
||||
await onRefresh();
|
||||
} catch {
|
||||
// ignore
|
||||
} finally {
|
||||
setLoadingSessionId(null);
|
||||
}
|
||||
},
|
||||
[onRefresh],
|
||||
);
|
||||
|
||||
const clearDirtyDelete = useCallback(() => {
|
||||
setDirtyDeleteSession(null);
|
||||
setDirtyDeleteFiles([]);
|
||||
@@ -192,6 +216,7 @@ export function useInstanceActions(
|
||||
handleDelete,
|
||||
handleForceDelete,
|
||||
handleRecreateTunnel,
|
||||
handleRename,
|
||||
clearDirtyDelete,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user