From 08307119dad1d183af14b39a87e4bf60759726b0 Mon Sep 17 00:00:00 2001 From: kaushik Date: Tue, 14 Jul 2026 14:20:24 +0530 Subject: [PATCH] image scanning and asset edit --- src/api/activityFeedsService.ts | 10 ++ src/api/adminService.ts | 6 + src/pages/admin/MissingMedia.tsx | 23 +++- src/pages/audit-session/AuditSession.tsx | 153 +++++++++++++++++++++-- 4 files changed, 180 insertions(+), 12 deletions(-) diff --git a/src/api/activityFeedsService.ts b/src/api/activityFeedsService.ts index dffabd9..168386c 100644 --- a/src/api/activityFeedsService.ts +++ b/src/api/activityFeedsService.ts @@ -62,6 +62,16 @@ export const activityFeedsService = { return response; }, + // Corrects a single record's asset classification. The backend resolves + // the canonical asset_name from the central catalog and returns it. + updateAnomalyAsset: async (id: number, assetId: number, isRectificationEnabled: boolean) => { + const response = await axiosClient.put('/api/audit/anomaly/asset', + { id, asset_id: assetId }, + { params: { isRectificationEnabled } } + ); + return response as unknown as { id: number; asset_id: number; asset_name: string }; + }, + // Called after normal (non-rectification) true anomaly audit updateAnomalyInDashboard: async (payload: { site_id: string, anomaly_id: number[] }) => { const response = await axiosClient.post('/api/audit/auditor/anomaly/submit', payload); diff --git a/src/api/adminService.ts b/src/api/adminService.ts index f65a58e..cd1a985 100644 --- a/src/api/adminService.ts +++ b/src/api/adminService.ts @@ -177,11 +177,16 @@ export interface MissingMediaRecord { export interface MissingMediaSummary { total: number; neverChecked: number; + // Independent, inclusive counts: missingImage/missingVideo each include + // records missing both; missingBoth is the overlap. missingImage: number; missingVideo: number; + missingBoth: number; gaveUp: number; } +export type MissingMediaFilter = 'image' | 'video' | 'both'; + export interface MissingMediaResult { records: MissingMediaRecord[]; total: number; @@ -299,6 +304,7 @@ export const adminService = { type: 'audits' | 'rectification'; limit?: number; offset?: number; + missing?: MissingMediaFilter; }): Promise => { return (await axiosClient.get('/api/audit/admin/media-status', { params })) as unknown as MissingMediaResult; }, diff --git a/src/pages/admin/MissingMedia.tsx b/src/pages/admin/MissingMedia.tsx index 378a1ee..d4f9400 100644 --- a/src/pages/admin/MissingMedia.tsx +++ b/src/pages/admin/MissingMedia.tsx @@ -5,7 +5,7 @@ import { ToggleButton, Button, CircularProgress, TablePagination, Typography, Chip, Tooltip, } from '@mui/material'; import { adminService } from '../../api/adminService'; -import type { MissingMediaRecord, MissingMediaSummary } from '../../api/adminService'; +import type { MissingMediaRecord, MissingMediaSummary, MissingMediaFilter } from '../../api/adminService'; import { accountService } from '../../api/accountService'; import { useToastStore } from '../../store/toastStore'; @@ -27,6 +27,7 @@ export const MissingMedia: React.FC = () => { const [organizations, setOrganizations] = useState([]); const [dbName, setDbName] = useState(''); const [type, setType] = useState<'audits' | 'rectification'>('audits'); + const [missing, setMissing] = useState<'all' | MissingMediaFilter>('all'); const [records, setRecords] = useState([]); const [summary, setSummary] = useState(null); const [total, setTotal] = useState(0); @@ -53,23 +54,27 @@ export const MissingMedia: React.FC = () => { try { const result = await adminService.getMissingMedia({ dbName, type, limit: PAGE_SIZE, offset: page * PAGE_SIZE, + ...(missing !== 'all' ? { missing } : {}), }); setRecords(result.records); setTotal(result.total); setSummary(result.summary); + // A recheck under an active filter can shrink the filtered total below + // the current page - snap back instead of stranding on an empty page. + if (page > 0 && result.total <= page * PAGE_SIZE) setPage(0); } catch { useToastStore.getState().showToast('Failed to load missing-media records.', 'error'); } finally { setLoading(false); } - }, [dbName, type, page]); + }, [dbName, type, page, missing]); useEffect(() => { load(); }, [load]); useEffect(() => { setPage(0); setSelectedIds(new Set()); - }, [dbName, type]); + }, [dbName, type, missing]); const toggleRow = (id: number) => { setSelectedIds((prev) => { @@ -119,6 +124,13 @@ export const MissingMedia: React.FC = () => { Rectification + v && setMissing(v)} size="small"> + All + Image missing + Video missing + Both missing + + + + + + {/* Keyboard Shortcuts Dialog */}