Skip to content

Commit

Permalink
Fix logic bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
ev-sc committed Dec 11, 2024
1 parent baa2272 commit 28d4cfc
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import {
} from '../../mapboxStyles'
import { MapReportExtended } from '../../reportContext'
import { Tileset } from '../../types'
import useBoundaryCounts from '../../useBoundaryCounts'
import useBoundaryStats from '../../useBoundaryStats'
import useDataByBoundary from '../../useDataByBoundary'
import useClickOnBoundaryEvents, {
selectedBoundaryAtom,
} from '../../useSelectBoundary'
Expand All @@ -34,14 +33,12 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({
tileset,
}) => {
// Show the layer only if the report is set to show the boundary type
// and the selected dataSource
const visibility =
report.displayOptions?.dataVisualisation?.boundaryType === boundaryType
? 'visible'
: 'none'

const countsByBoundaryType = useBoundaryCounts(report, boundaryType)
const dataByBoundaryType = useBoundaryStats(report, boundaryType)
const { data: dataByBoundary } = useDataByBoundary({ report, boundaryType })
const map = useLoadedMap()
const [selectedBoundary, setSelectedBoundary] = useAtom(selectedBoundaryAtom)
useClickOnBoundaryEvents(visibility === 'visible' ? tileset : null)
Expand All @@ -54,11 +51,11 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({

// When the map is loaded and we have the data, add the data to the boundaries
useEffect(() => {
if (map.loaded && countsByBoundaryType) {
if (map.loaded && dataByBoundary) {
// If the currently selected dataSource is of type "MEMBER",
// we need to add the count to the mapbox layer
addCountByGssToMapboxLayer(
countsByBoundaryType,
dataByBoundary,
tileset.mapboxSourceId,
tileset.sourceLayerId,
map.loadedMap
Expand All @@ -68,10 +65,10 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({
// we need to get the chosen dataSourecField
// and add the area stats to the mapbox layer
}
}, [map.loaded, countsByBoundaryType])
}, [map.loaded, dataByBoundary, report])

if (!map.loaded) return null
if (!countsByBoundaryType || !tileset) return null
if (!dataByBoundary || !tileset) return null

return (
<>
Expand All @@ -88,11 +85,8 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({
source={tileset.mapboxSourceId}
source-layer={tileset.sourceLayerId}
type="fill"
filter={getChoroplethFillFilter(countsByBoundaryType, tileset)}
paint={getChoroplethFill(
countsByBoundaryType,
visibility === 'visible'
)}
filter={getChoroplethFillFilter(dataByBoundary, tileset)}
paint={getChoroplethFill(dataByBoundary, visibility === 'visible')}
//layout={{ visibility: delayedVisibility }}
/>
{/* Border of the boundary */}
Expand Down Expand Up @@ -123,13 +117,13 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({
<Source
id={`${tileset.mapboxSourceId}-area-count`}
type="geojson"
data={getAreaGeoJSON(countsByBoundaryType)}
data={getAreaGeoJSON(dataByBoundary)}
>
<Layer
id={`${tileset.mapboxSourceId}-area-count`}
type="symbol"
layout={{
...getAreaCountLayout(countsByBoundaryType),
...getAreaCountLayout(dataByBoundary),
visibility,
}}
paint={{
Expand All @@ -153,7 +147,7 @@ const PoliticalChoropleths: React.FC<PoliticalChoroplethsProps> = ({
id={`${tileset.mapboxSourceId}-area-label`}
type="symbol"
layout={{
...getAreaLabelLayout(countsByBoundaryType),
...getAreaLabelLayout(dataByBoundary),
visibility,
}}
paint={{
Expand Down
92 changes: 49 additions & 43 deletions nextjs/src/app/reports/[id]/(components)/ReportVisualisation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { startCase } from 'lodash'
import React from 'react'
import { VisualisationType } from '../reportContext'
import useBoundaryStats, { getFieldsFromDataSource } from '../useBoundaryStats'
import useDataByBoundary from '../useDataByBoundary'
import CollapsibleSection from './CollapsibleSection'
import { UpdateConfigProps } from './ReportConfiguration'
import { useReport } from './ReportProvider'
Expand All @@ -23,9 +24,10 @@ const ReportVisualisation: React.FC<UpdateConfigProps> = ({
politicalBoundaries,
displayOptions: { dataVisualisation },
} = report
const dataByBoundaryType = useBoundaryStats(report)
const sourceFields =
dataByBoundaryType && getFieldsFromDataSource(dataByBoundaryType)
const { fieldNames } = useDataByBoundary({
report,
boundaryType: dataVisualisation?.boundaryType,
})

const visualisationType = dataVisualisation?.visualisationType
const dataSourceId = dataVisualisation?.dataSource
Expand Down Expand Up @@ -60,9 +62,9 @@ const ReportVisualisation: React.FC<UpdateConfigProps> = ({
<SelectValue />
</SelectTrigger>
<SelectContent>
{Object.keys(VisualisationType).map((type) => (
{Object.values(VisualisationType).map((type) => (
<SelectItem className="font-medium" key={type} value={type}>
{type}
{startCase(type)}
</SelectItem>
))}
</SelectContent>
Expand All @@ -71,43 +73,45 @@ const ReportVisualisation: React.FC<UpdateConfigProps> = ({
Colour shading by category
</p>
</div>
<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"
{report.layers.length && (
<div>
<Select
onValueChange={(type) =>
updateVisualisationConfig({
dataSource: type as MapLayer['id'],
})
}
value={dataSourceId}
>
<SelectValue />
</SelectTrigger>
<SelectContent>
{layers.map((layer) => (
<SelectItem
className="font-medium"
key={layer.id}
value={layer.id}
>
{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>
<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>
)}
{selectedDataSource?.source.dataType === 'AREA_STATS' && (
<div>
<Select
Expand All @@ -117,6 +121,8 @@ const ReportVisualisation: React.FC<UpdateConfigProps> = ({
})
}
value={dataSourceField}
defaultOpen={!dataSourceField}
required
>
<Label
htmlFor="select-vis-type"
Expand All @@ -131,7 +137,7 @@ const ReportVisualisation: React.FC<UpdateConfigProps> = ({
<SelectValue />
</SelectTrigger>
<SelectContent>
{sourceFields?.map((field) => (
{fieldNames?.map((field) => (
<SelectItem className="font-medium" key={field} value={field}>
{field}
</SelectItem>
Expand Down
4 changes: 2 additions & 2 deletions nextjs/src/app/reports/[id]/addCountByGssToMapboxLayer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { MAPBOX_LOAD_INTERVAL } from '@/lib/map/useLoadedMap'
import { MapRef } from 'react-map-gl'
import { CountByBoundary } from './useBoundaryCounts'
import { DataByBoundary } from './useDataByBoundary'

// GSS (Geographic Statistical System) codes are unique identifiers
// used in the UK to reference geographic areas for statistical purposes.
// The data prop needs to contain the gss code and the count
export function addCountByGssToMapboxLayer(
data: CountByBoundary,
data: DataByBoundary,
mapboxSourceId: string,
sourceLayerId?: string,
mapbox?: MapRef | null
Expand Down
14 changes: 7 additions & 7 deletions nextjs/src/app/reports/[id]/mapboxStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
SymbolLayerSpecification,
} from 'mapbox-gl'
import { Tileset } from './types'
import { CountByBoundary } from './useBoundaryCounts'
import { DataByBoundary } from './useDataByBoundary'

export function getChoroplethFill(
data: { count: number }[],
Expand Down Expand Up @@ -61,7 +61,7 @@ export function getChoroplethFill(
...colourStops,
],
'fill-opacity': visible ? 1 : 0,
'fill-opacity-transition': { duration: 500 },
'fill-opacity-transition': { duration: 750 },
}
}

Expand Down Expand Up @@ -105,7 +105,7 @@ export function getSelectedChoroplethEdge(): LineLayerSpecification['paint'] {
}
}
export const getChoroplethFillFilter = (
data: CountByBoundary,
data: DataByBoundary,
tileset: Tileset
) => {
return [
Expand All @@ -122,7 +122,7 @@ export const getSelectedChoroplethFillFilter = (
return ['==', ['get', tileset.promoteId], selectedGss]
}

export function getAreaGeoJSON(data: CountByBoundary) {
export function getAreaGeoJSON(data: DataByBoundary) {
return {
type: 'FeatureCollection',
features: data
Expand All @@ -138,7 +138,7 @@ export function getAreaGeoJSON(data: CountByBoundary) {
}
}

function getStatsForData(data: CountByBoundary) {
function getStatsForData(data: DataByBoundary) {
let min =
data.reduce(
(min, p) => (p?.count! < min ? p?.count! : min),
Expand All @@ -165,7 +165,7 @@ function getStatsForData(data: CountByBoundary) {
}

export const getAreaCountLayout = (
data: CountByBoundary
data: DataByBoundary
): SymbolLayerSpecification['layout'] => {
const { min, max, textScale } = getStatsForData(data)

Expand Down Expand Up @@ -206,7 +206,7 @@ export const getAreaCountLayout = (
}

export const getAreaLabelLayout = (
data: CountByBoundary
data: DataByBoundary
): SymbolLayerSpecification['layout'] => {
const { min, max, textScale } = getStatsForData(data)

Expand Down
14 changes: 9 additions & 5 deletions nextjs/src/app/reports/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import {
import { currentOrganisationIdAtom } from '@/lib/organisation'

import { SidebarProvider } from '@/components/ui/sidebar'
import { merge } from 'lodash'
import ReportDisplaySettings from './(components)/ReportDisplaySettings'
import ReportNavbar from './(components)/ReportNavbar'
import ReportPage from './(components)/ReportPage'
import ReportProvider from './(components)/ReportProvider'
import { ReportSidebarLeft } from './(components)/ReportSidebarLeft'
import { GET_MAP_REPORT } from './gql_queries'
import { getPoliticalTilesetsByCountry } from './politicalTilesets'
import { MapReportExtended } from './reportContext'
import { defaultReportConfig, MapReportExtended } from './reportContext'

type Params = {
id: string
Expand Down Expand Up @@ -50,10 +51,13 @@ export default function Page({ params: { id } }: { params: Params }) {
// Really important to check if the report is null before rendering the page
// The ReportProvider component needs to be able to provide a report to its children
if (!report.data?.mapReport) return null
const mapReport = {
...report.data.mapReport,
politicalBoundaries: getPoliticalTilesetsByCountry('uk'),
} as unknown as MapReportExtended
const mapReport = merge(
{
displayOptions: defaultReportConfig,
politicalBoundaries: getPoliticalTilesetsByCountry('uk'),
},
report.data.mapReport
) as unknown as MapReportExtended

return (
<JotaiProvider key={id}>
Expand Down
6 changes: 3 additions & 3 deletions nextjs/src/app/reports/[id]/reportContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ export type MapReportExtended = Omit<MapReport, 'displayOptions'> & {
}

export interface ReportConfig {
dataVisualisation?: {
dataVisualisation: {
boundaryType?: AnalyticalAreaType
visualisationType?: VisualisationType
palette?: Palette
dataSource?: MapLayer['id']
dataSourceField?: string
}
display?: {
display: {
showStreetDetails?: boolean
showMPs?: boolean
showLastElectionData?: boolean
Expand Down Expand Up @@ -56,7 +56,7 @@ interface ReportContextProps {
deleteReport: () => void
updateReport: (payload: {
name?: string
displayOptions?: ReportConfig
displayOptions?: Partial<ReportConfig>
layers?: any[]
}) => void
refreshReportData: () => void
Expand Down
Loading

0 comments on commit 28d4cfc

Please sign in to comment.