Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fire Center Advisory Report #3850

Merged
merged 27 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
94f6583
init
brettedw Aug 3, 2024
a1897ef
fix ASA not going full width & menu bar overlap
brettedw Aug 6, 2024
eca15fc
simplify map/sidePanel sizing
brettedw Aug 6, 2024
2ed58a5
simplify layout further
brettedw Aug 6, 2024
a02f5b9
remove import
brettedw Aug 6, 2024
ad89cb4
remove combustible area viz
brettedw Aug 6, 2024
b77b644
advisory report text auto generate
brettedw Aug 6, 2024
1c2bd77
colours and status logic
brettedw Aug 6, 2024
8aafa8c
zoneStatus use var
brettedw Aug 7, 2024
8733fbf
Refactor text
brettedw Aug 7, 2024
29194bd
remove dropdown date metadata
brettedw Aug 7, 2024
a5f393a
text date change
brettedw Aug 7, 2024
f487086
Merge branch 'main' into task/auto-advisory-report
brettedw Aug 9, 2024
f553444
Merge branch 'main' into task/auto-advisory-report
brettedw Aug 12, 2024
514aaca
Merge branch 'main' into task/auto-advisory-report
brettedw Aug 12, 2024
1ec8f27
fire center advisories, zooming
brettedw Aug 13, 2024
ecda5bc
imports, remove showSummaryPanel
brettedw Aug 13, 2024
9c48b3c
fbaMap test
brettedw Aug 13, 2024
12d2e63
Merge branch 'main' into task/auto-advisory-report
brettedw Aug 13, 2024
486b6ef
BC & initial extent
brettedw Aug 13, 2024
9486ee6
report tab state names
brettedw Aug 13, 2024
cc2a1b5
make smell happy
brettedw Aug 13, 2024
d725d7b
text change
brettedw Aug 13, 2024
b25369d
tests
brettedw Aug 13, 2024
da8cf59
more tests
brettedw Aug 14, 2024
154896f
Merge branch 'main' into task/auto-advisory-report
brettedw Aug 14, 2024
4945b35
kw/m
brettedw Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions web/src/app/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ export const DARK_GREY = '#A7A7A7'
export const LIGHT_GREY = '#DADADA'
export const MEDIUM_GREY = '#B5B5B5'

export const INFO_PANEL_HEADER_BACKGORUND = '#e4e4e5'
export const INFO_PANEL_CONTENT_BACKGORUND = '#f0f0f0'
export const INFO_PANEL_HEADER_BACKGROUND = '#e4e4e5'
export const INFO_PANEL_CONTENT_BACKGROUND = '#f0f0f0'
export const TRANSPARENT_COLOUR = '#0000'

interface WeatherParams {
Expand Down
6 changes: 5 additions & 1 deletion web/src/components/FireCenterDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { TextField, Autocomplete } from '@mui/material'
import { FireCenter } from 'api/fbaAPI'
import { FireCenter, FireShape } from 'api/fbaAPI'
import { isEqual } from 'lodash'
import React from 'react'

interface FireCenterDropdownProps {
selectedFireCenter?: FireCenter
fireCenterOptions: FireCenter[]
setSelectedFireCenter: React.Dispatch<React.SetStateAction<FireCenter | undefined>>
setSelectedFireShape: React.Dispatch<React.SetStateAction<FireShape | undefined>>
setZoomSource: React.Dispatch<React.SetStateAction<'fireCenter' | 'fireShape' | undefined>>
}

const FireCenterDropdown = (props: FireCenterDropdownProps) => {
// eslint-disable-next-line
const changeHandler = (_: React.ChangeEvent<{}>, value: any | null) => {
if (!isEqual(props.selectedFireCenter, value)) {
props.setSelectedFireShape(undefined)

Check warning on line 18 in web/src/components/FireCenterDropdown.tsx

View check run for this annotation

Codecov / codecov/patch

web/src/components/FireCenterDropdown.tsx#L18

Added line #L18 was not covered by tests
props.setSelectedFireCenter(value)
props.setZoomSource('fireCenter')

Check warning on line 20 in web/src/components/FireCenterDropdown.tsx

View check run for this annotation

Codecov / codecov/patch

web/src/components/FireCenterDropdown.tsx#L20

Added line #L20 was not covered by tests
}
}

Expand Down
40 changes: 13 additions & 27 deletions web/src/features/fba/components/AdvisoryMetadata.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,31 @@
import { Autocomplete, Box, Grid, TextField, Typography } from '@mui/material'
import { Autocomplete, TextField } from '@mui/material'
import React from 'react'
import { DateTime } from 'luxon'
import { RunType } from 'features/fba/pages/FireBehaviourAdvisoryPage'
import { isNull } from 'lodash'

export interface AdvisoryMetadataProps {
testId?: string
runType: string
setRunType: React.Dispatch<React.SetStateAction<RunType>>
forDate: DateTime
issueDate: DateTime | null
}
const AdvisoryMetadata = ({ runType, setRunType, forDate, issueDate }: AdvisoryMetadataProps) => {
// eslint-disable-next-line
const AdvisoryMetadata = ({ runType, setRunType }: AdvisoryMetadataProps) => {
const changeHandler = (_: React.ChangeEvent<{}>, value: any | null) => {
if (!isNull(value)) {
setRunType(value)
}
}
return (
<Box sx={{ width: 270 }}>
<Grid container spacing={2}>
<Grid item xs>
<Autocomplete
disablePortal
disableClearable
autoComplete
size="small"
id="asa-forecast-actual-select"
options={[RunType.FORECAST, RunType.ACTUAL]}
defaultValue={runType}
onChange={changeHandler}
renderInput={params => <TextField {...params} label="Forecast or Actual" />}
/>{' '}
<Typography variant="subtitle2">is for {forDate.toISODate()}</Typography>
<Typography variant="subtitle2">
issued on {!isNull(issueDate) ? issueDate.toISO({ includeOffset: false }) : ''}
</Typography>
</Grid>
</Grid>
</Box>
<Autocomplete
disablePortal
disableClearable
autoComplete
size="small"
id="asa-forecast-actual-select"
options={[RunType.FORECAST, RunType.ACTUAL]}
defaultValue={runType}
onChange={changeHandler}
renderInput={params => <TextField {...params} label="Forecast or Actual" />}
/>
)
}

Expand Down
66 changes: 66 additions & 0 deletions web/src/features/fba/components/infoPanel/AdvisoryReport.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Box, Tabs, Tab, Grid } from '@mui/material'
import { FireCenter } from 'api/fbaAPI'
import { INFO_PANEL_CONTENT_BACKGROUND } from 'app/theme'
import AdvisoryText from 'features/fba/components/infoPanel/AdvisoryText'
import InfoAccordion from 'features/fba/components/infoPanel/InfoAccordion'
import { DateTime } from 'luxon'
import React, { useState } from 'react'

interface AdvisoryReportProps {
issueDate: DateTime | null
forDate: DateTime
advisoryThreshold: number
selectedFireCenter?: FireCenter
}

interface TabPanelProps {
children?: React.ReactNode
index: number
value: number
}

const TabPanel = ({ children, index, value }: TabPanelProps) => {
return (
<div hidden={value !== index} id={`tabpanel-${index}`} data-testid={`tabpanel-${index}`}>
{value === index && <Box paddingBottom={3}>{children}</Box>}
</div>
)
}

const AdvisoryReport = ({ issueDate, forDate, advisoryThreshold, selectedFireCenter }: AdvisoryReportProps) => {
const [tabNumber, setTabNumber] = useState(0)

const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
setTabNumber(newValue)
}

return (
<div data-testid="advisory-report">
<InfoAccordion
defaultExpanded={true}
title={'Advisory Report'}
accordionDetailBackgroundColour={INFO_PANEL_CONTENT_BACKGROUND}
>
<Grid container justifyContent="center">
<Grid item sx={{ width: '90%' }}>
<Box>
<Tabs value={tabNumber} onChange={handleTabChange}>
<Tab label="BULLETIN" />
</Tabs>
</Box>
<TabPanel value={tabNumber} index={0}>
<AdvisoryText
issueDate={issueDate}
forDate={forDate}
advisoryThreshold={advisoryThreshold}
selectedFireCenter={selectedFireCenter}
></AdvisoryText>
</TabPanel>
</Grid>
</Grid>
</InfoAccordion>
</div>
)
}

export default AdvisoryReport
132 changes: 132 additions & 0 deletions web/src/features/fba/components/infoPanel/AdvisoryText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { Box, Typography } from '@mui/material'
import { FireCenter, FireShapeAreaDetail } from 'api/fbaAPI'
import { DateTime } from 'luxon'
import React from 'react'
import { useSelector } from 'react-redux'
import { selectProvincialSummary } from 'features/fba/slices/provincialSummarySlice'
import { AdvisoryStatus } from 'utils/constants'
import { groupBy } from 'lodash'

interface AdvisoryTextProps {
issueDate: DateTime | null
forDate: DateTime
selectedFireCenter?: FireCenter
advisoryThreshold: number
}

const AdvisoryText = ({ issueDate, forDate, advisoryThreshold, selectedFireCenter }: AdvisoryTextProps) => {
const provincialSummary = useSelector(selectProvincialSummary)

const calculateStatus = (details: FireShapeAreaDetail[]): AdvisoryStatus | undefined => {
const advisoryThresholdDetail = details.find(detail => detail.threshold == 1)
const warningThresholdDetail = details.find(detail => detail.threshold == 2)
const advisoryPercentage = advisoryThresholdDetail?.elevated_hfi_percentage ?? 0
const warningPercentage = warningThresholdDetail?.elevated_hfi_percentage ?? 0

if (warningPercentage > advisoryThreshold) {
return AdvisoryStatus.WARNING
}

if (advisoryPercentage + warningPercentage > advisoryThreshold) {
return AdvisoryStatus.ADVISORY
}
}

const getZoneStatusMap = (fireZoneUnitDetails: Record<string, FireShapeAreaDetail[]>) => {
const zoneStatusMap: Record<AdvisoryStatus, string[]> = {
[AdvisoryStatus.ADVISORY]: [],
[AdvisoryStatus.WARNING]: []
}

for (const zoneUnit in fireZoneUnitDetails) {
const fireShapeAreaDetails: FireShapeAreaDetail[] = fireZoneUnitDetails[zoneUnit]
const status = calculateStatus(fireShapeAreaDetails)

if (status) {
zoneStatusMap[status].push(zoneUnit)
}
}

return zoneStatusMap
}

const renderDefaultMessage = () => {
return (
<>
{issueDate?.isValid ? (
<Typography data-testid="default-message">Please select a fire center.</Typography>
) : (
<Typography data-testid="no-data-message">No advisory data available for today.</Typography>
)}{' '}
</>
)
}

const renderAdvisoryText = () => {
const forToday = issueDate?.toISODate() === forDate.toISODate()
const displayForDate = forToday ? 'today' : forDate.toLocaleString({ month: 'short', day: 'numeric' })

const fireCenterSummary = provincialSummary[selectedFireCenter!.name]
const groupedFireZoneUnitInfos = groupBy(fireCenterSummary, 'fire_shape_name')
const zoneStatusMap = getZoneStatusMap(groupedFireZoneUnitInfos)

return (
<>
{issueDate?.isValid && (
<Typography
sx={{ whiteSpace: 'pre-wrap' }}
>{`Issued on ${issueDate?.toLocaleString(DateTime.DATE_MED)} for ${displayForDate}.\n\n`}</Typography>
)}
{zoneStatusMap[AdvisoryStatus.WARNING].length > 0 && (
<>
<Typography data-testid="advisory-message-warning">{`There is a fire behaviour ${AdvisoryStatus.WARNING} in effect in the following areas:`}</Typography>
<ul>
{zoneStatusMap[AdvisoryStatus.WARNING].map(zone => (
<li key={zone}>
<Typography>{zone}</Typography>
</li>
))}
</ul>
</>
)}
{zoneStatusMap[AdvisoryStatus.ADVISORY].length > 0 && (
<>
<Typography data-testid="advisory-message-advisory">{`There is a fire behaviour ${AdvisoryStatus.ADVISORY} in effect in the following areas:`}</Typography>
<ul>
{zoneStatusMap[AdvisoryStatus.ADVISORY].map(zone => (
<li key={zone}>
<Typography>{zone}</Typography>
</li>
))}
</ul>
</>
)}
{zoneStatusMap[AdvisoryStatus.WARNING].length === 0 && zoneStatusMap[AdvisoryStatus.ADVISORY].length === 0 && (
<Typography data-testid="no-advisory-message">
No advisories or warnings issued for the selected fire center.
</Typography>
)}
</>
)
}

return (
<div data-testid="advisory-text">
<Box
sx={{
height: 350,
maxWidth: '100%',
overflow: 'auto',
border: '1px solid #ccc',
padding: 2,
borderRadius: 1,
backgroundColor: 'white'
}}
>
{!selectedFireCenter || !issueDate?.isValid ? renderDefaultMessage() : renderAdvisoryText()}
</Box>
</div>
)
}

export default AdvisoryText
6 changes: 3 additions & 3 deletions web/src/features/fba/components/infoPanel/FireCentreInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import FireZoneUnitInfo from 'features/fba/components/infoPanel/FireZoneUnitInfo'
import { groupBy } from 'lodash'
import { FireShapeAreaDetail } from 'api/fbaAPI'
import { INFO_PANEL_CONTENT_BACKGORUND } from 'app/theme'
import { INFO_PANEL_CONTENT_BACKGROUND } from 'app/theme'

interface FireCentreInfoProps {
advisoryThreshold: number
Expand All @@ -16,7 +16,7 @@ interface FireCentreInfoProps {
}

const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
backgroundColor: INFO_PANEL_CONTENT_BACKGORUND,
backgroundColor: INFO_PANEL_CONTENT_BACKGROUND,
flexDirection: 'row-reverse',
fontWeight: 'bold',
margin: '0px',
Expand Down Expand Up @@ -47,7 +47,7 @@ const FireCenterInfo = ({
<StyledAccordionSummary expandIcon={<ExpandMoreIcon />}>{fireCentreName}</StyledAccordionSummary>
<AccordionDetails
sx={{
backgroundColor: INFO_PANEL_CONTENT_BACKGORUND,
backgroundColor: INFO_PANEL_CONTENT_BACKGROUND,
padding: '0',
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react'
import CombustibleAreaViz from 'features/fba/components/viz/CombustibleAreaViz'
import { Grid } from '@mui/material'
import { isUndefined } from 'lodash'
import { ElevationInfoByThreshold, FireShape, FireShapeArea, FireZoneThresholdFuelTypeArea } from 'api/fbaAPI'
Expand Down Expand Up @@ -35,11 +34,6 @@ const FireZoneUnitSummary = ({
direction={'column'}
sx={{ paddingBottom: theme.spacing(2), paddingTop: theme.spacing(2) }}
>
<Grid item>
<CombustibleAreaViz
fireZoneAreas={fireShapeAreas.filter(area => area.fire_shape_id == selectedFireZoneUnit?.fire_shape_id)}
/>
</Grid>
<Grid item sx={{ width: '95%' }}>
<FuelSummary selectedFireZoneUnit={selectedFireZoneUnit} fuelTypeInfo={fuelTypeInfo} />
</Grid>
Expand Down
4 changes: 2 additions & 2 deletions web/src/features/fba/components/infoPanel/InfoAccordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react'
import { Accordion, AccordionDetails, AccordionSummary, Typography } from '@mui/material'
import { styled, useTheme } from '@mui/material/styles'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { INFO_PANEL_HEADER_BACKGORUND } from 'app/theme'
import { INFO_PANEL_HEADER_BACKGROUND } from 'app/theme'

interface InfoAccordionProps {
accordionDetailBackgroundColour?: string
Expand All @@ -13,7 +13,7 @@ interface InfoAccordionProps {
}

const StyledAccordionSummary = styled(AccordionSummary)(() => ({
backgroundColor: INFO_PANEL_HEADER_BACKGORUND,
backgroundColor: INFO_PANEL_HEADER_BACKGROUND,
['& .MuiAccordionSummary-content']: {
margin: 0
}
Expand Down
2 changes: 1 addition & 1 deletion web/src/features/fba/components/infoPanel/InfoPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface InfoPanelProps {
// A component to host information in a side panel in ASA.
const InfoPanel = React.forwardRef(({ children }: InfoPanelProps, ref: React.ForwardedRef<HTMLDivElement>) => {
return (
<Grid data-testid="info-panel" item ref={ref} sx={{ minWidth: '500px', overflowY: 'auto' }}>
<Grid data-testid="info-panel" item ref={ref} sx={{ width: '500px', overflowY: 'auto' }}>
{children}
</Grid>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import InfoAccordion from 'features/fba/components/infoPanel/InfoAccordion'
import { isNull, isUndefined } from 'lodash'
import { Typography } from '@mui/material'
import { useTheme } from '@mui/material/styles'
import { INFO_PANEL_CONTENT_BACKGORUND } from 'app/theme'
import { INFO_PANEL_CONTENT_BACKGROUND } from 'app/theme'
import { FireCentres } from 'utils/constants'

interface ProvincialSummaryProps {
Expand Down Expand Up @@ -68,7 +68,7 @@ const ProvincialSummary = ({ advisoryThreshold }: ProvincialSummaryProps) => {
return (
<div data-testid="provincial-summary">
<InfoAccordion
accordionDetailBackgroundColour={noProvincialSummary ? undefined : INFO_PANEL_CONTENT_BACKGORUND}
accordionDetailBackgroundColour={noProvincialSummary ? undefined : INFO_PANEL_CONTENT_BACKGROUND}
defaultExpanded={true}
title={'Provincial Summary'}
>
Expand Down
Loading
Loading