Compare commits

..

4 Commits

Author SHA1 Message Date
gpt-engineer-app[bot]
53b576ecc1 Invalidate all system-alerts queries on resolve
Update PipelineHealthAlerts resolve flow to invalidate all severity-specific system_alerts queries (not just the base key), ensuring resolved alerts disappear from UI. Adds broad invalidation pattern and preserves loading state handling.
2025-11-11 14:14:32 +00:00
gpt-engineer-app[bot]
eac8c7a77f Add robust loading cleanup
Ensure Resolve button clears loading state with proper try-catch-finally around async resolution, preventing stuck loading indicator and improving error handling.
2025-11-11 14:12:57 +00:00
gpt-engineer-app[bot]
21cd547c27 Add loading state to Resolve button
- Introduce per-button loading state in PipelineHealthAlerts
- Disable button and show spinner with "Resolving..." while resolving
- Re-enable after operation completes
- Keeps user feedback inline with alert resolution flow
2025-11-11 14:11:46 +00:00
gpt-engineer-app[bot]
da32935d63 Add debugging for Resolve on monitoring page
Enhance PipelineHealthAlerts flow to log and refresh
- Add console logs when resolving alerts on PipelineHealthAlerts
- Invalidate related queries to refresh UI after resolution
- Improve error handling and user feedback paths for resolve action
2025-11-11 14:10:10 +00:00

View File

@@ -5,14 +5,17 @@
* Shows top 10 active alerts with severity-based styling and resolution actions. * Shows top 10 active alerts with severity-based styling and resolution actions.
*/ */
import { useState } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { useSystemAlerts } from '@/hooks/useSystemHealth'; import { useSystemAlerts } from '@/hooks/useSystemHealth';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { AlertTriangle, CheckCircle, XCircle, AlertCircle } from 'lucide-react'; import { AlertTriangle, CheckCircle, XCircle, AlertCircle, Loader2 } from 'lucide-react';
import { format } from 'date-fns'; import { format } from 'date-fns';
import { supabase } from '@/lib/supabaseClient'; import { supabase } from '@/lib/supabaseClient';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { useQueryClient } from '@tanstack/react-query';
import { queryKeys } from '@/lib/queryKeys';
const SEVERITY_CONFIG = { const SEVERITY_CONFIG = {
critical: { color: 'destructive', icon: XCircle }, critical: { color: 'destructive', icon: XCircle },
@@ -38,6 +41,8 @@ const ALERT_TYPE_LABELS: Record<string, string> = {
}; };
export function PipelineHealthAlerts() { export function PipelineHealthAlerts() {
const queryClient = useQueryClient();
const [resolvingAlertId, setResolvingAlertId] = useState<string | null>(null);
const { data: criticalAlerts } = useSystemAlerts('critical'); const { data: criticalAlerts } = useSystemAlerts('critical');
const { data: highAlerts } = useSystemAlerts('high'); const { data: highAlerts } = useSystemAlerts('high');
const { data: mediumAlerts } = useSystemAlerts('medium'); const { data: mediumAlerts } = useSystemAlerts('medium');
@@ -49,15 +54,34 @@ export function PipelineHealthAlerts() {
].slice(0, 10); ].slice(0, 10);
const resolveAlert = async (alertId: string) => { const resolveAlert = async (alertId: string) => {
const { error } = await supabase console.log('🔴 Resolve button clicked in PipelineHealthAlerts', { alertId });
.from('system_alerts') setResolvingAlertId(alertId);
.update({ resolved_at: new Date().toISOString() })
.eq('id', alertId);
if (error) { try {
toast.error('Failed to resolve alert'); const { error } = await supabase
} else { .from('system_alerts')
.update({ resolved_at: new Date().toISOString() })
.eq('id', alertId);
if (error) {
console.error('❌ Error resolving alert:', error);
toast.error('Failed to resolve alert');
return;
}
console.log('✅ Alert resolved successfully');
toast.success('Alert resolved'); toast.success('Alert resolved');
// Invalidate all system-alerts queries (critical, high, medium, etc.)
await Promise.all([
queryClient.invalidateQueries({ queryKey: ['system-alerts'] }),
queryClient.invalidateQueries({ queryKey: queryKeys.monitoring.systemHealth() })
]);
} catch (err) {
console.error('❌ Unexpected error resolving alert:', err);
toast.error('An unexpected error occurred');
} finally {
setResolvingAlertId(null);
} }
}; };
@@ -113,8 +137,16 @@ export function PipelineHealthAlerts() {
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => resolveAlert(alert.id)} onClick={() => resolveAlert(alert.id)}
disabled={resolvingAlertId === alert.id}
> >
Resolve {resolvingAlertId === alert.id ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
Resolving...
</>
) : (
'Resolve'
)}
</Button> </Button>
</div> </div>
); );