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

Allow choropleth to be toggled on and off #168

Merged
merged 8 commits into from
Dec 18, 2024
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AnalyticalAreaType } from '@/__generated__/graphql'
import { useLoadedMap } from '@/lib/map'
import { useAtom } from 'jotai'
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import { Layer, Source } from 'react-map-gl'
import { addCountByGssToMapboxLayer } from '../../addCountByGssToMapboxLayer'
import {
Expand Down Expand Up @@ -38,11 +38,22 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({
? 'visible'
: 'none'

const visualisationType =
report.displayOptions?.dataVisualisation?.visualisationType

const { data: dataByBoundary } = useDataByBoundary({ report, boundaryType })
const map = useLoadedMap()
const [selectedBoundary, setSelectedBoundary] = useAtom(selectedBoundaryAtom)
useClickOnBoundaryEvents(visibility === 'visible' ? tileset : null)

const [fillVisibility, setFillVisibility] = useState<'choropleth' | 'none'>(
visualisationType === 'none' ? 'none' : 'choropleth'
)

useEffect(() => {
setFillVisibility(visualisationType === 'none' ? 'none' : 'choropleth')
}, [visualisationType])
Moggach marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
if (visibility === 'none') {
setSelectedBoundary(null)
Expand Down Expand Up @@ -78,17 +89,19 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({
url={`mapbox://${tileset.mapboxSourceId}`}
promoteId={tileset.promoteId}
>
{/* Display fill when visualisation type if not none */}
{/* Fill of the boundary */}
<Layer
beforeId="road-simple"
id={`${tileset.mapboxSourceId}-fill`}
source={tileset.mapboxSourceId}
source-layer={tileset.sourceLayerId}
type="fill"
filter={getChoroplethFillFilter(dataByBoundary, tileset)}
paint={getChoroplethFill(dataByBoundary, visibility === 'visible')}
//layout={{ visibility: delayedVisibility }}
/>
{fillVisibility !== 'none' && (
<Layer
beforeId="road-simple"
id={`${tileset.mapboxSourceId}-fill`}
source={tileset.mapboxSourceId}
source-layer={tileset.sourceLayerId}
type="fill"
filter={getChoroplethFillFilter(dataByBoundary, tileset)}
paint={getChoroplethFill(dataByBoundary, visibility === 'visible')}
/>
)}
{/* Border of the boundary */}
<Layer
beforeId={PLACEHOLDER_LAYER_ID_CHOROPLETH}
Expand Down
194 changes: 105 additions & 89 deletions nextjs/src/app/reports/[id]/(components)/ReportVisualisation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,100 +66,116 @@ const ReportVisualisation: React.FC<UpdateConfigProps> = ({
<SelectValue />
</SelectTrigger>
<SelectContent>
{Object.values(VisualisationType).map((type) => (
<SelectItem className="font-medium" key={type} value={type}>
{startCase(type)}
</SelectItem>
))}
{Object.values(VisualisationType)
.filter((type) => type !== VisualisationType.None)
.map((type) => (
<SelectItem
className="font-medium flex items-center"
key={type}
value={type}
>
{startCase(type)}
{type === 'choropleth' && (
<span className="text-meepGray-400 text-xs ml-2">
Colour shading by category
</span>
)}
</SelectItem>
))}
<SelectItem className="font-medium" key="none" value="none">
None
</SelectItem>
</SelectContent>
</Select>
<p className="text-meepGray-400 text-sm font-normal mb-3 mt-3">
Colour shading by category
</p>
</div>
{/* Conditionally render selectors if visualisationType is not 'none' */}
{visualisationType !== 'none' && (
<>
{report.layers.length && (
<div>
<Select
onValueChange={(type) =>
updateVisualisationConfig({
dataSource: type as MapLayer['id'],
})
}
value={dataSourceId}
>
<Label
htmlFor="select-vis-type"
className="text-white text-sm font-medium"
>
Colour by
</Label>
<SelectTrigger
id="select-vis-type"
className="w-full border-meepGray-100 text-meepGray-100 mt-2 font-medium"
>
<SelectValue />
</SelectTrigger>
<SelectContent>
{layers.map((layer) => (
<SelectItem
className="font-medium"
key={layer.id}
value={layer.id}
>
{startCase(layer.name)}
</SelectItem>
))}
</SelectContent>
</Select>
<p className="text-meepGray-400 text-sm font-normal mb-3 mt-3">
Select which data will populate your {selectedBoundaryLabel}
</p>
</div>
)}

{report.layers.length && (
<div>
<Select
onValueChange={(type) =>
updateVisualisationConfig({
dataSource: type as MapLayer['id'],
})
}
value={dataSourceId}
>
<Label
htmlFor="select-vis-type"
className="text-white text-sm font-medium"
>
Colour by
</Label>
<SelectTrigger
id="select-vis-type"
className="w-full border-meepGray-100 text-meepGray-100 mt-2 font-medium"
>
<SelectValue />
</SelectTrigger>
<SelectContent>
{layers.map((layer) => (
<SelectItem
className="font-medium"
key={layer.id}
value={layer.id}
{selectedDataSource?.source.dataType === 'AREA_STATS' && (
<div>
<Select
onValueChange={(type) =>
updateVisualisationConfig({
dataSourceField: type as MapLayer['id'],
})
}
value={dataSourceField}
defaultOpen={!dataSourceField}
required
disabled={isLoading}
>
<Label
htmlFor="select-vis-type"
className="text-white text-sm font-medium"
>
{startCase(layer.name)}
</SelectItem>
))}
</SelectContent>
</Select>
<p className="text-meepGray-400 text-sm font-normal mb-3 mt-3">
Select which data will populate your {selectedBoundaryLabel}
</p>
</div>
)}
{selectedDataSource?.source.dataType === 'AREA_STATS' && (
<div>
<Select
onValueChange={(type) =>
updateVisualisationConfig({
dataSourceField: type as MapLayer['id'],
})
}
value={dataSourceField}
defaultOpen={!dataSourceField}
required
disabled={isLoading}
>
<Label
htmlFor="select-vis-type"
className="text-white text-sm font-medium"
>
Select data field
</Label>
<SelectTrigger
id="select-vis-type"
className="w-full border-meepGray-100 text-meepGray-100 mt-2 font-medium flex items-center"
>
{isLoading ? <LoadingIcon size={'18'} /> : <SelectValue />}
</SelectTrigger>
{!isLoading && (
<SelectContent>
{fieldNames.map((field) => (
<SelectItem
className="font-medium"
key={field}
value={field}
>
{field}
</SelectItem>
))}
</SelectContent>
)}
</Select>
<p className="text-meepGray-400 text-sm font-normal mb-3 mt-3">
Select the field from your data source
</p>
</div>
Select data field
</Label>
<SelectTrigger
id="select-vis-type"
className="w-full border-meepGray-100 text-meepGray-100 mt-2 font-medium flex items-center"
>
{isLoading ? <LoadingIcon size={'18'} /> : <SelectValue />}
</SelectTrigger>
{!isLoading && (
<SelectContent>
{fieldNames.map((field) => (
<SelectItem
className="font-medium"
key={field}
value={field}
>
{field}
</SelectItem>
))}
</SelectContent>
)}
</Select>
<p className="text-meepGray-400 text-sm font-normal mb-3 mt-3">
Select the field from your data source
</p>
</div>
)}
</>
)}
</div>
</CollapsibleSection>
Expand Down
1 change: 1 addition & 0 deletions nextjs/src/app/reports/[id]/reportContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createContext } from 'react'
import { PoliticalTileset } from './politicalTilesets'

export enum VisualisationType {
None = 'none',
Choropleth = 'choropleth',
}

Expand Down
Loading