feat(logs): add workspace activity log page
This commit is contained in:
140
src/api/logs.ts
Normal file
140
src/api/logs.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { authFetch } from "./client";
|
||||
|
||||
export type WorkspaceLogSection =
|
||||
| "workspace"
|
||||
| "workspace_members"
|
||||
| "clients"
|
||||
| "projects"
|
||||
| "project_members"
|
||||
| "tags"
|
||||
| "time_entries"
|
||||
| "rates"
|
||||
| "report_exports";
|
||||
|
||||
export type WorkspaceLogEvent =
|
||||
| "create"
|
||||
| "update"
|
||||
| "delete"
|
||||
| "restore"
|
||||
| "archive"
|
||||
| "unarchive"
|
||||
| "activate"
|
||||
| "deactivate";
|
||||
|
||||
export interface WorkspaceLogActor {
|
||||
id: string;
|
||||
full_name: string;
|
||||
mobile?: string | null;
|
||||
profile_picture?: string | null;
|
||||
}
|
||||
|
||||
export interface WorkspaceLogTarget {
|
||||
id: string;
|
||||
name: string;
|
||||
section: WorkspaceLogSection;
|
||||
workspace_id: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceLogPreviewChange {
|
||||
field: string;
|
||||
label: string;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceLogItem {
|
||||
id: number;
|
||||
timestamp: string;
|
||||
section: WorkspaceLogSection;
|
||||
model: string | null;
|
||||
event: WorkspaceLogEvent;
|
||||
audit_action: string;
|
||||
actor: WorkspaceLogActor | null;
|
||||
target: WorkspaceLogTarget;
|
||||
changed_fields: string[];
|
||||
preview_changes: WorkspaceLogPreviewChange[];
|
||||
}
|
||||
|
||||
export interface WorkspaceLogChangeRow {
|
||||
field: string;
|
||||
label: string;
|
||||
change_type: "field" | "m2m";
|
||||
operation: string;
|
||||
old_value: string | null;
|
||||
new_value: string | null;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceLogDetail extends WorkspaceLogItem {
|
||||
remote_addr?: string | null;
|
||||
changes: WorkspaceLogChangeRow[];
|
||||
raw_changes: Record<string, unknown>;
|
||||
serialized_snapshot?: unknown;
|
||||
additional_data: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface WorkspaceLogFilters {
|
||||
workspace: string;
|
||||
section?: WorkspaceLogSection | "";
|
||||
actor?: string;
|
||||
event?: WorkspaceLogEvent | "";
|
||||
search?: string;
|
||||
from?: string;
|
||||
to?: string;
|
||||
ordering?: "-timestamp" | "timestamp";
|
||||
}
|
||||
|
||||
interface PaginatedResponse<T> {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: T[];
|
||||
}
|
||||
|
||||
const toQueryString = (params: Record<string, string | number | undefined>) => {
|
||||
const query = new URLSearchParams();
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== null && value !== "") {
|
||||
query.set(key, String(value));
|
||||
}
|
||||
});
|
||||
return query.toString();
|
||||
};
|
||||
|
||||
export const listWorkspaceLogs = async (
|
||||
filters: WorkspaceLogFilters,
|
||||
pagination?: { limit?: number; offset?: number },
|
||||
): Promise<PaginatedResponse<WorkspaceLogItem>> => {
|
||||
const query = toQueryString({
|
||||
workspace: filters.workspace,
|
||||
section: filters.section || undefined,
|
||||
actor: filters.actor || undefined,
|
||||
event: filters.event || undefined,
|
||||
search: filters.search || undefined,
|
||||
from: filters.from || undefined,
|
||||
to: filters.to || undefined,
|
||||
ordering: filters.ordering || "-timestamp",
|
||||
limit: pagination?.limit,
|
||||
offset: pagination?.offset,
|
||||
});
|
||||
|
||||
const response = await authFetch(`/api/logs/${query ? `?${query}` : ""}`);
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch workspace logs.");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return {
|
||||
count: data.count || 0,
|
||||
next: data.next || null,
|
||||
previous: data.previous || null,
|
||||
results: data.results || [],
|
||||
};
|
||||
};
|
||||
|
||||
export const getWorkspaceLogDetail = async (id: number): Promise<WorkspaceLogDetail> => {
|
||||
const response = await authFetch(`/api/logs/${id}/`);
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch workspace log detail.");
|
||||
}
|
||||
return await response.json();
|
||||
};
|
||||
Reference in New Issue
Block a user