111 lines
2.9 KiB
TypeScript
111 lines
2.9 KiB
TypeScript
import { useState, useCallback, useEffect } from 'react';
|
|
import apiService from '../services/apiService';
|
|
|
|
// ============== INTERFACES ==============
|
|
|
|
export interface VersionChange {
|
|
field: string;
|
|
oldValue: any;
|
|
newValue: any;
|
|
}
|
|
|
|
export interface AuditLogEntry {
|
|
name: string;
|
|
owner: string;
|
|
creation: string;
|
|
changes: VersionChange[];
|
|
added: any[];
|
|
removed: any[];
|
|
rowChanged: any[];
|
|
}
|
|
|
|
interface UseAuditLogsOptions {
|
|
doctype: string;
|
|
docname: string | null;
|
|
limit?: number;
|
|
enabled?: boolean;
|
|
}
|
|
|
|
interface UseAuditLogsReturn {
|
|
auditLogs: AuditLogEntry[];
|
|
loading: boolean;
|
|
error: string | null;
|
|
refetch: () => void;
|
|
}
|
|
|
|
// ============== HOOK ==============
|
|
|
|
export const useAuditLogs = ({
|
|
doctype,
|
|
docname,
|
|
limit = 50,
|
|
enabled = true,
|
|
}: UseAuditLogsOptions): UseAuditLogsReturn => {
|
|
const [auditLogs, setAuditLogs] = useState<AuditLogEntry[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const fetchAuditLogs = useCallback(async () => {
|
|
if (!enabled || !doctype || !docname) return;
|
|
|
|
setLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const response = await apiService.apiCall<any>(
|
|
`/api/resource/Version?filters=[["ref_doctype","=","${encodeURIComponent(doctype)}"],["docname","=","${encodeURIComponent(docname)}"]]&fields=["name","owner","creation","data"]&order_by=creation desc&limit=${limit}`
|
|
);
|
|
|
|
if (response?.data && response.data.length > 0) {
|
|
const parsedLogs: AuditLogEntry[] = response.data.map((version: any) => {
|
|
let parsedData = { added: [], changed: [], removed: [], row_changed: [] };
|
|
try {
|
|
parsedData = JSON.parse(version.data || '{}');
|
|
} catch (e) {
|
|
console.error('Error parsing version data:', e);
|
|
}
|
|
|
|
const changes: VersionChange[] = (parsedData.changed || []).map((change: any[]) => ({
|
|
field: change[0] || '',
|
|
oldValue: change[1],
|
|
newValue: change[2],
|
|
}));
|
|
|
|
return {
|
|
name: version.name,
|
|
owner: version.owner,
|
|
creation: version.creation,
|
|
changes,
|
|
added: parsedData.added || [],
|
|
removed: parsedData.removed || [],
|
|
rowChanged: parsedData.row_changed || [],
|
|
};
|
|
});
|
|
|
|
setAuditLogs(parsedLogs);
|
|
} else {
|
|
setAuditLogs([]);
|
|
}
|
|
} catch (err) {
|
|
console.error(`Error fetching audit logs for ${doctype}/${docname}:`, err);
|
|
setError(err instanceof Error ? err.message : 'Failed to load activity log');
|
|
setAuditLogs([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [doctype, docname, limit, enabled]);
|
|
|
|
// Initial fetch
|
|
useEffect(() => {
|
|
fetchAuditLogs();
|
|
}, [fetchAuditLogs]);
|
|
|
|
return {
|
|
auditLogs,
|
|
loading,
|
|
error,
|
|
refetch: fetchAuditLogs,
|
|
};
|
|
};
|
|
|
|
export default useAuditLogs; |