feat(web): suppress browser ctrl+s and add file tree CRUD
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -127,6 +127,107 @@ export function useFileWrite(): UseMutationResult<
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: fileReadQueryKey(variables.workspaceId, variables.path),
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["workspaces", variables.workspaceId, "files"],
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export interface MkdirVariables {
|
||||
workspaceId: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export function useFileMkdir(): UseMutationResult<
|
||||
void,
|
||||
Error,
|
||||
MkdirVariables
|
||||
> {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ workspaceId, path }) => {
|
||||
const url = `/api/workspaces/${encodeURIComponent(workspaceId)}/files/mkdir`;
|
||||
const res = await apiClient(url, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ path }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to create folder: ${res.status}`);
|
||||
}
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["workspaces", variables.workspaceId, "files"],
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export interface RemoveVariables {
|
||||
workspaceId: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export function useFileRemove(): UseMutationResult<
|
||||
void,
|
||||
Error,
|
||||
RemoveVariables
|
||||
> {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ workspaceId, path }) => {
|
||||
const url =
|
||||
`/api/workspaces/${encodeURIComponent(workspaceId)}/files?` +
|
||||
new URLSearchParams({ path }).toString();
|
||||
const res = await apiClient(url, { method: "DELETE" });
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to delete file: ${res.status}`);
|
||||
}
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["workspaces", variables.workspaceId, "files"],
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: fileReadQueryKey(variables.workspaceId, variables.path),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export interface RenameVariables {
|
||||
workspaceId: string;
|
||||
oldPath: string;
|
||||
newPath: string;
|
||||
}
|
||||
|
||||
export function useFileRename(): UseMutationResult<
|
||||
void,
|
||||
Error,
|
||||
RenameVariables
|
||||
> {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ workspaceId, oldPath, newPath }) => {
|
||||
const url = `/api/workspaces/${encodeURIComponent(workspaceId)}/files/rename`;
|
||||
const res = await apiClient(url, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ oldPath, newPath }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to rename file: ${res.status}`);
|
||||
}
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["workspaces", variables.workspaceId, "files"],
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: fileReadQueryKey(variables.workspaceId, variables.oldPath),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user