update: widget settings ui is now updated for RS, AL changes, Comm Coor, and IVANS widgets. it contains sections and a unified color scheme in the themes file in the popover recipe

This commit is contained in:
2026-11-10 08:31:12 -08:00
parent 5798b90ab7
commit b7a5ae2ae2
6 changed files with 257 additions and 166 deletions
@@ -112,16 +112,16 @@ export default function IvansAlerts({ settings, widgetID }) {
{/* This box needs to be at h="100%" for the pdf toolbar to appear */}
<Box w="100%" h="100%" p={1} borderBottomRadius="lg" bg="widgetItemExpandedBg">
<Flex direction="column" gap={2} borderRadius="lg" p={2} align="start">
<Text w="fit" fontSize="sm" color="text" p={1} bg="widgetBadgeBg" borderRadius="md">Preparer: {item?.preparer}</Text>
<Text w="fit" fontSize="sm" color="text" p={1} bg="widgetInnerBadgeBg" borderRadius="md">Preparer: {item?.preparer}</Text>
<Text w="100%" h="100%" fontSize="sm" color="text" textAlign="left" whiteSpace="pre-line">{item?.summary}</Text>
</Flex>
{item?.files?.map((file, index) => {
return (
<Box w="100%" h="100%" key={index}>
<Box w="100%" h="100%" key={index} >
<Flex direction="row" w="100%">
<Text w="100%" p={1} fontWeight="semibold" bg="widgetBadgeBg" borderLeftRadius="lg" fontSize="sm" color="text">File: </Text>
<Text w="100%" p={1} fontWeight="semibold" bg="widgetInnerBadgeBg" borderLeftRadius="lg" fontSize="sm" color="text">File: </Text>
<a href={`${file?.url}#view=FitV&toolbar=0`} target="_blank" rel="noopener noreferrer">
<Text truncate w="100%" p={1} bg="widgetBadgeBg" borderRightRadius="lg" fontSize="sm" color="text">
<Text truncate w="100%" p={1} bg="widgetInnerBadgeBg" borderRightRadius="lg" fontSize="sm" color="text">
{file?.name}
</Text>
</a>
@@ -131,12 +131,12 @@ export default function IvansAlerts({ settings, widgetID }) {
type="application/pdf"
style={{ width: '100%', height: '100%', display: 'block' }}
>
<Flex direction="column" w="100%" h="100%" align="center" p={4} color="widgetTextMuted" bg="widgetBadgeBg" borderRadius="md">
<Flex direction="column" w="100%" h="100%" align="center" p={4} mt={1} color="widgetTextMuted" bg="widgetInnerBadgeBg" borderRadius="lg">
<Text mb={2} fontSize="xs" color="red.300">
Your browser cannot display this PDF directly.
</Text>
<a href={file?.url} target="_blank" bg="widgetBadgeBg" rel="noopener noreferrer">
<Text fontSize="xs" bg="widgetInnerBadgeBg" borderRadius="md" p={1}>Download PDF Instead</Text>
<Text fontSize="xs" bg="widgetBadgeBg" borderRadius="md" p={1}>Download PDF Instead</Text>
</a>
</Flex>
</object>
@@ -13,20 +13,22 @@ import {
useFilter,
useListCollection,
Wrap,
Badge
Badge, Separator, HStack, useSlotRecipe
} from "@chakra-ui/react";
import { useDashboardStore } from "@/store/useDashboardStore.jsx";
import { useState, useMemo } from "react";
export default function AlertChangeSettings({ widgetId, currentSettings }) {
// STYLING
const popoverRecipe = useSlotRecipe({ key: "glassPopover" });
const popoverStyles = popoverRecipe();
// STATE MANAGEMENT
const updateSettings = useDashboardStore(
(state) => state.updateWidgetSettings,
);
const [startError, setStartError] = useState(null);
const [endError, setEndError] = useState(null);
console.log("currentSettings:", currentSettings);
const [selectedVolcanoes, setSelectedVolcanoes] = useState([]);
const { startsWith } = useFilter({ sensitivity: "base" });
@@ -36,6 +38,7 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
limit: 10,
});
// FUNCTIONS
const handleValueChange = (details) => {
setSelectedVolcanoes(details.value)
}
@@ -45,14 +48,11 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
<Fieldset.Root>
<Fieldset.Content>
{/* SELECTING DATE RANGE */}
<Flex direction="column" w="100%" h="100%" justify="center" gap={2}>
<Flex direction="column">
<Text w="100%" fontWeight="bold">
Date Range Selection
</Text>
<hr /> {/*line seperator*/}
</Flex>
<HStack>
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
<Flex direction="column" w="100%" h="100%" justify="center" gap={2} pr={1}>
{/* start date */}
<Field.Root invalid={!!startError}>
<Flex
@@ -68,8 +68,7 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
<Flex direction="column" w="100%">
<Input
type="date"
w="100%"
borderRadius="lg"
css={popoverStyles.date}
value={currentSettings?.startDate || ""}
onChange={(e) => {
const value = e.target.value;
@@ -109,8 +108,8 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
<Flex direction="column" w="100%">
<Input
type="date"
w="100%"
borderRadius="lg"
css={popoverStyles.date}
value={currentSettings?.endDate || ""}
onChange={(e) => {
const value = e.target.value;
@@ -137,18 +136,15 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
{/* FILTERS */}
<CheckboxGroup w="100%">
<Flex direction="column" w="100%" gap={2}>
<Flex direction="column" w="100%">
<Text w="fit" fontWeight="bold">
Filters
</Text>
<hr /> {/*line seperator*/}
</Flex>
<HStack>
<Text flexShrink="0" fontWeight="semibold">Filters</Text>
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
{/* level increases */}
<CheckboxCard.Root
size="sm"
variant="surface"
borderRadius="lg"
css={popoverStyles.checkboxcard}
defaultChecked={currentSettings?.filters?.levelIncreases}
onCheckedChange={(e) => {
updateSettings(widgetId, {
@@ -167,15 +163,14 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
Level Increases
</CheckboxCard.Label>
</CheckboxCard.Content>
<CheckboxCard.Indicator />
<CheckboxCard.Indicator css={popoverStyles.checkbox} />
</CheckboxCard.Control>
</CheckboxCard.Root>
{/* level decreases */}
<CheckboxCard.Root
size="sm"
variant="surface"
borderRadius="lg"
css={popoverStyles.checkboxcard}
defaultChecked={currentSettings?.filters?.levelDecreases}
onCheckedChange={(e) => {
updateSettings(widgetId, {
@@ -194,15 +189,14 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
Level Decreases
</CheckboxCard.Label>
</CheckboxCard.Content>
<CheckboxCard.Indicator />
<CheckboxCard.Indicator css={popoverStyles.checkbox} />
</CheckboxCard.Control>
</CheckboxCard.Root>
{/* elevated levels */}
<CheckboxCard.Root
size="sm"
variant="surface"
borderRadius="lg"
css={popoverStyles.checkboxcard}
defaultChecked={currentSettings?.filters?.elevatedLevels}
onCheckedChange={(e) => {
updateSettings(widgetId, {
@@ -221,7 +215,7 @@ export default function AlertChangeSettings({ widgetId, currentSettings }) {
Only Elevated Levels
</CheckboxCard.Label>
</CheckboxCard.Content>
<CheckboxCard.Indicator />
<CheckboxCard.Indicator css={popoverStyles.checkbox}/>
</CheckboxCard.Control>
</CheckboxCard.Root>
</Flex>
@@ -1,12 +1,18 @@
import {Button, Field, Flex, Input, Switch, Text, Fieldset, Separator, HStack} from "@chakra-ui/react";
import {Button, Field, Flex, Input, Switch, Text, Fieldset, Separator, HStack, useSlotRecipe} from "@chakra-ui/react";
import {useDashboardStore} from "@/store/useDashboardStore.jsx";
import {useState} from "react";
export default function CommCoorReportSettings({ widgetId, currentSettings }) {
// STYLING
const popoverRecipe = useSlotRecipe({ key: "glassPopover" });
const popoverStyles = popoverRecipe();
// STATE MANAGEMENT
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
const [startError, setStartError] = useState(null);
const [endError, setEndError] = useState(null);
// FUNCTIONS
const handleCopyToClipboard = () => {
updateSettings(widgetId, {copyToClipboard: true});
}
@@ -19,12 +25,13 @@ export default function CommCoorReportSettings({ widgetId, currentSettings }) {
<Flex flexDirection="column" justifyContent="space-between" gap={2} overflowY="auto">
<Fieldset.Root>
<Fieldset.Content>
{/* SELECTING DATE RANGE */}
<HStack>
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
{/* SELECTING DATE RANGE */}
<Flex direction="column" w="100%" h="100%" justify="center" gap="2">
<Flex direction="column" w="100%" h="100%" justify="center" gap={2} pr={1}>
{/* start date */}
<Field.Root invalid={!!startError}>
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
<Text w="50%" align="center" justify="center" mt={2} color="text">
@@ -33,6 +40,7 @@ export default function CommCoorReportSettings({ widgetId, currentSettings }) {
<Flex direction="column" w="100%">
<Input
w="100%"
css={popoverStyles.date}
type="date"
value={currentSettings?.startDate || ""}
onChange={(e) => {
@@ -51,6 +59,7 @@ export default function CommCoorReportSettings({ widgetId, currentSettings }) {
</Flex>
</Flex>
</Field.Root>
{/* end date */}
<Field.Root invalid={!!endError}>
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
<Text w="50%" align="center" justify="center" mt={2} color="text">
@@ -59,6 +68,7 @@ export default function CommCoorReportSettings({ widgetId, currentSettings }) {
<Flex direction="column" w="100%">
<Input
w="100%"
css={popoverStyles.date}
type="date"
value={currentSettings?.endDate || ""}
onChange={(e) => {
@@ -85,9 +95,9 @@ export default function CommCoorReportSettings({ widgetId, currentSettings }) {
</HStack>
<Flex direction="column" w="100%" h="100%" justify="center" gap={2}>
{/* COPY TO CLIPBOARD */}
<Button w="100%" size="xs" borderRadius="lg" variant="subtle" onClick={handleCopyToClipboard}>Copy Report</Button>
<Button css={popoverStyles.button} onClick={handleCopyToClipboard}>Copy Report</Button>
{/* DOWNLOAD REPORT */}
<Button w="100%" size="xs" borderRadius="lg" variant="subtle" onClick={handleDownloadReport}>Download Report</Button>
<Button css={popoverStyles.button} onClick={handleDownloadReport}>Download Report</Button>
</Flex>
</Fieldset.Content>
</Fieldset.Root>
@@ -15,14 +15,16 @@ import {useDashboardStore} from "../../../store/useDashboardStore.jsx";
import {useState} from "react";
export default function IvansAlertsSettings({ widgetId, currentSettings }) {
// STYLING
const popoverRecipe = useSlotRecipe({ key: "glassPopover" });
const popoverStyles = popoverRecipe();
// STATE MANAGEMENT
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
const [startError, setStartError] = useState(null);
const [endError, setEndError] = useState(null);
const popoverRecipe = useSlotRecipe({ key: "glassPopover" });
const popoverStyles = popoverRecipe();
// FUNCTIONS
const handleCopyToClipboard = () => {
updateSettings(widgetId, {copyToClipboard: true});
}
@@ -40,13 +42,11 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
<Fieldset.Root>
<Fieldset.Content>
{/* SELECTING DATE RANGE */}
<Flex direction="column" w="100%" h="100%" justify="center" gap={2}>
<HStack>
<Separator flex="1" size="md"/> {/*line seperator*/}
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
<Separator flex="1" size="md"/> {/*line seperator*/}
<HStack>
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
<Flex direction="column" w="100%" h="100%" justify="center" gap={2} pr={1}>
{/* start date */}
<Field.Root invalid={!!startError}>
<Flex
@@ -64,7 +64,7 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
type="date"
w="100%"
borderRadius="lg"
bg="widgetBadgeBg"
css={popoverStyles.date}
value={currentSettings?.startDate || ""}
onChange={(e) => {
const value = e.target.value;
@@ -106,7 +106,7 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
type="date"
w="100%"
borderRadius="lg"
bg="widgetBadgeBg"
css={popoverStyles.date}
value={currentSettings?.endDate || ""}
onChange={(e) => {
const value = e.target.value;
@@ -132,20 +132,18 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
{/* SORTS */}
<HStack>
<Separator flex="1" size="md"/> {/*line seperator*/}
<Text flexShrink="0" fontWeight="semibold">Sorts</Text>
<Separator flex="1" size="md"/> {/*line seperator*/}
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
{/* time sort */}
<Switch.Root
checked={currentSettings?.activeSorts?.timeSort === "asc"}
onCheckedChange={handleTimeSort}
colorPalette="orange"
>
<Switch.HiddenInput />
<Switch.Control>
<Switch.Thumb />
<Switch.Control css={popoverStyles.switch}>
<Switch.Thumb bg="white"/>
</Switch.Control>
<Switch.Label fontWeight={400}>Oldest to Newest</Switch.Label>
</Switch.Root>
@@ -154,26 +152,23 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
<Switch.Root
checked={currentSettings?.activeSorts?.volcanoSort}
onCheckedChange={handleVolcanoSort}
colorPalette="orange"
>
<Switch.HiddenInput />
<Switch.Control>
<Switch.Thumb />
<Switch.Control css={popoverStyles.switch}>
<Switch.Thumb bg="white" />
</Switch.Control>
<Switch.Label fontWeight={400}>Alphabetically by Volcano</Switch.Label>
</Switch.Root>
<HStack>
<Separator flex="1" size="md"/> {/*line seperator*/}
<Text flexShrink="0" fontWeight="semibold">Filters</Text>
<Separator flex="1" size="md"/> {/*line seperator*/}
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
{/* elevated levels */}
<CheckboxCard.Root
size="sm"
variant="surface"
borderRadius="lg"
// size="sm"
// variant="surface"
css={popoverStyles.checkboxcard}
defaultChecked={currentSettings?.filters?.elevatedLevels}
@@ -194,17 +189,21 @@ export default function IvansAlertsSettings({ widgetId, currentSettings }) {
Only Elevated Levels
</CheckboxCard.Label>
</CheckboxCard.Content>
<CheckboxCard.Indicator css={popoverStyles.checkboxcard} />
<CheckboxCard.Indicator css={popoverStyles.checkbox} />
</CheckboxCard.Control>
</CheckboxCard.Root>
{/* COPY TO CLIPBOARD */}
<HStack>
<Separator flex="1" size="md"/> {/*line seperator*/}
<Text flexShrink="0" fontWeight="semibold">Tools</Text>
<Separator flex="1" size="md"/> {/*line seperator*/}
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
<Button mt={-2} colorPalette="orange" w="100%" size="xs" borderRadius="lg" variant="subtle" onClick={handleCopyToClipboard}>Copy All IVANS</Button>
<Button mt={-2} w="100%" size="xs" borderRadius="lg" variant="subtle"
css={popoverStyles.button}
onClick={handleCopyToClipboard}
>
Copy All IVANS
</Button>
</Fieldset.Content>
</Fieldset.Root>
</Flex>
@@ -1,12 +1,18 @@
import {Button, Field, Flex, Input, Switch, Text} from "@chakra-ui/react";
import {Button, Field, Flex, HStack, Input, Separator, Switch, Text, useSlotRecipe, Fieldset} from "@chakra-ui/react";
import {useDashboardStore} from "@/store/useDashboardStore.jsx";
import {useState} from "react";
export default function RemoteSensingSettings({ widgetId, currentSettings }) {
// STYLING
const popoverRecipe = useSlotRecipe({ key: "glassPopover" });
const popoverStyles = popoverRecipe();
// STATE MANAGEMENT
const updateSettings = useDashboardStore(state => state.updateWidgetSettings);
const [startError, setStartError] = useState(null);
const [endError, setEndError] = useState(null);
// FUNCTIONS
const handleCopyToClipboard = () => {
updateSettings(widgetId, {copyToClipboard: true});
}
@@ -21,88 +27,111 @@ export default function RemoteSensingSettings({ widgetId, currentSettings }) {
return (
<Flex flexDirection="column" justifyContent="space-between" gap={2} overflowY="auto">
{/* COPYING TO CLIPBOARD */}
<Button w="fit" size="xs" onClick={handleCopyToClipboard}>Copy All RS</Button>
<Fieldset.Root>
<Fieldset.Content>
{/* SELECTING DATE RANGE */}
<HStack>
<Text flexShrink="0" fontWeight="semibold">Date Range Selection</Text>
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
<Flex direction="column" w="100%" h="100%" justify="center" gap={2} pr={1}>
{/* start date */}
<Field.Root invalid={!!startError}>
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
<Text w="50%" align="center" justify="center" mt={2} color="text">
Start Date
</Text>
<Flex direction="column" w="100%">
<Input
type="date"
css={popoverStyles.date}
{/* SORTING */}
<Switch.Root
checked={currentSettings?.activeSorts?.timeSort === "asc"}
onCheckedChange={handleTimeSort}
colorPalette="blue"
>
<Switch.HiddenInput />
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Switch.Label>Sort Oldest to Newest</Switch.Label>
</Switch.Root>
<Switch.Root
checked={currentSettings?.activeSorts?.volcanoSort}
onCheckedChange={handleVolcanoSort}
colorPalette="blue"
>
<Switch.HiddenInput />
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Switch.Label>Sort by Volcano</Switch.Label>
</Switch.Root>
value={currentSettings?.startDate || ""}
onChange={(e) => {
const value = e.target.value;
updateSettings(widgetId, {...currentSettings, startDate: value});
{/* SELECTING DATE RANGE */}
<Flex direction="column" w="100%" h="100%" align="center" justify="center" gap="2">
<Field.Root invalid={!!startError}>
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
<Text w="50%" align="center" justify="center" mt={2} color="gray.700">
Start Date
</Text>
<Flex direction="column" w="100%">
<Input
w="100%"
type="date"
value={currentSettings?.startDate || ""}
onChange={(e) => {
const value = e.target.value;
updateSettings(widgetId, {...currentSettings, startDate: value});
const dateSelected = new Date(value);
const today = new Date();
today.setHours(0, 0, 0, 0);
const dateSelected = new Date(value);
const today = new Date();
today.setHours(0, 0, 0, 0);
if (value && (dateSelected > today)) setStartError("Can't Choose a Future Date");
else setStartError("");
}}
/>
{startError && <Field.ErrorText>{startError}</Field.ErrorText>}
</Flex>
</Flex>
</Field.Root>
if (value && (dateSelected > today)) setStartError("Can't Choose a Future Date");
else setStartError("");
}}
/>
{startError && <Field.ErrorText>{startError}</Field.ErrorText>}
</Flex>
{/* end date */}
<Field.Root invalid={!!endError}>
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
<Text w="50%" align="center" justify="center" mt={2} color="text">
End Date
</Text>
<Flex direction="column" w="100%">
<Input
type="date"
css={popoverStyles.date}
value={currentSettings?.endDate || ""}
onChange={(e) => {
const value = e.target.value;
updateSettings(widgetId, {...currentSettings, endDate: value});
const dateSelected = new Date(value);
const today = new Date();
today.setHours(0, 0, 0, 0);
if (value && (dateSelected > today)) setEndError("Can't Choose a Future Date");
else setEndError("");
}}
/>
{endError && <Field.ErrorText>{endError}</Field.ErrorText>}
</Flex>
</Flex>
</Field.Root>
</Flex>
</Field.Root>
<Field.Root invalid={!!endError}>
<Flex direction="row" w="100%" h="100%" align="center" justify="center">
<Text w="50%" align="center" justify="center" mt={2} color="gray.700">
End Date
</Text>
<Flex direction="column" w="100%">
<Input
w="100%"
type="date"
value={currentSettings?.endDate || ""}
onChange={(e) => {
const value = e.target.value;
updateSettings(widgetId, {...currentSettings, endDate: value});
const dateSelected = new Date(value);
const today = new Date();
today.setHours(0, 0, 0, 0);
{/* SORTING */}
<HStack>
<Text flexShrink="0" fontWeight="semibold">Sorting</Text>
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
<Switch.Root
checked={currentSettings?.activeSorts?.timeSort === "asc"}
onCheckedChange={handleTimeSort}
>
<Switch.HiddenInput />
<Switch.Control css={popoverStyles.switch}>
<Switch.Thumb bg="white" />
</Switch.Control>
<Switch.Label>Oldest to Newest</Switch.Label>
</Switch.Root>
if (value && (dateSelected > today)) setEndError("Can't Choose a Future Date");
else setEndError("");
}}
/>
{endError && <Field.ErrorText>{endError}</Field.ErrorText>}
</Flex>
</Flex>
</Field.Root>
</Flex>
<Switch.Root
checked={currentSettings?.activeSorts?.volcanoSort}
onCheckedChange={handleVolcanoSort}
colorPalette="blue"
>
<Switch.HiddenInput />
<Switch.Control css={popoverStyles.switch}>
<Switch.Thumb bg="white"/>
</Switch.Control>
<Switch.Label>By Volcano</Switch.Label>
</Switch.Root>
{/* COPYING TO CLIPBOARD */}
<HStack>
<Text flexShrink="0" fontWeight="semibold">Tools</Text>
<Separator flex="1" size="sm"/> {/*line seperator*/}
</HStack>
<Button css={popoverStyles.button} onClick={handleCopyToClipboard}>
Copy All RS
</Button>
</Fieldset.Content>
</Fieldset.Root>
</Flex>
)
}