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: Enhancements to the Radius Search Tool #366

Merged
merged 19 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 3 additions & 1 deletion frontend/e2e/pages/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export const map_page = async (page: Page) => {
await expect(
page.getByRole('button', { name: 'Polygon Search' }),
).toBeVisible()
await expect(page.getByRole('button', { name: 'Point Search' })).toBeVisible()
await expect(
page.getByRole('button', { name: 'Radius Search' }),
).toBeVisible()

const searchBy = page.getByText('Status')
await expect(searchBy).toBeVisible()
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/AuthorizationListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function AuthorizationListItem({
sx={sx}
>
<Typography component="div" fontSize={14} marginBottom="8px">
Authorization #: <b>{number}</b>
Authorization #: <span>{number}</span>
</Typography>
<Typography
component="div"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ export enum ActiveToolEnum {
/**
* The smallest allowed radius in meters for the Point Search feature.
*/
export const MIN_CIRCLE_RADIUS = 500
export const MIN_CIRCLE_RADIUS = 1000
14 changes: 14 additions & 0 deletions frontend/src/features/map/map-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface MapSliceState {
// data layers, search by and filter by (small screens only - shown in bottom drawer)
activeTool?: ActiveToolEnum
searchResults: OmrrData[]
isRadiusActive: boolean
}

export const initialState: MapSliceState = {
Expand All @@ -44,6 +45,7 @@ export const initialState: MapSliceState = {
dataLayers: [],
activeTool: undefined,
searchResults: [],
isRadiusActive: false,
}

export const mapSlice = createSlice({
Expand Down Expand Up @@ -99,6 +101,14 @@ export const mapSlice = createSlice({
clearSearchResults: (state) => {
state.searchResults = []
},
setRadiusActive: (state, action: PayloadAction<boolean>) => {
state.isRadiusActive = action.payload
if (action.payload) {
state.bottomDrawerHeight = 500 // 300 + 200
} else {
state.bottomDrawerHeight = 300
}
},
},
})

Expand All @@ -114,6 +124,7 @@ export const {
toggleActiveTool,
clearActiveTool,
clearSearchResults,
setRadiusActive,
} = mapSlice.actions

// Create a thunk to clear both search results and search text
Expand Down Expand Up @@ -162,3 +173,6 @@ export const useHasDataLayersOn = () => useSelector(selectDataLayers).length > 0

const selectActiveTool = (state: RootState) => state.map.activeTool
export const useActiveTool = () => useSelector(selectActiveTool)

export const useRadiusActive = () =>
useSelector((state: RootState) => state.map.isRadiusActive)
28 changes: 27 additions & 1 deletion frontend/src/features/omrr/omrr-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export interface OmrrSliceState {
lastSearchTime?: number
pointFilterCenter?: LatLngTuple
pointFilterRadius: number
pointFilterFinished: boolean
polygonFilterPositions: LatLngTuple[]
polygonFilterFinished: boolean
}
Expand Down Expand Up @@ -79,6 +80,7 @@ export const initialState: OmrrSliceState = {
// The point filter is active when the center point is defined
pointFilterCenter: undefined,
pointFilterRadius: MIN_CIRCLE_RADIUS,
pointFilterFinished: false,
// The polygon filter is active when finished is true
polygonFilterPositions: [],
polygonFilterFinished: false,
Expand Down Expand Up @@ -215,8 +217,8 @@ export const omrrSlice = createSlice({
}
},
resetPointFilter: (state) => {
// Reset point filter and search if necessary
state.pointFilterRadius = MIN_CIRCLE_RADIUS
state.pointFilterFinished = false
if (state.pointFilterCenter) {
state.pointFilterCenter = undefined
performSearch(state, false)
Expand All @@ -232,6 +234,18 @@ export const omrrSlice = createSlice({
performSearch(state, false)
}
},
setPointFilterFinished: (state) => {
if (!state.pointFilterFinished && state.pointFilterCenter) {
state.pointFilterFinished = true
performSearch(state)
}
},
setPointFilterUnfinished: (state) => {
if (!state.pointFilterFinished && state.pointFilterCenter) {
state.pointFilterFinished = false
performSearch(state)
}
},
},
extraReducers: (builder: ActionReducerMapBuilder<OmrrSliceState>) => {
// Handle the pending action
Expand Down Expand Up @@ -284,6 +298,8 @@ export const {
setPointFilterRadius,
resetPointFilter,
clearShapeFilters,
setPointFilterFinished,
setPointFilterUnfinished,
} = omrrSlice.actions

export default omrrSlice.reducer
Expand Down Expand Up @@ -356,3 +372,13 @@ const selectPointFilterRadius = (state: RootState) =>
state.omrr.pointFilterRadius
export const usePointFilterCenter = () => useSelector(selectPointFilterCenter)
export const usePointFilterRadius = () => useSelector(selectPointFilterRadius)

// Add a new selector to check if point filter is active
export const usePointFilterActive = () => {
return useSelector(
(state: RootState) => state.omrr.pointFilterCenter !== undefined,
)
}

export const usePointFilterFinished = () =>
useSelector((state: RootState) => state.omrr.pointFilterFinished)
2 changes: 1 addition & 1 deletion frontend/src/pages/map/MapView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe('Test suite for MapView', () => {
it('should render the MapView and test point search', async () => {
const { user } = renderComponent(themeBreakpointValues.xxl, mockOmrrData)

const pointSearchBtn = screen.getByRole('button', { name: 'Point Search' })
const pointSearchBtn = screen.getByRole('button', { name: 'Radius Search' })
await user.click(pointSearchBtn)

const cancelBtn = screen.getByRole('button', { name: 'Cancel' })
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/pages/map/drawer/MapBottomDrawer.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
border-radius: 6px 6px 0 0;
border-bottom: 1px solid var(--surface-color-border-light);
transition: height 0.5s ease-in-out;
max-height: calc(100% - var(--header-height));
}

.map-bottom-drawer.map-bottom-drawer--full-height {
Expand Down Expand Up @@ -85,3 +86,11 @@ button.map-bottom-drawer-button {
overflow: hidden auto;
padding-bottom: 40px;
}

.map-bottom-drawer--expanded {
min-height: 100px;
}

.map-bottom-drawer--expanded.radius-active {
min-height: 250px;
}
11 changes: 9 additions & 2 deletions frontend/src/pages/map/drawer/MapBottomDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { SearchResultsList } from './SearchResultsList'
import { PolygonSearch } from '../search/PolygonSearch'
import { PointSearch } from '../search/PointSearch'
import { ClearSelectedItemButton } from './ClearSelectedItemButton'
import { useRadiusActive } from '@/features/map/map-slice'

import ChevronUpIcon from '@/assets/svgs/fa-chevron-up.svg?react'
import CloseIcon from '@/assets/svgs/close.svg?react'
Expand All @@ -31,7 +32,7 @@ function getTitle(
case ActiveToolEnum.polygonSearch:
return 'Polygon Search'
case ActiveToolEnum.pointSearch:
return 'Point Search'
return 'Radius Search'
case ActiveToolEnum.searchBy:
return 'Status'
case ActiveToolEnum.filterBy:
Expand Down Expand Up @@ -64,6 +65,7 @@ export function MapBottomDrawer() {
} = useBottomDrawerState()
const [fullHeight, setFullHeight] = useState<boolean>(false)
const ref = useRef<HTMLDivElement>(null)
const isRadiusActive = useRadiusActive()

const onClose = () => {
setExpanded(false)
Expand Down Expand Up @@ -96,11 +98,16 @@ export function MapBottomDrawer() {
return (
<div
ref={ref}
style={!isExpanded || fullHeight ? undefined : { height: `${height}px` }}
style={
!isExpanded || fullHeight
? undefined
: { height: `${height}px`, maxHeight: '80vh' }
}
className={clsx(
'map-bottom-drawer',
isExpanded && 'map-bottom-drawer--expanded',
fullHeight && 'map-bottom-drawer--full-height',
isExpanded && isRadiusActive && 'radius-active',
)}
data-testid="map-bottom-drawer"
>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/map/drawer/MapDrawer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ describe('Test suite for MapDrawer', () => {
await waitFor(() => expect(div).toHaveClass('map-bottom-drawer--expanded'))
expect(state.bottomDrawerHeight).toBe(MAP_BOTTOM_DRAWER_HEIGHT_SMALL)
expect(state.activeTool).toBe(ActiveToolEnum.pointSearch)
screen.getByText('Point Search')
screen.getByText('Radius Search')
screen.getByRole('slider', { name: 'Search radius' })

// Swipe up to make full height
Expand Down
17 changes: 12 additions & 5 deletions frontend/src/pages/map/layers/PointSearchLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
setPointFilterCenter,
usePointFilterCenter,
usePointFilterRadius,
usePointFilterFinished,
} from '@/features/omrr/omrr-slice'
import { useMapCrosshairsCursor } from '../hooks/useMapCrosshairsCursor'
import { CrosshairsTooltipMarker } from './CrosshairsTooltipMarker'
Expand All @@ -24,29 +25,35 @@ function CircleLayer() {
const dispatch = useDispatch()
const center = usePointFilterCenter()
const radius = usePointFilterRadius()
const finished = usePointFilterFinished()
const map = useMap()
useMapCrosshairsCursor(map)

useMapEvents({
click: (ev: LeafletMouseEvent) => {
const newCenter: LatLngTuple = [ev.latlng.lat, ev.latlng.lng]
dispatch(setPointFilterCenter(newCenter))
if (!finished) {
const newCenter: LatLngTuple = [ev.latlng.lat, ev.latlng.lng]
dispatch(setPointFilterCenter(newCenter))
}
},
})

const drawCircle = center && radius > 0
return (
<>
<CrosshairsTooltipMarker center={center}>
Click to place center point
</CrosshairsTooltipMarker>
{!finished && (
<CrosshairsTooltipMarker center={center}>
Click to place center point
</CrosshairsTooltipMarker>
)}
{drawCircle && (
<Circle
center={center}
radius={radius}
stroke
fill
className="point-search-circle"
interactive={false}
/>
)}
</>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/map/search/AutocompleteItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function getLabel(matchType: MatchType, item: OmrrData | undefined): ReactNode {
const { 'Authorization Number': number = 0 } = item
return (
<span>
Authorization #: <b>{number}</b>
Authorization #: <span>{number}</span>
</span>
)
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/map/search/MapSearch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Test suite for MapSearch', () => {
screen.getByRole('button', { name: 'Find Me' })
screen.getByRole('button', { name: 'Layers' })
screen.getByRole('button', { name: 'Polygon Search' })
screen.getByRole('button', { name: 'Point Search' })
screen.getByRole('button', { name: 'Radius Search' })
screen.getByText('Status')
screen.getByRole('button', { name: 'Filter' })

Expand All @@ -37,7 +37,7 @@ describe('Test suite for MapSearch', () => {
screen.queryByRole('button', { name: 'Layers' }),
).not.toBeInTheDocument()
screen.getByRole('button', { name: 'Polygon Search' })
screen.getByRole('button', { name: 'Point Search' })
screen.getByRole('button', { name: 'Radius Search' })
screen.getByText('Status')
screen.getByRole('button', { name: 'Filter' })
})
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/map/search/PointSearch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('Test suite for PointSearch', () => {

const setRadiusBtn = screen.getByRole('button', { name: 'Set Radius' })
await user.click(setRadiusBtn)
screen.getByText(`${MIN_CIRCLE_RADIUS} m`)
screen.getByText(`${MIN_CIRCLE_RADIUS / 1000} km`)
const slider = screen.getByRole('slider', { name: 'Search radius' })
fireEvent.change(slider, { target: { value: 1000 } })
expect(state.pointFilterCenter).toBeUndefined()
Expand All @@ -68,7 +68,7 @@ describe('Test suite for PointSearch', () => {
expect(screen.queryByText('Cancel')).not.toBeInTheDocument()
screen.getByText('Set Radius:')
const slider = screen.getByRole('slider', { name: 'Search radius' })
screen.getByText(`${MIN_CIRCLE_RADIUS} m`)
screen.getByText(`${MIN_CIRCLE_RADIUS / 1000} km`)
fireEvent.change(slider, { target: { value: 2000 } })
expect(state.pointFilterCenter).toBeUndefined()
expect(state.pointFilterRadius).toBe(2000)
Expand Down
Loading
Loading