Skip to content

Commit

Permalink
Show/Hide weather models (#3402)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgboss authored Feb 14, 2024
1 parent df91b76 commit ac14d0c
Show file tree
Hide file tree
Showing 8 changed files with 550 additions and 50 deletions.
3 changes: 3 additions & 0 deletions web/src/app/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,6 @@ export const PLANNING_AREA = {
height: 45
}
export const UNSELECTED_STATION_COLOR = 'rgba(0,0,0,0.54)'
export const DARK_GREY = '#A7A7A7'
export const LIGHT_GREY = '#DADADA'
export const MEDIUM_GREY = '#B5B5B5'
97 changes: 96 additions & 1 deletion web/src/features/moreCast2/components/DataGridColumns.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react'
import { GridColumnVisibilityModel, GridColDef, GridColumnGroupingModel } from '@mui/x-data-grid'
import { WeatherDeterminate, WeatherDeterminateChoices } from 'api/moreCast2API'
import {
Expand All @@ -6,9 +7,12 @@ import {
MORECAST2_INDEX_FIELDS,
MORECAST2_STATION_DATE_FIELDS
} from 'features/moreCast2/components/MoreCast2Column'
import GroupHeader from 'features/moreCast2/components/GroupHeader'
import { handleShowHideChangeType } from 'features/moreCast2/components/TabbedDataGrid'

export interface ColumnVis {
columnName: string
displayName?: string
visible: boolean
}

Expand All @@ -27,7 +31,27 @@ export class DataGridColumns {
return model
}

public static updateGridColumnVisibliityModel(
public static initGridColumnVisibilityModelNew() {
// First check local storage for existing column visibility
const groupedColumnVisibility = localStorage.getItem('groupedColumnVisibility')
if (groupedColumnVisibility) {
console.log(groupedColumnVisibility)
}

const model: GridColumnVisibilityModel = {}
const weatherParameterColumns = this.getWeatherParameterColumns()
weatherParameterColumns.forEach(columnName => {
// temperature columns are visible by default
if (columnName.startsWith('temp')) {
model[columnName] = true
} else {
model[columnName] = false
}
})
return model
}

public static updateGridColumnVisibilityModel(
parameters: ColumnVis[],
columnVisibilityModel: GridColumnVisibilityModel
) {
Expand All @@ -44,6 +68,18 @@ export class DataGridColumns {
return newModel
}

public static updateGridColumnVisibilityFromShowHideColumnsModel(
parameters: ColumnVis[],
columnVisibilityModel: GridColumnVisibilityModel
) {
const newModel: GridColumnVisibilityModel = {}
Object.assign(newModel, columnVisibilityModel)
for (const param of parameters) {
newModel[param.columnName] = param.visible
}
return newModel
}

public static getTabColumns(): GridColDef[] {
let tabColumns: GridColDef[] = []
MORECAST2_FIELDS.forEach(field => {
Expand All @@ -64,6 +100,65 @@ export class DataGridColumns {
const fields = DataGridColumns.getTabColumns().map(column => column.field)
return fields.filter(field => field !== 'stationName' && field !== 'forDate')
}

public static getWeatherModelColumns() {
const columns = DataGridColumns.getTabColumns()
return columns.filter(
column => column.field !== 'stationName' && column.field !== 'forDate' && !column.field.endsWith('Forecast')
)
}
}

const renderGroupHeader = (
id: string,
weatherParam: string,
columns: ColumnVis[],
handleShowHideChange: handleShowHideChangeType
) => {
return (
<GroupHeader columns={columns} id={id} weatherParam={weatherParam} handleShowHideChange={handleShowHideChange} />
)
}

export const getColumnGroupingModel = (
showHideColumnsModel: Record<string, ColumnVis[]>,
handleShowHideChange: handleShowHideChangeType
) => {
const model = [
{
groupId: 'ID',
children: [{ field: 'stationName' }, { field: 'forDate' }]
},
{
groupId: 'Temp',
children: columnGroupingModelChildGenerator('temp'),
renderHeaderGroup: () => renderGroupHeader('Temp', 'temp', showHideColumnsModel['temp'], handleShowHideChange)
},
{
groupId: 'RH',
children: columnGroupingModelChildGenerator('rh'),
renderHeaderGroup: () => renderGroupHeader('RH', 'rh', showHideColumnsModel['rh'], handleShowHideChange)
},
{
groupId: 'Precip',
children: columnGroupingModelChildGenerator('precip'),
renderHeaderGroup: () =>
renderGroupHeader('Precip', 'precip', showHideColumnsModel['precip'], handleShowHideChange)
},
{
groupId: 'Wind Dir',
children: columnGroupingModelChildGenerator('windDirection'),
renderHeaderGroup: () =>
renderGroupHeader('Wind Dir', 'windDirection', showHideColumnsModel['windDirection'], handleShowHideChange)
},
{
groupId: 'Wind Speed',
children: columnGroupingModelChildGenerator('windSpeed'),
renderHeaderGroup: () =>
renderGroupHeader('Wind Speed', 'windSpeed', showHideColumnsModel['windSpeed'], handleShowHideChange)
}
]
return model
}

export const columnGroupingModel: GridColumnGroupingModel = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ const NOT_AVAILABLE = 'N/A'

export class GridComponentRenderer {
public renderForecastHeaderWith = (params: GridColumnHeaderParams) => {
return <Button>{params.colDef.headerName}</Button>
return <Button data-testid={`${params.colDef.field}-column-header`}>{params.colDef.headerName}</Button>
}
public renderHeaderWith = (params: GridColumnHeaderParams) => {
if (params.field.endsWith('_BIAS')) {
const headerName = params.colDef.headerName || ''
const index = headerName.indexOf('_BIAS')
const prefix = headerName.slice(0, index)
return (
<div>
<div data-testid={`${params.colDef.field}-column-header`}>
<Box sx={{ height: '1rem' }}>{prefix}</Box>
<Box>bias</Box>
</div>
)
}
return <>{params.colDef.headerName}</>
return <div data-testid={`${params.colDef.field}-column-header`}>{params.colDef.headerName}</div>
}
public renderCellWith = (params: Pick<GridRenderCellParams, 'formattedValue'>) => (
<TextField sx={{ pointerEvents: 'none' }} disabled={true} size="small" value={params.formattedValue}></TextField>
Expand Down
90 changes: 90 additions & 0 deletions web/src/features/moreCast2/components/GroupHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Checkbox, FormControlLabel, FormGroup, IconButton, Popover, Stack, Typography, styled } from '@mui/material'
import { ExpandMore } from '@mui/icons-material'
import React, { ChangeEvent, MouseEvent, useState } from 'react'
import { LIGHT_GREY, MEDIUM_GREY, DARK_GREY } from 'app/theme'
import { ColumnVis } from 'features/moreCast2/components/DataGridColumns'

interface GroupHeaderProps {
id: string
columns: ColumnVis[]
weatherParam: string
handleShowHideChange: (weatherParam: string, columnName: string, value: boolean) => void
}

const PopoverHeader = styled(Typography)(({ theme }) => ({
backgroundColor: DARK_GREY,
fontSize: '14px',
fontWeight: 'bold',
padding: theme.spacing(1)
}))

const PopoverFormControlLabel = styled(FormControlLabel)(({ theme }) => ({
height: theme.spacing(4),
marginRight: 0,
paddingLeft: theme.spacing(1),
[':hover']: {
backgroundColor: LIGHT_GREY
}
}))

const ShowHideCheckbox = styled(Checkbox)({
['&.Mui-checked']: {
color: MEDIUM_GREY
}
})

const GroupHeader = ({ id, columns, weatherParam, handleShowHideChange }: GroupHeaderProps) => {
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)
const open = Boolean(anchorEl)
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget)
}

const handleClose = () => {
setAnchorEl(null)
}

const handleOnChange = (event: ChangeEvent<HTMLInputElement>) => {
handleShowHideChange(weatherParam, event.target.name, event.target.checked)
}

return (
<>
<Typography style={{ fontWeight: 'bold' }}>{id}</Typography>
<IconButton onClick={handleClick}>
<ExpandMore />
</IconButton>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
>
<Stack sx={{ overflow: 'hidden' }}>
<PopoverHeader>Choose Models to Display</PopoverHeader>
<FormGroup>
{columns.map(column => {
return (
<PopoverFormControlLabel
control={
<ShowHideCheckbox
checked={column.visible}
name={column.columnName}
onChange={handleOnChange}
size="small"
/>
}
key={column.columnName}
label={<Typography sx={{ fontSize: '12px' }}>{column.displayName}</Typography>}
/>
)
})}
</FormGroup>
</Stack>
</Popover>
</>
)
}

export default React.memo(GroupHeader)
10 changes: 8 additions & 2 deletions web/src/features/moreCast2/components/SelectableButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ import { theme } from 'app/theme'

interface SelectableButtonProps {
children?: React.ReactNode
dataTestId?: string
onClick: () => void
selected: boolean
}

const SelectableButton = ({ children, onClick, selected }: SelectableButtonProps) => {
const SelectableButton = ({ children, dataTestId, onClick, selected }: SelectableButtonProps) => {
return (
<Button sx={{ marginLeft: theme.spacing(1) }} onClick={onClick} variant={selected ? 'contained' : 'outlined'}>
<Button
data-testid={dataTestId}
sx={{ marginLeft: theme.spacing(1) }}
onClick={onClick}
variant={selected ? 'contained' : 'outlined'}
>
{children}
</Button>
)
Expand Down
Loading

0 comments on commit ac14d0c

Please sign in to comment.