Fix #1 (CRITICAL): Wire message_analyzed through Redis EventBroadcaster - DG aiAnalyzer.ts: Add broadcastAnalysisCompleted() helper that publishes to both in-memory WS broadcaster AND Redis EventBroadcaster - DG bootstrap.ts: Pass eventBroadcaster to startPendingAIAnalysisWorker() - Fixes broken real-time chain so analysis results appear instantly Fix #2: Collapsible AI Analysis with Rich Formatting - MessageCard: AI analysis now collapsible with color-coded severity border (red/yellow/blue), summary line showing categories + confidence + severity - Default collapsed for clean, expanded for warn/flagged Fix #3: Toast Notifications for Flagged Content - Wrap app in ToastProvider; ModerationAlertListener component listens for moderation_alert custom events and shows toast with emoji + details Fix #4: Discord-style Message Grouping - MessageFeed: Group consecutive messages from same user within 5 min - MessageCard: Compact variant hides avatar, reduces padding for non-first Fix #5: Moderation Action Buttons in UI - BE: POST /api/messages/:id/moderate endpoint + publishCommand() for Redis - FE: Delete/Warn buttons on flagged/warned cards with confirmation dialog Fix #6: Search Results Include Full Data - BE analysis.service.ts: SELECT all 26 message columns instead of just 11 - Search results now render with full MessageCard including images/analysis Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
34 lines
899 B
TypeScript
34 lines
899 B
TypeScript
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
import React from "react";
|
|
import ReactDOM from "react-dom/client";
|
|
import App from "./App";
|
|
import { ToastProvider } from "./shared/ui";
|
|
import "./styles.css";
|
|
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
staleTime: 30_000, // data stays fresh for 30s — no refetch within this window
|
|
gcTime: 5 * 60_000, // keep unused data in cache for 5 minutes
|
|
refetchOnWindowFocus: false, // avoid spamming the API on tab switches
|
|
retry: 2,
|
|
},
|
|
},
|
|
});
|
|
|
|
const root = document.getElementById("root");
|
|
|
|
if (!root) {
|
|
throw new Error("Root element not found");
|
|
}
|
|
|
|
ReactDOM.createRoot(root).render(
|
|
<React.StrictMode>
|
|
<QueryClientProvider client={queryClient}>
|
|
<ToastProvider>
|
|
<App />
|
|
</ToastProvider>
|
|
</QueryClientProvider>
|
|
</React.StrictMode>,
|
|
);
|