mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:31:12 -05:00
Fix auto-refresh and queue claiming
This commit is contained in:
@@ -7,11 +7,12 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
|||||||
import { Textarea } from '@/components/ui/textarea';
|
import { Textarea } from '@/components/ui/textarea';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { useUserRole } from '@/hooks/useUserRole';
|
import { useUserRole } from '@/hooks/useUserRole';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { format } from 'date-fns';
|
import { format, formatDistance } from 'date-fns';
|
||||||
import { PhotoModal } from './PhotoModal';
|
import { PhotoModal } from './PhotoModal';
|
||||||
import { SubmissionReviewManager } from './SubmissionReviewManager';
|
import { SubmissionReviewManager } from './SubmissionReviewManager';
|
||||||
import { useIsMobile } from '@/hooks/use-mobile';
|
import { useIsMobile } from '@/hooks/use-mobile';
|
||||||
@@ -366,6 +367,17 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
|
|
||||||
// If there are changes and we should preserve interaction
|
// If there are changes and we should preserve interaction
|
||||||
if (mergeResult.hasChanges) {
|
if (mergeResult.hasChanges) {
|
||||||
|
// Debug logging for smart merge
|
||||||
|
console.log('🔄 Smart merge detected changes:', {
|
||||||
|
added: mergeResult.changes.added.length,
|
||||||
|
updated: mergeResult.changes.updated.length,
|
||||||
|
removed: mergeResult.changes.removed.length,
|
||||||
|
newItemsCount: mergeResult.changes.added.length,
|
||||||
|
protectedIds: Array.from(preserveInteraction ? interactingWith : new Set<string>()),
|
||||||
|
strategy: refreshStrategy,
|
||||||
|
preserveInteraction
|
||||||
|
});
|
||||||
|
|
||||||
// Filter out items user is interacting with
|
// Filter out items user is interacting with
|
||||||
const protectedIds = preserveInteraction ? interactingWith : new Set<string>();
|
const protectedIds = preserveInteraction ? interactingWith : new Set<string>();
|
||||||
const mergedWithProtection = mergeResult.items.map(item => {
|
const mergedWithProtection = mergeResult.items.map(item => {
|
||||||
@@ -2027,21 +2039,40 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* New Items Notification */}
|
{/* Auto-refresh Status Indicator */}
|
||||||
|
{refreshMode === 'auto' && (
|
||||||
|
<div className="flex items-center gap-2 text-xs text-muted-foreground px-1">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<div className="w-2 h-2 rounded-full bg-green-500 animate-pulse" />
|
||||||
|
<span>Auto-refresh active</span>
|
||||||
|
</div>
|
||||||
|
<span>•</span>
|
||||||
|
<span>Checking every {Math.round(pollInterval / 1000)}s</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* New Items Notification - Enhanced */}
|
||||||
{newItemsCount > 0 && (
|
{newItemsCount > 0 && (
|
||||||
<div className="flex items-center justify-center">
|
<div className="sticky top-0 z-10 animate-in fade-in-50">
|
||||||
<Button
|
<Alert className="border-primary/50 bg-primary/5">
|
||||||
variant="outline"
|
<AlertCircle className="h-4 w-4 animate-pulse" />
|
||||||
size="sm"
|
<AlertTitle>New Items Available</AlertTitle>
|
||||||
onClick={() => {
|
<AlertDescription className="flex items-center justify-between">
|
||||||
setNewItemsCount(0);
|
<span>{newItemsCount} new {newItemsCount === 1 ? 'submission' : 'submissions'} pending review</span>
|
||||||
fetchItems(activeEntityFilter, activeStatusFilter, false);
|
<Button
|
||||||
}}
|
variant="default"
|
||||||
className="flex items-center gap-2 border-primary/50 bg-primary/5 hover:bg-primary/10"
|
size="sm"
|
||||||
>
|
onClick={() => {
|
||||||
<RefreshCw className="w-4 h-4" />
|
setNewItemsCount(0);
|
||||||
Show {newItemsCount} new {newItemsCount === 1 ? 'item' : 'items'}
|
fetchItems(activeEntityFilter, activeStatusFilter, false);
|
||||||
</Button>
|
}}
|
||||||
|
className="ml-4"
|
||||||
|
>
|
||||||
|
<RefreshCw className="w-4 h-4 mr-2" />
|
||||||
|
Show New Items
|
||||||
|
</Button>
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
-- Fix ambiguous column reference in claim_next_submission
|
||||||
|
CREATE OR REPLACE FUNCTION public.claim_next_submission(
|
||||||
|
moderator_id UUID,
|
||||||
|
lock_duration INTERVAL DEFAULT '15 minutes'
|
||||||
|
)
|
||||||
|
RETURNS TABLE (
|
||||||
|
submission_id UUID,
|
||||||
|
submission_type TEXT,
|
||||||
|
priority INTEGER,
|
||||||
|
waiting_time INTERVAL
|
||||||
|
)
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
SECURITY DEFINER
|
||||||
|
SET search_path = public
|
||||||
|
AS $$
|
||||||
|
BEGIN
|
||||||
|
-- Update priority for all pending submissions first
|
||||||
|
UPDATE content_submissions
|
||||||
|
SET priority = calculate_submission_priority(id)
|
||||||
|
WHERE status IN ('pending', 'partially_approved')
|
||||||
|
AND (assigned_to IS NULL OR locked_until < NOW());
|
||||||
|
|
||||||
|
-- Claim next item with row-level lock
|
||||||
|
RETURN QUERY
|
||||||
|
UPDATE content_submissions
|
||||||
|
SET
|
||||||
|
assigned_to = moderator_id,
|
||||||
|
assigned_at = NOW(),
|
||||||
|
locked_until = NOW() + lock_duration,
|
||||||
|
first_reviewed_at = COALESCE(first_reviewed_at, NOW())
|
||||||
|
WHERE id = (
|
||||||
|
SELECT cs.id FROM content_submissions cs
|
||||||
|
WHERE cs.status IN ('pending', 'partially_approved')
|
||||||
|
AND (cs.assigned_to IS NULL OR cs.locked_until < NOW())
|
||||||
|
ORDER BY
|
||||||
|
cs.priority DESC,
|
||||||
|
cs.submitted_at ASC
|
||||||
|
LIMIT 1
|
||||||
|
FOR UPDATE SKIP LOCKED
|
||||||
|
)
|
||||||
|
RETURNING
|
||||||
|
content_submissions.id,
|
||||||
|
content_submissions.submission_type,
|
||||||
|
content_submissions.priority,
|
||||||
|
NOW() - content_submissions.submitted_at;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
Reference in New Issue
Block a user