Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
effdf8ae02 | ||
|
|
1ef77c02ff | ||
|
|
b8aa67f64c | ||
|
|
79f7e9661c |
@@ -8,6 +8,10 @@ export default function LlmAlChangesQuadPlot(props) {
|
|||||||
let tn_percent = 0;
|
let tn_percent = 0;
|
||||||
let fp_percent = 0;
|
let fp_percent = 0;
|
||||||
let fn_percent = 0;
|
let fn_percent = 0;
|
||||||
|
let jf_percent = 0;
|
||||||
|
let error_count = 0;
|
||||||
|
let no_dvar_data_count = 0;
|
||||||
|
|
||||||
|
|
||||||
// Clean, single-line data fetching
|
// Clean, single-line data fetching
|
||||||
const { data: apiData, isLoading, error } = VdapApi('/api/v2/llm_quadrant_plot');
|
const { data: apiData, isLoading, error } = VdapApi('/api/v2/llm_quadrant_plot');
|
||||||
@@ -32,32 +36,34 @@ export default function LlmAlChangesQuadPlot(props) {
|
|||||||
|
|
||||||
if (apiData) {
|
if (apiData) {
|
||||||
console.log(apiData);
|
console.log(apiData);
|
||||||
tp_percent = ((apiData[0]['tp_count']/apiData[0]['tot_count'])*100).toFixed(2);
|
tp_percent = ((apiData[0]['tp_count']/apiData[0]['vr_count'])*100).toFixed(2);
|
||||||
tn_percent = ((apiData[0]['tn_count']/apiData[0]['tot_count'])*100).toFixed(2);
|
tn_percent = ((apiData[0]['tn_count']/apiData[0]['vr_count'])*100).toFixed(2);
|
||||||
fp_percent = ((apiData[0]['fp_count']/apiData[0]['tot_count'])*100).toFixed(2);
|
fp_percent = ((apiData[0]['fp_count']/apiData[0]['vr_count'])*100).toFixed(2);
|
||||||
fn_percent = ((apiData[0]['fn_count']/apiData[0]['tot_count'])*100).toFixed(2);
|
fn_percent = ((apiData[0]['fn_count']/apiData[0]['vr_count'])*100).toFixed(2);
|
||||||
|
jf_percent = ((apiData[0]['jf_count']/apiData[0]['vr_count'])*100).toFixed(2);
|
||||||
|
error_count = apiData[0]['e_count'];
|
||||||
|
no_dvar_data_count = apiData[0]['ndd_count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" w="100%" h="100%" borderRadius="lg">
|
<Flex direction="column" w="100%" h="100%" bg="gray.800" borderRadius="lg" gap={1} p={1}>
|
||||||
<Flex direction="row" w="100%" bg="gray.800" borderTopRadius="lg" justifyItems="center" alignItems="start" p={2} pb={0} pl={4} justifyContent="end">
|
<Flex direction="column" align="end" justify="center" color="white" gap={1}>
|
||||||
{/*<Text fontWeight="bold" fontSize="lg" color="white">Alert Level Changes Quad Plot</Text>*/}
|
<Text w="fit" bg="cyan.200/5" borderRadius="sm" p={1}>All Time</Text>
|
||||||
<Text bg="cyan.200/5" borderRadius="sm" padding="1" fontWeight="normal" fontSize="sm" color="white">All time</Text>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex direction="column" w="100%" h="100%" bg="gray.800" gap="2" padding="2" borderBottomRadius="lg">
|
<Flex direction="column" w="100%" h="100%" gap="2" borderBottomRadius="lg">
|
||||||
<Flex direction="row" w="100%" h="100%" gap="2">
|
<Flex direction="row" w="100%" h="100%" gap="2">
|
||||||
<Center bg={`blue.200/${tp_percent % 50}`} w="100%" h="100%" borderRadius="lg" color="white" fontSize="sm" fontWeight="bold">
|
<Center bg={`blue.200/${tp_percent % 50}`} w="100%" h="100%" borderRadius="lg" color="white" fontSize="sm" fontWeight="bold">
|
||||||
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
||||||
<Text>True Positive</Text>
|
<Text>True Positive</Text>
|
||||||
<Text fontSize="lg"> {tp_percent}% </Text>
|
<Text fontSize="lg"> {tp_percent}% </Text>
|
||||||
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['tp_count']}/{apiData[0]['tot_count']} </Text>
|
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['tp_count']}/{apiData[0]['vr_count']} </Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Center>
|
</Center>
|
||||||
<Center bg={`blue.200/${tn_percent % 50}`} w="100%" h="100%" borderRadius="lg" color="white" fontSize="sm" fontWeight="bold">
|
<Center bg={`blue.200/${tn_percent % 50}`} w="100%" h="100%" borderRadius="lg" color="white" fontSize="sm" fontWeight="bold">
|
||||||
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
||||||
<Text>True Negative</Text>
|
<Text>True Negative</Text>
|
||||||
<Text fontSize="lg"> {tn_percent}% </Text>
|
<Text fontSize="lg"> {tn_percent}% </Text>
|
||||||
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['tn_count']}/{apiData[0]['tot_count']} </Text>
|
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['tn_count']}/{apiData[0]['vr_count']} </Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Center>
|
</Center>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -66,17 +72,30 @@ export default function LlmAlChangesQuadPlot(props) {
|
|||||||
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
||||||
<Text>False Positive</Text>
|
<Text>False Positive</Text>
|
||||||
<Text fontSize="lg"> {fp_percent}% </Text>
|
<Text fontSize="lg"> {fp_percent}% </Text>
|
||||||
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['fp_count']}/{apiData[0]['tot_count']} </Text>
|
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['fp_count']}/{apiData[0]['vr_count']} </Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Center>
|
</Center>
|
||||||
<Center bg={`blue.200/${fn_percent % 50}`} w="100%" h="100%" borderRadius="lg" color="white" fontSize="sm" fontWeight="bold">
|
<Center bg={`blue.200/${fn_percent % 50}`} w="100%" h="100%" borderRadius="lg" color="white" fontSize="sm" fontWeight="bold">
|
||||||
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
||||||
<Text>False Negative</Text>
|
<Text>False Negative</Text>
|
||||||
<Text fontSize="lg"> {fn_percent}% </Text>
|
<Text fontSize="lg"> {fn_percent}% </Text>
|
||||||
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['fn_count']}/{apiData[0]['tot_count']} </Text>
|
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['fn_count']}/{apiData[0]['vr_count']} </Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Center>
|
</Center>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<Flex direction="row" w="100%" h="100%" gap="2">
|
||||||
|
<Center bg={`blue.200/${jf_percent % 50}`} w="100%" h="100%" borderRadius="lg" color="white" fontSize="sm" fontWeight="bold">
|
||||||
|
<Flex direction="column" w="100%" h="100%" justifyContent="center" alignItems="center">
|
||||||
|
<Text>Just False</Text>
|
||||||
|
<Text fontSize="lg"> {jf_percent}% </Text>
|
||||||
|
<Text color="gray.400" fontSize="xs" fontWeight="normal"> {apiData[0]['jf_count']}/{apiData[0]['vr_count']} </Text>
|
||||||
|
</Flex>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction="row" w="100%" justify="space-between" gap={1} color="white">
|
||||||
|
<Text w="fit" bg="blue.200/5" borderRadius="sm" p={1}>Errors: {error_count}</Text>
|
||||||
|
<Text w="fit" bg="blue.200/5" borderRadius="sm" p={1}>No DVAR Data: {no_dvar_data_count}</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,23 +4,21 @@ import {useDashboardStore} from "@/store/useDashboardStore.jsx";
|
|||||||
export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
export default function IvansAlertsSettings({ widgetId, currentSettings }) {
|
||||||
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
|
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
|
||||||
|
|
||||||
console.log("currentSettings:", currentSettings);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex flexDirection="column" justifyContent="space-between" align="center" gap={2} pb={2}>
|
<Flex flexDirection="column" justifyContent="space-between" gap={2} pb={2}>
|
||||||
{/* SLIDER DATE RANGE SELECTION */}
|
{/* SLIDER DATE RANGE SELECTION */}
|
||||||
<Slider.Root
|
<Slider.Root
|
||||||
w="90%" h="100%"
|
width="80%" h="100%"
|
||||||
min={1} max={14}
|
min={1} max={14}
|
||||||
defaultValue={[1]}
|
defaultValue={[7]}
|
||||||
step={1}
|
step={1}
|
||||||
onValueChangeEnd={(e) => {
|
onValueChangeEnd={(e) => {
|
||||||
console.log("change end", e);
|
|
||||||
const day = new Date(Date.now() - (e.value[0])*86400000).toLocaleDateString('en-CA');
|
const day = new Date(Date.now() - (e.value[0])*86400000).toLocaleDateString('en-CA');
|
||||||
|
console.log("new start: ", day);
|
||||||
updateSettings(widgetId, {...currentSettings, startDate: day});
|
updateSettings(widgetId, {...currentSettings, startDate: day});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Slider.Label>{currentSettings?.startDate} to {currentSettings?.endDate}</Slider.Label>
|
<Slider.Label>{currentSettings?.endDate} to {currentSettings?.startDate}</Slider.Label>
|
||||||
<Slider.Control>
|
<Slider.Control>
|
||||||
<Slider.Track>
|
<Slider.Track>
|
||||||
<Slider.Range />
|
<Slider.Range />
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "IVANS",
|
name: "IVANS",
|
||||||
category: "Communications",
|
category: "Communications",
|
||||||
description: "Feed of recent IVANS reports and reviewer statuses.",
|
description: "Feed of recent IVANS reports and reviewer statuses.",
|
||||||
component: lazy(() => import('../components/Widgets/IvansAlerts.jsx')),
|
component: lazy(() => import('../components/widgets/IvansAlerts.jsx')),
|
||||||
settingsComponent: lazy(() => import('../components/Widgets/settings/IvansAlertsSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/IvansAlertsSettings.jsx')),
|
||||||
defaultSettings: {
|
defaultSettings: {
|
||||||
startDate: getStartDate(),
|
startDate: getStartDate(),
|
||||||
endDate: getEndDate(),
|
endDate: getEndDate(),
|
||||||
@@ -72,8 +72,8 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "Remote Sensing",
|
name: "Remote Sensing",
|
||||||
category: "Remote Sensing",
|
category: "Remote Sensing",
|
||||||
description: "Feed of recent remote sensing reports.",
|
description: "Feed of recent remote sensing reports.",
|
||||||
component: lazy(() => import('../components/Widgets/RemoteSensing.jsx')),
|
component: lazy(() => import('../components/widgets/RemoteSensing.jsx')),
|
||||||
settingsComponent: lazy(() => import('../components/Widgets/Settings/RemoteSensingSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/RemoteSensingSettings.jsx')),
|
||||||
defaultSettings: {
|
defaultSettings: {
|
||||||
startDate: getStartDate(),
|
startDate: getStartDate(),
|
||||||
endDate: getEndDate(),
|
endDate: getEndDate(),
|
||||||
@@ -94,8 +94,8 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "Alert Level Changes",
|
name: "Alert Level Changes",
|
||||||
category: "Daily Alerts",
|
category: "Daily Alerts",
|
||||||
description: "List of 7-day alert level changes with trend arrows.",
|
description: "List of 7-day alert level changes with trend arrows.",
|
||||||
component: lazy(() => import('../components/Widgets/AlertChanges.jsx')),
|
component: lazy(() => import('../components/widgets/AlertChanges.jsx')),
|
||||||
settingsComponent: lazy(() => import('../components/Widgets/settings/AlertChangeSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/AlertChangeSettings.jsx')),
|
||||||
defaultSettings: {
|
defaultSettings: {
|
||||||
startDate: getStartDate(),
|
startDate: getStartDate(),
|
||||||
endDate: getEndDate(),
|
endDate: getEndDate(),
|
||||||
@@ -111,7 +111,7 @@ export const WIDGET_REGISTRY = {
|
|||||||
category: "Daily Volcanic Activity",
|
category: "Daily Volcanic Activity",
|
||||||
description: "List of explosion events over a specified time period.",
|
description: "List of explosion events over a specified time period.",
|
||||||
|
|
||||||
component: lazy(() => import('../components/Widgets/ExplosionEvents.jsx')),
|
component: lazy(() => import('../components/widgets/ExplosionEvents.jsx')),
|
||||||
|
|
||||||
// The specific settings UI for this widget
|
// The specific settings UI for this widget
|
||||||
settingsComponent: lazy(() => import('../components/widgets/settings/ExplosionEventsSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/ExplosionEventsSettings.jsx')),
|
||||||
@@ -131,8 +131,8 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "Plume Events",
|
name: "Plume Events",
|
||||||
category: "Daily Volcanic Activity",
|
category: "Daily Volcanic Activity",
|
||||||
description: "Plot of explosion heights over a weeks time.",
|
description: "Plot of explosion heights over a weeks time.",
|
||||||
component: lazy(() => import('../components/Widgets/PlumeEvents.jsx')),
|
component: lazy(() => import('../components/widgets/PlumeEvents.jsx')),
|
||||||
settingsComponent: lazy(() => import('../components/Widgets/settings/PlumeEventsSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/PlumeEventsSettings.jsx')),
|
||||||
defaultSettings: {
|
defaultSettings: {
|
||||||
startDate: getStartDate(),
|
startDate: getStartDate(),
|
||||||
endDate: getEndDate(),
|
endDate: getEndDate(),
|
||||||
@@ -146,8 +146,8 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "Seismic Events",
|
name: "Seismic Events",
|
||||||
category: "Daily Volcanic Activity",
|
category: "Daily Volcanic Activity",
|
||||||
description: "Plot of number of seismic events over a weeks time.",
|
description: "Plot of number of seismic events over a weeks time.",
|
||||||
component: lazy(() => import('../components/Widgets/SeismicEvents.jsx')),
|
component: lazy(() => import('../components/widgets/SeismicEvents.jsx')),
|
||||||
settingsComponent: lazy(() => import('../components/Widgets/settings/SeismicEventsSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/SeismicEventsSettings.jsx')),
|
||||||
defaultSettings: {
|
defaultSettings: {
|
||||||
startDate: getStartDate(),
|
startDate: getStartDate(),
|
||||||
endDate: getEndDate(),
|
endDate: getEndDate(),
|
||||||
@@ -161,7 +161,7 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "Alert Level Changes Quad Plot",
|
name: "Alert Level Changes Quad Plot",
|
||||||
category: "Computer Science",
|
category: "Computer Science",
|
||||||
description: "Percentage of TP, TN, FP, and FN changes in viable alert levels.",
|
description: "Percentage of TP, TN, FP, and FN changes in viable alert levels.",
|
||||||
component: lazy(() => import('../components/Widgets/LlmAlChangesQuadPlot.jsx')),
|
component: lazy(() => import('../components/widgets/LlmAlChangesQuadPlot.jsx')),
|
||||||
allowedSizes: {
|
allowedSizes: {
|
||||||
medium: { w: 3, h: 12 }
|
medium: { w: 3, h: 12 }
|
||||||
}
|
}
|
||||||
@@ -171,8 +171,8 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "Communication Coordinator Report",
|
name: "Communication Coordinator Report",
|
||||||
category: "Daily Volcanic Activity",
|
category: "Daily Volcanic Activity",
|
||||||
description: "Generated Report",
|
description: "Generated Report",
|
||||||
component: lazy(() => import('../components/Widgets/CommCoorReport.jsx')),
|
component: lazy(() => import('../components/widgets/CommCoorReport.jsx')),
|
||||||
settingsComponent: lazy(() => import('../components/Widgets/settings/CommCoorReportSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/CommCoorReportSettings.jsx')),
|
||||||
defaultSettings: {
|
defaultSettings: {
|
||||||
copyToClipboard: false,
|
copyToClipboard: false,
|
||||||
downloadReport: false,
|
downloadReport: false,
|
||||||
@@ -188,8 +188,8 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "VAA Polygon Projections Map",
|
name: "VAA Polygon Projections Map",
|
||||||
category: "Maps",
|
category: "Maps",
|
||||||
description: "By selecting a volcano, the map will take you to it and show a polygon of the ash in 8, 12, and 18 hours",
|
description: "By selecting a volcano, the map will take you to it and show a polygon of the ash in 8, 12, and 18 hours",
|
||||||
component: lazy(() => import('../components/Widgets/VaaMap.jsx')),
|
component: lazy(() => import('../components/widgets/VaaMap.jsx')),
|
||||||
settingsComponent: lazy(() => import('../components/Widgets/settings/VaaMapSettings.jsx')),
|
settingsComponent: lazy(() => import('../components/widgets/settings/VaaMapSettings.jsx')),
|
||||||
defaultSettings: {
|
defaultSettings: {
|
||||||
position: [45.61142, -122.49630], // CVO's coordinates
|
position: [45.61142, -122.49630], // CVO's coordinates
|
||||||
startDate: getToday(),
|
startDate: getToday(),
|
||||||
@@ -209,7 +209,7 @@ export const WIDGET_REGISTRY = {
|
|||||||
name: "Travel Gantt Chart",
|
name: "Travel Gantt Chart",
|
||||||
category: "Communications",
|
category: "Communications",
|
||||||
description: "View upcoming travels in a gantt chart",
|
description: "View upcoming travels in a gantt chart",
|
||||||
component: lazy(() => import('../components/Widgets/TravelGanttChart.jsx')),
|
component: lazy(() => import('../components/widgets/TravelGanttChart.jsx')),
|
||||||
allowedSizes: {
|
allowedSizes: {
|
||||||
medium: { w: 6, h: 12 }
|
medium: { w: 6, h: 12 }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,9 @@ export default function MyDashboard() {
|
|||||||
const hasHydrated = useRef(false);
|
const hasHydrated = useRef(false);
|
||||||
|
|
||||||
// 1. Pull the global slot recipes
|
// 1. Pull the global slot recipes
|
||||||
const glassPanelRecipe = useSlotRecipe({key: "glassPanel"});
|
const recipe = useSlotRecipe({key: "glassPanel"});
|
||||||
const glassPanelStyles = glassPanelRecipe();
|
const styles = recipe({ layout: "widget" });
|
||||||
const widgetStyles = glassPanelRecipe({ layout: "widget" });
|
const popoverStyles = recipe({ layout: "popover" });
|
||||||
const widgetSettingsRecipe = useSlotRecipe({ key: "widgetSettings" });
|
|
||||||
const widgetSettingsStyles = widgetSettingsRecipe();
|
|
||||||
|
|
||||||
// 2. Populate widgets
|
// 2. Populate widgets
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -69,7 +67,7 @@ export default function MyDashboard() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box css={widgetStyles.header}>
|
<Box css={styles.header}>
|
||||||
<Text>
|
<Text>
|
||||||
{registryEntry.name}
|
{registryEntry.name}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -84,8 +82,8 @@ export default function MyDashboard() {
|
|||||||
</Popover.Trigger>
|
</Popover.Trigger>
|
||||||
|
|
||||||
{/* NEW: The Positioner lifts the content out of the Flexbox flow */}
|
{/* NEW: The Positioner lifts the content out of the Flexbox flow */}
|
||||||
<Popover.Positioner z-index="1">
|
<Popover.Positioner zIndex={1}>
|
||||||
<Popover.Content css={[widgetSettingsStyles.root, glassPanelStyles.root]}> {/*className={`${glassPanelStyles.root} ${widgetSettingsStyles.root}`}>*/}
|
<Popover.Content css={popoverStyles.root}>
|
||||||
<Suspense fallback={<Spinner size="sm"/>}>
|
<Suspense fallback={<Spinner size="sm"/>}>
|
||||||
<SettingsUI
|
<SettingsUI
|
||||||
widgetId={widget.id}
|
widgetId={widget.id}
|
||||||
@@ -98,7 +96,7 @@ export default function MyDashboard() {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box css={widgetStyles.body}>
|
<Box css={styles.body}>
|
||||||
<Component settings={widget.settings || {}} widgetID={widget.id || {}}/>
|
<Component settings={widget.settings || {}} widgetID={widget.id || {}}/>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
@@ -107,7 +105,7 @@ export default function MyDashboard() {
|
|||||||
|
|
||||||
// Fallback if someone asks for a widget that doesn't exist
|
// Fallback if someone asks for a widget that doesn't exist
|
||||||
return (
|
return (
|
||||||
<Flex css={widgetStyles.body} align="center" justify="center" direction="column">
|
<Flex css={styles.body} align="center" justify="center" direction="column">
|
||||||
<Text fontWeight="bold" color="red.400">Error</Text>
|
<Text fontWeight="bold" color="red.400">Error</Text>
|
||||||
<Text fontSize="sm" color="gray.400">Widget '{widget.type}' not found.</Text>
|
<Text fontSize="sm" color="gray.400">Widget '{widget.type}' not found.</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -131,12 +129,12 @@ export default function MyDashboard() {
|
|||||||
{widgets.map(widget => (
|
{widgets.map(widget => (
|
||||||
<Box
|
<Box
|
||||||
key={widget.id}
|
key={widget.id}
|
||||||
css={widgetStyles.root}
|
css={styles.root}
|
||||||
// Grid-specific state overrides remain inline
|
// Grid-specific state overrides remain inline
|
||||||
boxShadow={isEditing ? "outline" : widgetStyles.root.boxShadow}
|
boxShadow={isEditing ? "outline" : styles.root.boxShadow}
|
||||||
borderStyle={isEditing ? "dashed" : "solid"}
|
borderStyle={isEditing ? "dashed" : "solid"}
|
||||||
borderWidth={isEditing ? "2px" : "1px"}
|
borderWidth={isEditing ? "2px" : "1px"}
|
||||||
borderColor={isEditing ? "orange.300" : widgetStyles.root.borderColor}
|
borderColor={isEditing ? "orange.300" : styles.root.borderColor}
|
||||||
cursor={isEditing ? "grab" : "default"}
|
cursor={isEditing ? "grab" : "default"}
|
||||||
position="relative" // REQUIRED so the absolute button stays inside this box
|
position="relative" // REQUIRED so the absolute button stays inside this box
|
||||||
>
|
>
|
||||||
@@ -165,7 +163,7 @@ export default function MyDashboard() {
|
|||||||
|
|
||||||
{/* SUSPENSE BOUNDARY wrapping the render function */}
|
{/* SUSPENSE BOUNDARY wrapping the render function */}
|
||||||
<Suspense fallback={
|
<Suspense fallback={
|
||||||
<Flex css={widgetStyles.body} align="center" justify="center">
|
<Flex css={styles.body} align="center" justify="center">
|
||||||
<Spinner size="md" color="blue.400" thickness="3px"/>
|
<Spinner size="md" color="blue.400" thickness="3px"/>
|
||||||
</Flex>
|
</Flex>
|
||||||
}>
|
}>
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ const useAuthStore = create((set) => ({
|
|||||||
// Hit the new lightweight endpoint
|
// Hit the new lightweight endpoint
|
||||||
const res = await api.get('session/');
|
const res = await api.get('session/');
|
||||||
|
|
||||||
|
// 🔨 Security Fix a broken API call, Verify we actually got a user object back, not HTML fallback text
|
||||||
|
if (typeof res.data === 'string' || !res.data.username) {
|
||||||
|
throw new Error("Received invalid data format instead of user session");
|
||||||
|
}
|
||||||
|
|
||||||
// Rehydrate the store with the user's info!
|
// Rehydrate the store with the user's info!
|
||||||
set({
|
set({
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
|
|||||||
+1
-12
@@ -304,16 +304,6 @@ const homeRecipe = defineSlotRecipe({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const widgetSettingsRecipe = defineSlotRecipe({
|
|
||||||
slots: ["root"],
|
|
||||||
base: {
|
|
||||||
root: {
|
|
||||||
w: "100%",
|
|
||||||
h: "500px",
|
|
||||||
bg: "red",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// const canvasRecipe = defineRecipe({
|
// const canvasRecipe = defineRecipe({
|
||||||
// base: {
|
// base: {
|
||||||
// bg: "{transparent}",
|
// bg: "{transparent}",
|
||||||
@@ -438,7 +428,7 @@ const glassPanelRecipe = defineSlotRecipe({
|
|||||||
popover: {
|
popover: {
|
||||||
root: {
|
root: {
|
||||||
borderRadius: "2xl",
|
borderRadius: "2xl",
|
||||||
p: 2,
|
p: 0,
|
||||||
boxShadow: "xl",
|
boxShadow: "xl",
|
||||||
minW: "240px",
|
minW: "240px",
|
||||||
maxW: "60%",
|
maxW: "60%",
|
||||||
@@ -785,7 +775,6 @@ const config = defineConfig({
|
|||||||
header: headerRecipe,
|
header: headerRecipe,
|
||||||
sidebar: sidebarRecipe,
|
sidebar: sidebarRecipe,
|
||||||
// widget: widgetRecipe,
|
// widget: widgetRecipe,
|
||||||
widgetSettings: widgetSettingsRecipe,
|
|
||||||
glassPanel: glassPanelRecipe,
|
glassPanel: glassPanelRecipe,
|
||||||
home: homeRecipe,
|
home: homeRecipe,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user