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

feat: New Global Controls in the Layer Picker #352

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion frontend/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
script-src 'self' https://www2.gov.bc.ca https://*.openstreetmap.org;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://use.fontawesome.com https://*.openstreetmap.org;
font-src 'self' https://fonts.gstatic.com https://*.openstreetmap.org;
img-src 'self' data: https://fonts.googleapis.com http://www.w3.org https://*.gov.bc.ca https://*.openstreetmap.org https://*.stadiamaps.com https://server.arcgisonline.com https://api.maptiler.com;
img-src 'self' data: https://fonts.googleapis.com http://www.w3.org https://*.gov.bc.ca https://*.google.com https://*.openstreetmap.org https://*.stadiamaps.com https://server.arcgisonline.com https://api.maptiler.com;
frame-ancestors 'none';
form-action 'self' {$BACKEND_URL};
frame-src 'none';
Expand Down
2 changes: 1 addition & 1 deletion frontend/e2e/pages/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const map_page = async (page: Page) => {
await page.getByTitle('Close').click({ force: true })

// Test basemap switcher
const basemapButton = page.locator('.basemap-toggle')
const basemapButton = page.locator('.leaflet-control-basemaps')
await expect(basemapButton).toBeVisible()
await basemapButton.click()

Expand Down
Binary file removed frontend/public/Streets.png
Binary file not shown.
Binary file removed frontend/public/custom-1.png
Binary file not shown.
Binary file removed frontend/public/custom-2.png
Binary file not shown.
Binary file removed frontend/public/custom-3.png
Binary file not shown.
Binary file removed frontend/public/custom-4.png
Binary file not shown.
Binary file removed frontend/public/pale-osm.png
Binary file not shown.
Binary file modified frontend/public/streets.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/terrain2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion frontend/src/components/DataLayersCheckboxGroup.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@
padding: 0;
}

button.layer-button {
color: black;
text-transform: none;
text-decoration: none;
}

button.layer-button:hover {
text-decoration: underline;
}

p.data-layers-top-text,
.data-layers-top-link {
color: var(--typography-color-disabled);
font-size: 14px;
font-style: italic;
}

.available-layers-row {
Expand Down
13 changes: 2 additions & 11 deletions frontend/src/components/DataLayersCheckboxGroup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ describe('Test suite for DataLayersCheckboxGroup', () => {
})

expect(screen.queryByText('Available Layers')).not.toBeInTheDocument()
expect(screen.queryByText('Reset')).not.toBeInTheDocument()
expect(screen.queryByText('Reset Layers')).not.toBeInTheDocument()

const toggle = screen.getByRole('button', {
name: 'Aquifers and Water Wells',
Expand All @@ -81,12 +79,8 @@ describe('Test suite for DataLayersCheckboxGroup', () => {
expect(state.dataLayers).toHaveLength(1)
expect(state.hasDataLayersOn).toBe(true)

const resetBtn = screen.getByRole('button', { name: 'Reset Layers' })
const resetBtn = screen.getByRole('button', { name: 'Clear All' })
await user.click(resetBtn)

expect(state.dataLayers).toHaveLength(0)
expect(state.hasDataLayersOn).toBe(false)
expect(screen.queryByText('Reset Layers')).not.toBeInTheDocument()
})

it('should render small DataLayersCheckboxGroup', async () => {
Expand All @@ -105,10 +99,7 @@ describe('Test suite for DataLayersCheckboxGroup', () => {
expect(state.dataLayers).toHaveLength(1)
expect(state.hasDataLayersOn).toBe(true)

const resetLink = screen.getByRole('button', { name: 'Reset' })
const resetLink = screen.getByRole('button', { name: 'Clear All' })
await user.click(resetLink)

expect(state.dataLayers).toHaveLength(0)
expect(screen.queryByText('Reset Layers')).not.toBeInTheDocument()
})
})
81 changes: 52 additions & 29 deletions frontend/src/components/DataLayersCheckboxGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NavLink } from 'react-router-dom'
import { useDispatch } from 'react-redux'
import { Button, Stack, Typography } from '@mui/material'
import clsx from 'clsx'
import { useState } from 'react'

import { DATA_LAYER_GROUPS } from '@/constants/data-layers'
import {
Expand All @@ -26,15 +27,26 @@ export function DataLayersCheckboxGroup({
const dispatch = useDispatch()
const isLarge = !isSmall
const hasDataLayers = useHasDataLayersOn()

const onLayerToggle = (layer: DataLayer) => {
dispatch(toggleDataLayer(layer))
}
const [forceAction, setForceAction] = useState<'collapse' | 'expand' | null>(
null,
)

const onReset = () => {
dispatch(resetDataLayers())
}

const onCollapseAll = () => {
setForceAction('collapse')
}

const onExpandAll = () => {
setForceAction('expand')
}

const onLayerToggle = (layer: DataLayer) => {
dispatch(toggleDataLayer(layer))
}

return (
<Stack
direction="column"
Expand All @@ -47,28 +59,38 @@ export function DataLayersCheckboxGroup({
data-testid="data-layers-checkbox-group"
>
<Stack direction="column" className="data-layers-top-section">
<Typography className="data-layers-top-text">
All data layers sourced from GeoBC.
</Typography>
<NavLink to="/guidance" className="data-layers-top-link">
Click here to read our guidance page about map layers.
</NavLink>
<Stack direction="row" justifyContent="space-between">
<Button
variant="text"
size="small"
className="layer-button"
onClick={onReset}
>
Clear All
</Button>
<Button
variant="text"
size="small"
className="layer-button"
onClick={onCollapseAll}
>
Collapse All
</Button>
<Button
variant="text"
size="small"
onClick={onExpandAll}
className="layer-button"
>
Expand All
</Button>
</Stack>
</Stack>
{isSmall && (
<div className="available-layers-row">
<Typography className="available-layers-text">
Available Layers
</Typography>
{hasDataLayers && (
<Button
variant="text"
size="small"
className="data-layers-reset-link"
onClick={onReset}
>
Reset
</Button>
)}
</div>
)}
{DATA_LAYER_GROUPS.map((group: DataLayerGroup) => (
Expand All @@ -77,17 +99,18 @@ export function DataLayersCheckboxGroup({
group={group}
onLayerToggle={onLayerToggle}
isSmall={isSmall}
forceAction={forceAction}
setForceAction={setForceAction}
/>
))}
{isLarge && hasDataLayers && (
<Button
variant="outlined"
onClick={onReset}
className="data-layers-reset-button"
>
Reset Layers
</Button>
)}
<Stack direction="column" spacing={1}>
<Typography className="data-layers-top-text">
All data layers sourced from GeoBC.
</Typography>
<NavLink to="/guidance" className="data-layers-top-link">
Click here to read our guidance page about map layers.
</NavLink>
</Stack>
</Stack>
)
}
24 changes: 23 additions & 1 deletion frontend/src/components/DataLayersToggleGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react'
import { useState, useEffect } from 'react'
import {
Button,
Checkbox,
Expand All @@ -16,22 +16,44 @@ import DownArrow from '@/assets/svgs/fa-caret-down.svg?react'

import './DataLayersToggleGroup.css'

type ForceAction = 'collapse' | 'expand' | null

interface Props {
group: DataLayerGroup
onLayerToggle: (layer: DataLayer) => void
isSmall: boolean
forceAction?: ForceAction
setForceAction: (action: ForceAction) => void
}

export function DataLayersToggleGroup({
group,
onLayerToggle,
isSmall,
forceAction,
setForceAction,
}: Readonly<Props>) {
const [expanded, setExpanded] = useState<boolean>(true)
const isDataLayerChecked = useIsDataLayerOn()

// Track when global expand/collapse was last triggered
const [lastGlobalAction, setLastGlobalAction] = useState<
'collapse' | 'expand' | null
>(null)

useEffect(() => {
if (forceAction && forceAction !== lastGlobalAction) {
setExpanded(forceAction === 'expand')
setLastGlobalAction(forceAction)
// Reset the force action after it's been applied
setTimeout(() => setForceAction(null), 0)
}
}, [forceAction, lastGlobalAction, setForceAction])

const onToggle = () => {
setExpanded(!expanded)
// Reset the global action tracking when user manually toggles
setLastGlobalAction(null)
}

return (
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/map/MapView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ describe('Test suite for MapView', () => {
const { user } = renderComponent(themeBreakpointValues.xxl, [])

const dataLayersBtn = screen.getByRole('button', {
name: 'Data Layers',
name: 'Layers',
})
await user.click(dataLayersBtn)

Expand All @@ -211,7 +211,7 @@ describe('Test suite for MapView', () => {
await user.click(layerCb)
expect(layerCb).toBeChecked()

const resetBtn = screen.getByRole('button', { name: 'Reset Layers' })
const resetBtn = screen.getByRole('button', { name: 'Clear All' })
await user.click(resetBtn)
expect(layerCb).not.toBeChecked()
})
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/pages/map/MapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { MapSearch } from './search/MapSearch'
import { MapDrawer } from './drawer/MapDrawer'
import { AuthorizationMarkers } from './layers/AuthorizationMarkers'
import { MyLocationMarker } from './layers/MyLocationMarker'
import { BasemapControl } from './layers/BasemapControl'
import { MapControls } from './layers/MapControls'
import { MapDataLayers } from './layers/MapDataLayers'
import { MapZoom } from './layers/MapZoom'
Expand Down Expand Up @@ -38,7 +37,6 @@ function MapView() {
zoomControl={false}
className="map-container"
>
<BasemapControl />
<MapDataLayers />
<MapControls />
<AuthorizationMarkers />
Expand Down
Loading
Loading