127 lines
4 KiB
TypeScript
127 lines
4 KiB
TypeScript
/**
|
|
* useWorkspaceEditor Hook
|
|
*
|
|
* State management for the workspace editor page.
|
|
* Loads pending file edit proposals from the API,
|
|
* provides accept/reject actions, and tracks the active tab.
|
|
*/
|
|
|
|
import { useState, useCallback, useEffect } from 'react';
|
|
import api from '../../../api';
|
|
|
|
export interface EditorFileEdit {
|
|
id: string;
|
|
fileId: string;
|
|
fileName: string;
|
|
mimeType: string;
|
|
oldContent: string;
|
|
newContent: string;
|
|
status: 'pending' | 'accepted' | 'rejected';
|
|
workflowId: string;
|
|
}
|
|
|
|
interface UseWorkspaceEditorReturn {
|
|
edits: EditorFileEdit[];
|
|
activeEditId: string | null;
|
|
isLoading: boolean;
|
|
setActiveEditId: (id: string | null) => void;
|
|
acceptEdit: (editId: string) => Promise<void>;
|
|
rejectEdit: (editId: string) => Promise<void>;
|
|
acceptAll: () => Promise<void>;
|
|
rejectAll: () => Promise<void>;
|
|
refresh: () => void;
|
|
pendingCount: number;
|
|
}
|
|
|
|
export function useWorkspaceEditor(instanceId: string): UseWorkspaceEditorReturn {
|
|
const [edits, setEdits] = useState<EditorFileEdit[]>([]);
|
|
const [activeEditId, setActiveEditId] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const refresh = useCallback(() => {
|
|
if (!instanceId) return;
|
|
setIsLoading(true);
|
|
api.get(`/api/workspace/${instanceId}/pending-edits`)
|
|
.then(res => {
|
|
const loadedEdits: EditorFileEdit[] = (res.data.edits || []).map((e: any) => ({
|
|
id: e.id,
|
|
fileId: e.fileId || '',
|
|
fileName: e.fileName || '',
|
|
mimeType: e.mimeType || '',
|
|
oldContent: e.oldContent || '',
|
|
newContent: e.newContent || '',
|
|
status: e.status || 'pending',
|
|
workflowId: e.workflowId || '',
|
|
}));
|
|
setEdits(loadedEdits);
|
|
if (loadedEdits.length > 0 && !activeEditId) {
|
|
setActiveEditId(loadedEdits[0].id);
|
|
}
|
|
})
|
|
.catch(err => console.error('Failed to load pending edits:', err))
|
|
.finally(() => setIsLoading(false));
|
|
}, [instanceId, activeEditId]);
|
|
|
|
useEffect(() => {
|
|
refresh();
|
|
}, [instanceId]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
const acceptEdit = useCallback(async (editId: string) => {
|
|
if (!instanceId) return;
|
|
setEdits(prev => prev.map(e => (e.id === editId ? { ...e, status: 'accepted' as const } : e)));
|
|
try {
|
|
await api.post(`/api/workspace/${instanceId}/edit/${editId}/accept`);
|
|
} catch (err) {
|
|
console.error('Failed to accept edit:', err);
|
|
setEdits(prev => prev.map(e => (e.id === editId ? { ...e, status: 'pending' as const } : e)));
|
|
}
|
|
}, [instanceId]);
|
|
|
|
const rejectEdit = useCallback(async (editId: string) => {
|
|
if (!instanceId) return;
|
|
setEdits(prev => prev.map(e => (e.id === editId ? { ...e, status: 'rejected' as const } : e)));
|
|
try {
|
|
await api.post(`/api/workspace/${instanceId}/edit/${editId}/reject`);
|
|
} catch (err) {
|
|
console.error('Failed to reject edit:', err);
|
|
setEdits(prev => prev.map(e => (e.id === editId ? { ...e, status: 'pending' as const } : e)));
|
|
}
|
|
}, [instanceId]);
|
|
|
|
const acceptAll = useCallback(async () => {
|
|
if (!instanceId) return;
|
|
setEdits(prev => prev.map(e => (e.status === 'pending' ? { ...e, status: 'accepted' as const } : e)));
|
|
try {
|
|
await api.post(`/api/workspace/${instanceId}/edit/accept-all`);
|
|
} catch (err) {
|
|
console.error('Failed to accept all edits:', err);
|
|
refresh();
|
|
}
|
|
}, [instanceId, refresh]);
|
|
|
|
const rejectAll = useCallback(async () => {
|
|
if (!instanceId) return;
|
|
setEdits(prev => prev.map(e => (e.status === 'pending' ? { ...e, status: 'rejected' as const } : e)));
|
|
try {
|
|
await api.post(`/api/workspace/${instanceId}/edit/reject-all`);
|
|
} catch (err) {
|
|
console.error('Failed to reject all edits:', err);
|
|
refresh();
|
|
}
|
|
}, [instanceId, refresh]);
|
|
|
|
const pendingCount = edits.filter(e => e.status === 'pending').length;
|
|
|
|
return {
|
|
edits,
|
|
activeEditId,
|
|
isLoading,
|
|
setActiveEditId,
|
|
acceptEdit,
|
|
rejectEdit,
|
|
acceptAll,
|
|
rejectAll,
|
|
refresh,
|
|
pendingCount,
|
|
};
|
|
}
|