mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 14:31:11 -05:00
Refactor: Implement system activity log fixes
This commit is contained in:
@@ -130,6 +130,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
const isMountingRef = useRef(true);
|
||||
const initialFetchCompleteRef = useRef(false);
|
||||
const FETCH_COOLDOWN_MS = 1000;
|
||||
const pauseFetchingRef = useRef(false);
|
||||
|
||||
// Pagination state
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
@@ -217,6 +218,12 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if tab is hidden - pause all fetching
|
||||
if (pauseFetchingRef.current || document.hidden) {
|
||||
console.log('⏸️ Fetch paused (tab hidden)');
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent concurrent calls - race condition guard
|
||||
if (fetchInProgressRef.current) {
|
||||
console.log('⚠️ Fetch already in progress, skipping duplicate call');
|
||||
@@ -803,6 +810,12 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
async (payload) => {
|
||||
const newSubmission = payload.new as any;
|
||||
|
||||
// Queue updates if tab is hidden
|
||||
if (document.hidden) {
|
||||
console.log('📴 Realtime event received while hidden - queuing for later');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore if recently removed (optimistic update)
|
||||
if (recentlyRemovedRef.current.has(newSubmission.id)) {
|
||||
return;
|
||||
@@ -977,6 +990,12 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
async (payload) => {
|
||||
const updatedSubmission = payload.new as any;
|
||||
|
||||
// Queue updates if tab is hidden
|
||||
if (document.hidden) {
|
||||
console.log('📴 Realtime UPDATE received while hidden - queuing for later');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore if recently removed (optimistic update in progress)
|
||||
if (recentlyRemovedRef.current.has(updatedSubmission.id)) {
|
||||
console.log('⏭️ Ignoring UPDATE for recently removed submission:', updatedSubmission.id);
|
||||
@@ -1146,6 +1165,27 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||
};
|
||||
}, [user, useRealtimeQueue, debouncedRealtimeUpdate]);
|
||||
|
||||
// Visibility change handler - pause queue updates when tab is hidden
|
||||
useEffect(() => {
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.hidden) {
|
||||
console.log('📴 Tab hidden - pausing queue updates');
|
||||
pauseFetchingRef.current = true;
|
||||
} else {
|
||||
console.log('📱 Tab visible - resuming queue updates');
|
||||
pauseFetchingRef.current = false;
|
||||
// Optional: trigger single refresh when tab becomes visible
|
||||
if (initialFetchCompleteRef.current && !isMountingRef.current) {
|
||||
console.log('🔄 Tab became visible - triggering refresh');
|
||||
fetchItems(filtersRef.current.entityFilter, filtersRef.current.statusFilter, true, activeTab);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
}, [fetchItems, activeTab]);
|
||||
|
||||
const handleResetToPending = async (item: ModerationItem) => {
|
||||
setActionLoading(item.id);
|
||||
try {
|
||||
|
||||
@@ -104,9 +104,11 @@ export async function fetchSystemActivities(
|
||||
const activities: SystemActivity[] = [];
|
||||
|
||||
// Fetch entity versions (entity changes)
|
||||
// Use simplified query without foreign key join - we'll fetch profiles separately
|
||||
const { data: versions, error: versionsError } = await supabase
|
||||
.from('entity_versions')
|
||||
.select('id, entity_type, entity_id, version_number, version_data, changed_by, changed_at, change_type, change_reason')
|
||||
.eq('is_current', true)
|
||||
.order('changed_at', { ascending: false })
|
||||
.limit(limit * 2); // Fetch more to account for filtering
|
||||
|
||||
@@ -117,7 +119,7 @@ export async function fetchSystemActivities(
|
||||
id: version.id,
|
||||
type: 'entity_change',
|
||||
timestamp: version.changed_at,
|
||||
actor_id: version.changed_by,
|
||||
actor_id: version.changed_by || null,
|
||||
action: `${version.change_type} ${version.entity_type}`,
|
||||
details: {
|
||||
entity_type: version.entity_type,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, Component, ReactNode } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { useUserRole } from '@/hooks/useUserRole';
|
||||
@@ -6,6 +6,48 @@ import { AdminLayout } from '@/components/layout/AdminLayout';
|
||||
import { SystemActivityLog } from '@/components/admin/SystemActivityLog';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||
import { AlertCircle } from 'lucide-react';
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
interface ErrorBoundaryState {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
constructor(props: ErrorBoundaryProps) {
|
||||
super(props);
|
||||
this.state = { hasError: false, error: null };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error) {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: any) {
|
||||
console.error('System Activity Log Error:', error, errorInfo);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error loading system activity log</AlertTitle>
|
||||
<AlertDescription>
|
||||
{this.state.error?.message || 'An unexpected error occurred'}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default function AdminSystemLog() {
|
||||
const { user, loading: authLoading } = useAuth();
|
||||
@@ -69,7 +111,9 @@ export default function AdminSystemLog() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ErrorBoundary>
|
||||
<SystemActivityLog limit={100} showFilters={true} />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user