diff --git a/client/src/components/Widgets/ExplosionEvents.jsx b/client/src/components/Widgets/ExplosionEvents.jsx index e5b14af..ddd8044 100644 --- a/client/src/components/Widgets/ExplosionEvents.jsx +++ b/client/src/components/Widgets/ExplosionEvents.jsx @@ -1,12 +1,16 @@ import { useMemo } from 'react'; import { Box, Flex, Spinner, Text } from '@chakra-ui/react'; +import { useColorMode } from "@/components/ui/color-mode.jsx"; import Plot from 'react-plotly.js'; import VdapApi from '../../hooks/useVdapApi.js'; // Adjust path as needed export default function ExplosionEvents({ settings }) { - console.log("3. Chart received settings:", settings); // Plotly expects 'linear' for normal axes - const plotYAxisType = settings?.yAxisScale === 'symlog' ? 'symlog' : 'linear'; + const plotYAxisType = settings?.yAxisScale === 'log' ? 'log' : 'linear'; + + // 🎨 Let's check color mode so we can make people happy with light and dark + const { colorMode } = useColorMode(); + const isDark = colorMode === 'dark'; // Clean, single-line data fetching const { data: apiData, isLoading, error } = VdapApi('/api/v2/explosion_events?start_date=2025-05-01&end_date=2025-05-30'); @@ -23,16 +27,17 @@ export default function ExplosionEvents({ settings }) { 'hexagon', 'octagon', 'cross', 'x' ]; - // Sort data descending by flight level (matching Observable behavior) - const sortedData = [...apiData].sort((a, b) => b.obs_fl - a.obs_fl); + // Sort data descending by number of events so smaller dots draw on top of larger ones + const sortedData = [...apiData].sort((a, b) => b.number_events - a.number_events); // Efficiently group into Plotly traces by volcano const groupedData = sortedData.reduce((acc, curr) => { - const name = curr.volc_name || 'Unknown'; + const name = curr.volcano_name || 'Unknown'; if (!acc[name]) acc[name] = { x: [], y: [] }; - acc[name].x.push(new Date(curr.obs_va_epoch)); - acc[name].y.push(curr.obs_fl); + // Map the explosion-specific keys + acc[name].x.push(new Date(curr.ts_epoch)); + acc[name].y.push(curr.number_events); return acc; }, {}); @@ -47,11 +52,11 @@ export default function ExplosionEvents({ settings }) { line: { width: .5, color: 'rgba(255, 255, 255, 0.7)' }, symbol: Symbolway[index % Symbolway.length], }, - // Replicating the clean Observable tooltip + // Replicating the clean D3/Observable tooltip hovertemplate: `${volcanoName}
` + - 'Date: %{x|%b %d %Y %H:%M}
' + - 'Flight Level: %{y}' + 'Date (UTC): %{x|%b %d %Y %H:%M}
' + + 'Number of Explosions: %{y}' })); }, [apiData]); @@ -75,14 +80,14 @@ export default function ExplosionEvents({ settings }) { font: { color: 'white', size: 12 } }, type: 'date', - tickformat: '%b %d
%Y %H:%M', // Multiline ticks from Observable + tickformat: '%b %d
%Y', // D3 requested %b %d \n %Y formatting gridcolor: '#4b5563', zerolinecolor: '#4b5563', automargin: true, }, yaxis: { title: { - text: 'Flight Level', + text: 'Number of Explosions', font: { color: 'white', size: 12 } }, type: plotYAxisType, @@ -126,12 +131,12 @@ export default function ExplosionEvents({ settings }) { if (plotTraces.length === 0) return ( - No flight level data available. + No data available for current filter. ); return ( - + state.updateWidgetSettings); // 1. Convert the saved string into a boolean for the toggle UI - const isSymlog = currentSettings?.yAxisScale === 'symlog'; + const isSymlog = currentSettings?.yAxisScale === 'log'; const handleToggle = (details) => { // 2. Chakra v3 passes { checked: boolean } in the details object. // Convert it back to the string Plotly expects. console.log("1. Toggle Clicked! Raw details from Chakra:", details); - const newScale = details.checked ? 'symlog' : 'normal'; + const newScale = details.checked ? 'log' : 'normal'; updateSettings(widgetId, { yAxisScale: newScale }); }; @@ -30,7 +30,7 @@ export default function ExplosionEventsSettings({ widgetId, currentSettings }) { - Use Symlog Scale + Use Log Scale ); diff --git a/client/src/components/Widgets/AlertLevelWidget.jsx b/client/src/components/deprecated/AlertLevelWidget.jsx similarity index 100% rename from client/src/components/Widgets/AlertLevelWidget.jsx rename to client/src/components/deprecated/AlertLevelWidget.jsx diff --git a/client/src/components/deprecated/FirstWidgetButton.jsx b/client/src/components/deprecated/FirstWidgetButton.jsx index 6ec7295..5c19f03 100644 --- a/client/src/components/deprecated/FirstWidgetButton.jsx +++ b/client/src/components/deprecated/FirstWidgetButton.jsx @@ -1,5 +1,5 @@ import { Box, Menu, Portal } from '@chakra-ui/react' -import AlertLevel from "@/components/Widgets/AlertLevelWidget.jsx"; +import AlertLevel from "@/components/deprecated/AlertLevelWidget.jsx"; export default function FirstWidgetButton({ appendWidget }) { const triggerItem = ( diff --git a/client/src/components/Widgets/Widget.jsx b/client/src/components/deprecated/Widget.jsx similarity index 100% rename from client/src/components/Widgets/Widget.jsx rename to client/src/components/deprecated/Widget.jsx diff --git a/client/src/components/deprecated/WidgetMenu.jsx b/client/src/components/deprecated/WidgetMenu.jsx index e834a47..140af76 100644 --- a/client/src/components/deprecated/WidgetMenu.jsx +++ b/client/src/components/deprecated/WidgetMenu.jsx @@ -1,5 +1,5 @@ import { Menu, Portal } from "@chakra-ui/react"; -import AlertLevel from "../Widgets/AlertLevelWidget.jsx"; +import AlertLevel from "./AlertLevelWidget.jsx"; export default function WidgetMenu({appendWidget, triggerItem, positioning}) { return ( diff --git a/client/src/constants/widgetRegistry.jsx b/client/src/constants/widgetRegistry.jsx index 7da17e0..3e763da 100644 --- a/client/src/constants/widgetRegistry.jsx +++ b/client/src/constants/widgetRegistry.jsx @@ -83,5 +83,6 @@ export const WIDGET_REGISTRY = { allowedSizes: { medium: { w: 6, h: 12 } } - } + }, + }; \ No newline at end of file diff --git a/client/src/pages/home/tabs/MyDashboard.jsx b/client/src/pages/home/tabs/MyDashboard.jsx index b7b3398..05f2c24 100644 --- a/client/src/pages/home/tabs/MyDashboard.jsx +++ b/client/src/pages/home/tabs/MyDashboard.jsx @@ -3,7 +3,7 @@ import { X, MoreVertical } from "lucide-react"; import { Responsive, WidthProvider } from "react-grid-layout"; import { useDashboardStore } from "@/store/useDashboardStore.jsx"; import { Suspense, useEffect, useRef } from 'react'; - +import { useColorModeValue } from "@/components/ui/color-mode"; // 1. Import database messenger import useAuthStore from "@/store/authStore"; @@ -14,6 +14,12 @@ import { WIDGET_REGISTRY } from '@/constants/widgetRegistry.jsx'; const ResponsiveGridLayout = WidthProvider(Responsive); export default function MyDashboard() { + // 🌗 Let's adjust for our light and dark mode + const frameBg = useColorModeValue("gray.100", "gray.800"); + const titleColor = useColorModeValue("gray.800", "gray.100"); + const iconColor = useColorModeValue("gray.600", "gray.400"); + const iconHoverBg = useColorModeValue("gray.100", "gray.700"); + // ☁️ Database Connection const { user } = useAuthStore(); @@ -67,7 +73,7 @@ export default function MyDashboard() { return ( // The "Frame" that holds both the Title and the Chart - + {/* THE TITLE BAR */} - + {registryEntry.name} @@ -166,7 +172,7 @@ export default function MyDashboard() { right={2} size="xs" bg="white" - color="gray.400" + color={iconColor} border="1px solid" borderColor="gray.200" _hover={{ bg: "red.50", color: "red.500", borderColor: "red.200" }}