Kraft102's picture
fix: sql.js Docker/Alpine compatibility layer for PatternMemory and FailureMemory
5a81b95
import { createContext, useContext, useState, useCallback, ReactNode } from 'react';
// Types for widget communication
export interface WidgetFilter {
severity?: 'all' | 'critical' | 'high' | 'medium' | 'low';
region?: string;
timeRange?: '1h' | '6h' | '24h' | '7d' | '30d';
searchQuery?: string;
}
export interface WidgetEvent {
type: string;
sourceWidgetId: string;
payload: any;
timestamp: number;
}
export interface SharedData {
selectedThreat?: { id: string; name: string; severity: string };
selectedRegion?: string;
highlightedIP?: string;
activeAlert?: { id: string; type: string; message: string };
}
interface WidgetContextType {
// Global filters
filters: WidgetFilter;
setFilters: (filters: Partial<WidgetFilter>) => void;
resetFilters: () => void;
// Shared data between widgets
sharedData: SharedData;
updateSharedData: (data: Partial<SharedData>) => void;
// Event system for widget communication
publishEvent: (event: Omit<WidgetEvent, 'timestamp'>) => void;
subscribeToEvents: (callback: (event: WidgetEvent) => void) => () => void;
// Recent events for debugging/display
recentEvents: WidgetEvent[];
}
const defaultFilters: WidgetFilter = {
severity: 'all',
region: undefined,
timeRange: '24h',
searchQuery: '',
};
const WidgetContext = createContext<WidgetContextType | null>(null);
export const WidgetProvider = ({ children }: { children: ReactNode }) => {
const [filters, setFiltersState] = useState<WidgetFilter>(defaultFilters);
const [sharedData, setSharedData] = useState<SharedData>({});
const [recentEvents, setRecentEvents] = useState<WidgetEvent[]>([]);
const [subscribers, setSubscribers] = useState<Set<(event: WidgetEvent) => void>>(new Set());
const setFilters = useCallback((newFilters: Partial<WidgetFilter>) => {
setFiltersState(prev => ({ ...prev, ...newFilters }));
}, []);
const resetFilters = useCallback(() => {
setFiltersState(defaultFilters);
}, []);
const updateSharedData = useCallback((data: Partial<SharedData>) => {
setSharedData(prev => ({ ...prev, ...data }));
}, []);
const publishEvent = useCallback((event: Omit<WidgetEvent, 'timestamp'>) => {
const fullEvent: WidgetEvent = {
...event,
timestamp: Date.now(),
};
// Add to recent events (keep last 50)
setRecentEvents(prev => [fullEvent, ...prev.slice(0, 49)]);
// Notify all subscribers
subscribers.forEach(callback => callback(fullEvent));
console.log('[WidgetContext] Event published:', fullEvent);
}, [subscribers]);
const subscribeToEvents = useCallback((callback: (event: WidgetEvent) => void) => {
setSubscribers(prev => new Set(prev).add(callback));
// Return unsubscribe function
return () => {
setSubscribers(prev => {
const newSet = new Set(prev);
newSet.delete(callback);
return newSet;
});
};
}, []);
return (
<WidgetContext.Provider value={{
filters,
setFilters,
resetFilters,
sharedData,
updateSharedData,
publishEvent,
subscribeToEvents,
recentEvents,
}}>
{children}
</WidgetContext.Provider>
);
};
export const useWidgetContext = () => {
const context = useContext(WidgetContext);
if (!context) {
throw new Error('useWidgetContext must be used within a WidgetProvider');
}
return context;
};
// Custom hook for widgets to easily communicate
export const useWidgetCommunication = (widgetId: string) => {
const context = useWidgetContext();
const publish = useCallback((type: string, payload: any) => {
context.publishEvent({
type,
sourceWidgetId: widgetId,
payload,
});
}, [context, widgetId]);
const selectThreat = useCallback((threat: { id: string; name: string; severity: string }) => {
context.updateSharedData({ selectedThreat: threat });
publish('threat_selected', threat);
}, [context, publish]);
const selectRegion = useCallback((region: string) => {
context.updateSharedData({ selectedRegion: region });
context.setFilters({ region });
publish('region_selected', { region });
}, [context, publish]);
const highlightIP = useCallback((ip: string) => {
context.updateSharedData({ highlightedIP: ip });
publish('ip_highlighted', { ip });
}, [context, publish]);
const selectAlert = useCallback((alert: { id: string; type: string; message: string }) => {
context.updateSharedData({ activeAlert: alert });
publish('alert_selected', alert);
}, [context, publish]);
return {
...context,
publish,
selectThreat,
selectRegion,
highlightIP,
selectAlert,
};
};