mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-17 01:22:45 +00:00
feat: use workspace ids instead of paths for workspace operations
This commit is contained in:
@@ -57,16 +57,16 @@ export const getWorkspaceSessions = async (): Promise<WorkspaceRecord[]> => {
|
||||
};
|
||||
|
||||
export const updateWorkspaceStar = async (
|
||||
workspacePath: string,
|
||||
): Promise<{ workspacePath: string; isStarred: boolean }> => {
|
||||
workspaceId: string,
|
||||
): Promise<{ workspaceId: string; isStarred: boolean }> => {
|
||||
const response = await authenticatedFetch(SIDEBAR_ENDPOINTS.updateWorkspaceStar, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify({ workspacePath }),
|
||||
body: JSON.stringify({ workspaceId }),
|
||||
});
|
||||
const payload = await parseJsonSafely<{
|
||||
success?: boolean;
|
||||
data?: {
|
||||
workspacePath?: string;
|
||||
workspaceId?: string;
|
||||
isStarred?: boolean;
|
||||
};
|
||||
error?: { message?: string };
|
||||
@@ -80,18 +80,18 @@ export const updateWorkspaceStar = async (
|
||||
}
|
||||
|
||||
return {
|
||||
workspacePath: payload?.data?.workspacePath || workspacePath,
|
||||
workspaceId: payload?.data?.workspaceId || workspaceId,
|
||||
isStarred: Boolean(payload?.data?.isStarred),
|
||||
};
|
||||
};
|
||||
|
||||
export const updateWorkspaceCustomName = async (
|
||||
workspacePath: string,
|
||||
workspaceId: string,
|
||||
workspaceCustomName: string | null,
|
||||
): Promise<void> => {
|
||||
const response = await authenticatedFetch(SIDEBAR_ENDPOINTS.updateWorkspaceCustomName, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify({ workspacePath, workspaceCustomName }),
|
||||
body: JSON.stringify({ workspaceId, workspaceCustomName }),
|
||||
});
|
||||
const payload = await parseJsonSafely<{ error?: { message?: string } }>(response);
|
||||
|
||||
@@ -103,10 +103,10 @@ export const updateWorkspaceCustomName = async (
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteWorkspaceByPath = async (workspacePath: string): Promise<void> => {
|
||||
export const deleteWorkspaceById = async (workspaceId: string): Promise<void> => {
|
||||
const response = await authenticatedFetch(SIDEBAR_ENDPOINTS.deleteWorkspace, {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify({ workspacePath }),
|
||||
body: JSON.stringify({ workspaceId }),
|
||||
});
|
||||
const payload = await parseJsonSafely<{ error?: { message?: string } }>(response);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
deleteSessionById,
|
||||
deleteWorkspaceByPath,
|
||||
deleteWorkspaceById,
|
||||
getWorkspaceSessions,
|
||||
updateSessionCustomName,
|
||||
updateWorkspaceCustomName,
|
||||
@@ -95,7 +95,7 @@ export const useWorkspaces = () => {
|
||||
[filteredWorkspaces],
|
||||
);
|
||||
|
||||
const toggleWorkspace = useCallback((workspacePath: string) => {
|
||||
const toggleWorkspace = useCallback((workspaceId: string, workspacePath: string) => {
|
||||
setExpandedWorkspaces((previousSet) => {
|
||||
const nextSet = new Set(previousSet);
|
||||
|
||||
@@ -107,7 +107,8 @@ export const useWorkspaces = () => {
|
||||
|
||||
return nextSet;
|
||||
});
|
||||
}, []);
|
||||
navigate(`/workspace/${encodeURIComponent(workspaceId)}`);
|
||||
}, [navigate]);
|
||||
|
||||
const openSession = useCallback(
|
||||
(workspacePath: string, sessionId: string) => {
|
||||
@@ -125,9 +126,9 @@ export const useWorkspaces = () => {
|
||||
navigate('/');
|
||||
}, [navigate]);
|
||||
|
||||
const toggleWorkspaceStar = useCallback(async (workspacePath: string) => {
|
||||
const toggleWorkspaceStar = useCallback(async (workspaceId: string) => {
|
||||
try {
|
||||
await updateWorkspaceStar(workspacePath);
|
||||
await updateWorkspaceStar(workspaceId);
|
||||
await refreshWorkspaces();
|
||||
} catch (error) {
|
||||
console.error('Failed to update workspace star:', error);
|
||||
@@ -149,10 +150,17 @@ export const useWorkspaces = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const editingWorkspace = workspaces.find(
|
||||
(workspace) => workspace.workspaceOriginalPath === editingWorkspacePath,
|
||||
);
|
||||
if (!editingWorkspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsSavingWorkspaceName(true);
|
||||
try {
|
||||
const trimmedName = editingWorkspaceName.trim();
|
||||
await updateWorkspaceCustomName(editingWorkspacePath, trimmedName || null);
|
||||
await updateWorkspaceCustomName(editingWorkspace.workspaceId, trimmedName || null);
|
||||
await refreshWorkspaces();
|
||||
cancelWorkspaceRename();
|
||||
} catch (error) {
|
||||
@@ -165,10 +173,12 @@ export const useWorkspaces = () => {
|
||||
editingWorkspaceName,
|
||||
editingWorkspacePath,
|
||||
refreshWorkspaces,
|
||||
workspaces,
|
||||
]);
|
||||
|
||||
const requestWorkspaceDelete = useCallback((workspace: WorkspaceRecord) => {
|
||||
setWorkspaceDeleteTarget({
|
||||
workspaceId: workspace.workspaceId,
|
||||
workspacePath: workspace.workspaceOriginalPath,
|
||||
workspaceName: getWorkspaceDisplayName(workspace),
|
||||
sessionCount: workspace.sessions.length,
|
||||
@@ -184,10 +194,11 @@ export const useWorkspaces = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const deletingWorkspaceId = workspaceDeleteTarget.workspaceId;
|
||||
const deletingWorkspacePath = workspaceDeleteTarget.workspacePath;
|
||||
setWorkspaceDeleteTarget(null);
|
||||
try {
|
||||
await deleteWorkspaceByPath(deletingWorkspacePath);
|
||||
await deleteWorkspaceById(deletingWorkspaceId);
|
||||
|
||||
// If the current session belonged to the deleted workspace, reset to root.
|
||||
const hadSelectedSession = workspaces.some(
|
||||
|
||||
@@ -15,6 +15,7 @@ export type WorkspaceSession = {
|
||||
};
|
||||
|
||||
export type WorkspaceRecord = {
|
||||
workspaceId: string;
|
||||
workspaceOriginalPath: string;
|
||||
workspaceCustomName: string | null;
|
||||
workspaceDisplayName: string;
|
||||
@@ -24,6 +25,7 @@ export type WorkspaceRecord = {
|
||||
};
|
||||
|
||||
export type WorkspaceDeleteTarget = {
|
||||
workspaceId: string;
|
||||
workspacePath: string;
|
||||
workspaceName: string;
|
||||
sessionCount: number;
|
||||
|
||||
@@ -29,8 +29,8 @@ type SidebarWorkspaceItemProps = {
|
||||
isSavingSessionName: boolean;
|
||||
onEditingWorkspaceNameChange: (name: string) => void;
|
||||
onEditingSessionNameChange: (name: string) => void;
|
||||
onToggleWorkspace: (workspacePath: string) => void;
|
||||
onToggleWorkspaceStar: (workspacePath: string) => void;
|
||||
onToggleWorkspace: (workspaceId: string, workspacePath: string) => void;
|
||||
onToggleWorkspaceStar: (workspaceId: string) => void;
|
||||
onStartWorkspaceRename: (workspace: WorkspaceRecord) => void;
|
||||
onCancelWorkspaceRename: () => void;
|
||||
onSaveWorkspaceRename: () => void;
|
||||
@@ -95,7 +95,7 @@ export function SidebarWorkspaceItem({
|
||||
!hasSelectedSession &&
|
||||
'border-yellow-200/30 bg-yellow-50/50 dark:border-yellow-800/30 dark:bg-yellow-900/5',
|
||||
)}
|
||||
onClick={() => onToggleWorkspace(workspace.workspaceOriginalPath)}
|
||||
onClick={() => onToggleWorkspace(workspace.workspaceId, workspace.workspaceOriginalPath)}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-3">
|
||||
@@ -179,7 +179,7 @@ export function SidebarWorkspaceItem({
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onToggleWorkspaceStar(workspace.workspaceOriginalPath);
|
||||
onToggleWorkspaceStar(workspace.workspaceId);
|
||||
}}
|
||||
title={workspace.isStarred ? 'Remove from Starred' : 'Add to Starred'}
|
||||
>
|
||||
@@ -236,7 +236,7 @@ export function SidebarWorkspaceItem({
|
||||
!hasSelectedSession &&
|
||||
'bg-yellow-50/50 hover:bg-yellow-100/50 dark:bg-yellow-900/10 dark:hover:bg-yellow-900/20',
|
||||
)}
|
||||
onClick={() => onToggleWorkspace(workspace.workspaceOriginalPath)}
|
||||
onClick={() => onToggleWorkspace(workspace.workspaceId, workspace.workspaceOriginalPath)}
|
||||
>
|
||||
<div className="flex min-w-0 flex-1 items-center gap-3">
|
||||
{isExpanded ? (
|
||||
@@ -318,7 +318,7 @@ export function SidebarWorkspaceItem({
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onToggleWorkspaceStar(workspace.workspaceOriginalPath);
|
||||
onToggleWorkspaceStar(workspace.workspaceId);
|
||||
}}
|
||||
title={workspace.isStarred ? 'Remove from Starred' : 'Add to Starred'}
|
||||
>
|
||||
|
||||
@@ -16,8 +16,8 @@ type SidebarWorkspaceListProps = {
|
||||
isSavingSessionName: boolean;
|
||||
onEditingWorkspaceNameChange: (name: string) => void;
|
||||
onEditingSessionNameChange: (name: string) => void;
|
||||
onToggleWorkspace: (workspacePath: string) => void;
|
||||
onToggleWorkspaceStar: (workspacePath: string) => void;
|
||||
onToggleWorkspace: (workspaceId: string, workspacePath: string) => void;
|
||||
onToggleWorkspaceStar: (workspaceId: string) => void;
|
||||
onStartWorkspaceRename: (workspace: WorkspaceRecord) => void;
|
||||
onCancelWorkspaceRename: () => void;
|
||||
onSaveWorkspaceRename: () => void;
|
||||
|
||||
Reference in New Issue
Block a user