Update widgets and added settings
This commit is contained in:
@@ -9,7 +9,6 @@ export default function AlertLevel({id, isEditable, isDelete, DeleteWidget}) {
|
||||
const [isSubmit, setIsSubmit] = useState(false);
|
||||
|
||||
const onSubmit = (data) => {
|
||||
console.log("data: ", data);
|
||||
setIsSubmit(true);
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@ import { Box, Flex, Spinner, Text } from '@chakra-ui/react';
|
||||
import Plot from 'react-plotly.js';
|
||||
import VdapApi from '../../hooks/useVdapApi.js'; // Adjust path as needed
|
||||
|
||||
export default function VaaActivity7Day() {
|
||||
export default function VaaActivity7Day({ settings }) {
|
||||
console.log("3. Chart received settings:", settings);
|
||||
// Plotly expects 'linear' for normal axes
|
||||
const plotYAxisType = settings?.yAxisScale === 'symlog' ? 'symlog' : 'linear';
|
||||
|
||||
// Clean, single-line data fetching
|
||||
const { data: apiData, isLoading, error } = VdapApi('/api/v2/comm_coor_vaa');
|
||||
|
||||
@@ -59,7 +63,7 @@ export default function VaaActivity7Day() {
|
||||
paper_bgcolor: 'transparent', // Let Chakra UI background show through
|
||||
plot_bgcolor: 'transparent',
|
||||
font: { color: '#d1d5db' }, // gray.300
|
||||
margin: { t: 20, r: 20, l: 20, b: 20 },
|
||||
margin: { t: 40, r: 20, l: 20, b: 20 },
|
||||
// title: {
|
||||
// text: '7 Day Consolidated Flight Levels',
|
||||
// font: { size: 16, color: 'white' },
|
||||
@@ -81,6 +85,7 @@ export default function VaaActivity7Day() {
|
||||
text: 'Flight Level',
|
||||
font: { color: 'white', size: 12 }
|
||||
},
|
||||
type: plotYAxisType,
|
||||
gridcolor: '#4b5563',
|
||||
zerolinecolor: '#ffffff',
|
||||
automargin: true,
|
||||
@@ -105,7 +110,7 @@ export default function VaaActivity7Day() {
|
||||
}
|
||||
],
|
||||
};
|
||||
}, [apiData]);
|
||||
}, [apiData, plotYAxisType]);
|
||||
|
||||
if (isLoading) return (
|
||||
<Flex w="100%" h="100%" bg="gray.800" borderRadius="md" align="center" justify="center">
|
||||
@@ -128,6 +133,7 @@ export default function VaaActivity7Day() {
|
||||
return (
|
||||
<Box height="100%" width="100%" bg="gray.800" borderRadius="md" p={2} overflow="hidden">
|
||||
<Plot
|
||||
key={plotYAxisType}
|
||||
data={plotTraces}
|
||||
layout={layout}
|
||||
useResizeHandler={true} // Essential for dashboard grid resizing!
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Box, Text, Switch } from "@chakra-ui/react";
|
||||
import { useDashboardStore } from "../../../store/useDashboardStore.jsx";
|
||||
|
||||
export default function VaaActivitySettings({ widgetId, currentSettings }) {
|
||||
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
|
||||
|
||||
// 1. Convert the saved string into a boolean for the toggle UI
|
||||
const isSymlog = currentSettings?.yAxisScale === 'symlog';
|
||||
|
||||
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';
|
||||
|
||||
updateSettings(widgetId, { yAxisScale: newScale });
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Text fontWeight="bold" mb={3} fontSize="sm">Y-Axis Settings</Text>
|
||||
|
||||
<Switch.Root
|
||||
checked={isSymlog}
|
||||
onCheckedChange={handleToggle}
|
||||
colorPalette="blue"
|
||||
>
|
||||
<Switch.HiddenInput />
|
||||
<Switch.Control>
|
||||
<Switch.Thumb />
|
||||
</Switch.Control>
|
||||
<Switch.Label>Use Symlog Scale</Switch.Label>
|
||||
</Switch.Root>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -13,6 +13,15 @@ export const WIDGET_REGISTRY = {
|
||||
category: "Aviation",
|
||||
description: "Displays 7-day flight level timelines across multiple volcanoes.",
|
||||
component: lazy(() => import('../components/widgets/VaaActivity7Day')),
|
||||
|
||||
// The specific settings UI for this widget
|
||||
settingsComponent: lazy(() => import('../components/widgets/settings/VaaActivitySettings')),
|
||||
|
||||
// The baseline data every new VAA widget starts with
|
||||
defaultSettings: {
|
||||
yAxisScale: 'normal' // Options: 'normal' | 'symlog'
|
||||
},
|
||||
|
||||
allowedSizes: {
|
||||
xlarge: { w: 12, h: 12 },
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Box, Text, Flex, IconButton, Spinner } from "@chakra-ui/react";
|
||||
import { X } from "lucide-react";
|
||||
import { Box, Text, Flex, IconButton, Spinner, Popover } from "@chakra-ui/react";
|
||||
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';
|
||||
@@ -62,30 +62,60 @@ export default function MyDashboard() {
|
||||
if (registryEntry && registryEntry.component) {
|
||||
const Component = registryEntry.component;
|
||||
|
||||
// 1. Check if this widget type has a settings component registered
|
||||
const SettingsUI = registryEntry.settingsComponent;
|
||||
|
||||
return (
|
||||
// The "Frame" that holds both the Title and the Chart
|
||||
<Flex direction="column" height="100%" width="100%" bg="gray.800">
|
||||
|
||||
{/* 1. THE TITLE BAR (Dynamically pulled from registry!) */}
|
||||
{/* THE TITLE BAR */}
|
||||
<Flex
|
||||
justify="space-between"
|
||||
align="center"
|
||||
px={3}
|
||||
py={2}
|
||||
// borderBottom="1px solid"
|
||||
// borderColor="gray.700"
|
||||
>
|
||||
<Text color="gray.100" fontWeight="semibold" fontSize="md" isTruncated>
|
||||
{registryEntry.name}
|
||||
</Text>
|
||||
|
||||
{/* (Optional) This is exactly where the ellipsis/settings icon will go later! */}
|
||||
{/* THE SETTINGS ELLIPSIS */}
|
||||
{SettingsUI ? (
|
||||
<Popover.Root positioning={{ placement: "bottom-end" }}>
|
||||
<Popover.Trigger asChild>
|
||||
<IconButton
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
color="gray.400"
|
||||
_hover={{ color: "white", bg: "gray.700" }}
|
||||
aria-label="Widget Settings"
|
||||
>
|
||||
<MoreVertical size={16} />
|
||||
</IconButton>
|
||||
</Popover.Trigger>
|
||||
|
||||
{/* NEW: The Positioner lifts the content out of the Flexbox flow */}
|
||||
<Popover.Positioner zIndex={10}>
|
||||
<Popover.Content bg="gray.50" p={4} boxShadow="xl" borderRadius="md">
|
||||
<Suspense fallback={<Spinner size="sm" />}>
|
||||
<SettingsUI
|
||||
widgetId={widget.id}
|
||||
currentSettings={widget.settings || {}}
|
||||
/>
|
||||
</Suspense>
|
||||
</Popover.Content>
|
||||
</Popover.Positioner>
|
||||
</Popover.Root>
|
||||
) : (
|
||||
<Box w="20px" h="20px" />
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{/* 2. THE CHART CANVAS */}
|
||||
{/* THE CHART CANVAS */}
|
||||
<Box flex="1" overflow="hidden" position="relative" p={1}>
|
||||
<Component />
|
||||
{/* Pass the settings object into the actual chart component */}
|
||||
<Component settings={widget.settings || {}} />
|
||||
</Box>
|
||||
|
||||
</Flex>
|
||||
|
||||
@@ -43,6 +43,17 @@ export const useDashboardStore = create((set, get) => ({
|
||||
}
|
||||
},
|
||||
|
||||
updateWidgetSettings: (id, newSettings) => set((state) => {
|
||||
console.log("2. Zustand updating widget:", id, "with:", newSettings);
|
||||
return {
|
||||
widgets: state.widgets.map(widget =>
|
||||
widget.id === id
|
||||
? { ...widget, settings: { ...widget.settings, ...newSettings } }
|
||||
: widget
|
||||
)
|
||||
};
|
||||
}),
|
||||
|
||||
addWidget: (widgetId, sizeKey) => {
|
||||
const registryEntry = WIDGET_REGISTRY[widgetId];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user