mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 23:51:13 -05:00
Fix moderation queue refresh logic
This commit is contained in:
@@ -103,7 +103,6 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
const fetchInProgressRef = useRef(false);
|
const fetchInProgressRef = useRef(false);
|
||||||
const itemsRef = useRef<ModerationItem[]>([]);
|
const itemsRef = useRef<ModerationItem[]>([]);
|
||||||
const loadedIdsRef = useRef<Set<string>>(new Set());
|
const loadedIdsRef = useRef<Set<string>>(new Set());
|
||||||
const lastFetchTimestampRef = useRef<string | null>(null);
|
|
||||||
|
|
||||||
// Get admin settings for polling configuration
|
// Get admin settings for polling configuration
|
||||||
const {
|
const {
|
||||||
@@ -207,12 +206,8 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
submissionsQuery = submissionsQuery.neq('submission_type', 'photo');
|
submissionsQuery = submissionsQuery.neq('submission_type', 'photo');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Silent polling: fetch submissions created OR updated since last poll
|
// Always fetch ALL pending/partially_approved submissions
|
||||||
if (silent && lastFetchTimestampRef.current) {
|
// Let ID-based tracking determine what's "new" instead of timestamp filtering
|
||||||
submissionsQuery = submissionsQuery.or(
|
|
||||||
`submitted_at.gt.${lastFetchTimestampRef.current},updated_at.gt.${lastFetchTimestampRef.current}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// CRM-style claim filtering: moderators only see unclaimed OR self-assigned submissions
|
// CRM-style claim filtering: moderators only see unclaimed OR self-assigned submissions
|
||||||
// Admins see all submissions
|
// Admins see all submissions
|
||||||
@@ -435,17 +430,10 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
const currentPreserveInteraction = preserveInteractionRef.current;
|
const currentPreserveInteraction = preserveInteractionRef.current;
|
||||||
|
|
||||||
if (silent) {
|
if (silent) {
|
||||||
// Update timestamp using actual data timestamps, not current time
|
// Background polling: detect new submissions by comparing IDs
|
||||||
if (moderationItems.length > 0) {
|
// Use currently DISPLAYED items (itemsRef) not loadedIdsRef to avoid false positives
|
||||||
const maxTimestamp = Math.max(
|
const currentDisplayedIds = new Set(itemsRef.current.map(item => item.id));
|
||||||
...moderationItems.map(item => new Date(item.updated_at || item.created_at).getTime())
|
const newSubmissions = moderationItems.filter(item => !currentDisplayedIds.has(item.id));
|
||||||
);
|
|
||||||
lastFetchTimestampRef.current = new Date(maxTimestamp).toISOString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Background polling: behavior controlled by admin settings
|
|
||||||
const currentLoadedIds = loadedIdsRef.current;
|
|
||||||
const newSubmissions = moderationItems.filter(item => !currentLoadedIds.has(item.id));
|
|
||||||
|
|
||||||
if (newSubmissions.length > 0) {
|
if (newSubmissions.length > 0) {
|
||||||
console.log('🆕 Detected new submissions:', newSubmissions.length);
|
console.log('🆕 Detected new submissions:', newSubmissions.length);
|
||||||
@@ -458,6 +446,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
// Track these IDs as loaded to prevent re-counting on next poll
|
// Track these IDs as loaded to prevent re-counting on next poll
|
||||||
if (uniqueNew.length > 0) {
|
if (uniqueNew.length > 0) {
|
||||||
const newIds = uniqueNew.map(item => item.id);
|
const newIds = uniqueNew.map(item => item.id);
|
||||||
|
const currentLoadedIds = loadedIdsRef.current;
|
||||||
loadedIdsRef.current = new Set([...currentLoadedIds, ...newIds]);
|
loadedIdsRef.current = new Set([...currentLoadedIds, ...newIds]);
|
||||||
setNewItemsCount(prev => prev + uniqueNew.length);
|
setNewItemsCount(prev => prev + uniqueNew.length);
|
||||||
}
|
}
|
||||||
@@ -508,11 +497,15 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
} else {
|
} else {
|
||||||
// Normal fetch: Load all items and reset pending
|
// Normal fetch: Load all items and reset pending
|
||||||
console.log('🔄 Manual refresh - replacing entire queue');
|
console.log('🔄 Manual refresh - replacing entire queue');
|
||||||
lastFetchTimestampRef.current = null; // Reset timestamp to fetch everything next time
|
|
||||||
setItems(moderationItems);
|
setItems(moderationItems);
|
||||||
setPendingNewItems([]);
|
setPendingNewItems([]);
|
||||||
setNewItemsCount(0);
|
setNewItemsCount(0);
|
||||||
console.log('📋 Queue loaded with', moderationItems.length, 'submissions');
|
|
||||||
|
// Initialize loadedIdsRef on first load or manual refresh
|
||||||
|
if (loadedIdsRef.current.size === 0 || !silent) {
|
||||||
|
loadedIdsRef.current = new Set(moderationItems.map(item => item.id));
|
||||||
|
console.log('📋 Queue loaded - tracking', loadedIdsRef.current.size, 'submissions');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
-- Fix the update trigger to only update updated_at when actual content changes
|
||||||
|
-- This prevents false "new submission" detection in the moderation queue
|
||||||
|
|
||||||
|
-- Drop and recreate the trigger function to add proper change detection
|
||||||
|
DROP TRIGGER IF EXISTS update_content_submissions_updated_at ON public.content_submissions;
|
||||||
|
DROP FUNCTION IF EXISTS public.update_content_submissions_updated_at();
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION public.update_content_submissions_updated_at()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
-- Only update updated_at if actual content has changed
|
||||||
|
-- Ignore changes to: updated_at, assigned_to, assigned_at, locked_until, priority
|
||||||
|
IF (
|
||||||
|
NEW.content IS DISTINCT FROM OLD.content OR
|
||||||
|
NEW.status IS DISTINCT FROM OLD.status OR
|
||||||
|
NEW.reviewer_id IS DISTINCT FROM OLD.reviewer_id OR
|
||||||
|
NEW.reviewer_notes IS DISTINCT FROM OLD.reviewer_notes OR
|
||||||
|
NEW.escalated IS DISTINCT FROM OLD.escalated OR
|
||||||
|
NEW.escalation_reason IS DISTINCT FROM OLD.escalation_reason OR
|
||||||
|
NEW.approval_mode IS DISTINCT FROM OLD.approval_mode
|
||||||
|
) THEN
|
||||||
|
NEW.updated_at = NOW();
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE TRIGGER update_content_submissions_updated_at
|
||||||
|
BEFORE UPDATE ON public.content_submissions
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION public.update_content_submissions_updated_at();
|
||||||
Reference in New Issue
Block a user