3 changed files with 54 additions and 30 deletions
@@ -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>
) )
+17 -17
View File
@@ -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 }
} }
+5
View File
@@ -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,