diff --git a/app/charts/chart-config-ui-options.ts b/app/charts/chart-config-ui-options.ts index 5dd1ee40a..4d3f8163f 100644 --- a/app/charts/chart-config-ui-options.ts +++ b/app/charts/chart-config-ui-options.ts @@ -295,13 +295,13 @@ export const chartConfigOptionsUISpec: ChartSpecs = { field: "areaLayer", optional: false, values: ["Measure"], - filters: false, + filters: true, }, { field: "symbolLayer", optional: false, values: ["Measure"], - filters: false, + filters: true, }, ], interactiveFilters: [], diff --git a/app/charts/map/chart-map.tsx b/app/charts/map/chart-map.tsx index fae4f2457..870d39aed 100644 --- a/app/charts/map/chart-map.tsx +++ b/app/charts/map/chart-map.tsx @@ -97,13 +97,28 @@ export const ChartMapVisualization = ({ const dimension = dimensions?.find((d) => d.iri === areaDimensionIri); if (isGeoShapesDimension(dimension) && geoShapes && observations) { - const { topology } = geoShapes; + const activeFilters = chartConfig.filters[areaDimensionIri]; + const activeFiltersIris = activeFilters + ? activeFilters.type === "single" + ? [activeFilters.value] + : activeFilters.type === "multi" + ? Object.keys(activeFilters.values) + : undefined + : undefined; + const { topology } = geoShapes; const topojson = topojsonFeature( topology, topology.objects.shapes ) as AreaLayer["shapes"]; + // Completely hide unselected shapes (so they don't affect the legend, etc) + if (activeFiltersIris) { + topojson.features = topojson.features.filter((d) => + activeFiltersIris.includes(d.properties.iri) + ); + } + topojson.features.forEach((d: GeoFeature) => { // Should we match by labels? const observation = observations.find( @@ -118,7 +133,13 @@ export const ChartMapVisualization = ({ mesh: topojsonMesh(topology, topology.objects.shapes), }; } - }, [areaDimensionIri, dimensions, observations, geoShapes]); + }, [ + areaDimensionIri, + dimensions, + chartConfig.filters, + observations, + geoShapes, + ]); const symbolLayer: SymbolLayer | undefined = useMemo(() => { const dimension = dimensions?.find((d) => d.iri === symbolDimensionIri); @@ -175,7 +196,6 @@ export const ChartMapVisualization = ({ measures={measures} dimensions={dimensions} baseLayer={chartConfig.baseLayer} - geoShapes={geoShapes} /> ); } else if (fetching || !areaLayerPrepared || !symbolLayerPrepared) { @@ -194,7 +214,6 @@ export const ChartMapPrototype = ({ measures, dimensions, baseLayer, - geoShapes, }: { observations: Observation[]; features: GeoData; @@ -202,7 +221,6 @@ export const ChartMapPrototype = ({ measures: DimensionMetaDataFragment[]; dimensions: DimensionMetaDataFragment[]; baseLayer: BaseLayer; - geoShapes?: GeoShapes; }) => { return ( @@ -213,7 +231,6 @@ export const ChartMapPrototype = ({ measures={measures} dimensions={dimensions} baseLayer={baseLayer} - geoShapes={geoShapes} /> ); @@ -227,7 +244,6 @@ export const ChartMap = memo( measures, dimensions, baseLayer, - geoShapes, }: { features: GeoData; observations: Observation[]; @@ -235,7 +251,6 @@ export const ChartMap = memo( dimensions: DimensionMetaDataFragment[]; fields: MapFields; baseLayer: BaseLayer; - geoShapes?: GeoShapes; }) => { return ( diff --git a/app/charts/map/helpers.ts b/app/charts/map/helpers.ts index 7564e247f..6593bec20 100644 --- a/app/charts/map/helpers.ts +++ b/app/charts/map/helpers.ts @@ -18,13 +18,16 @@ export const getBBox = ( const visiblePoints = symbols.filter( (d) => d.properties.observation !== undefined ); - const [minLng, maxLng] = extent(visiblePoints, (d) => d.coordinates[0]); - const [minLat, maxLat] = extent(visiblePoints, (d) => d.coordinates[1]); - symbolsBbox = [ - [minLng, minLat], - [maxLng, maxLat], - ] as BBox; + if (visiblePoints.length > 0) { + const [minLng, maxLng] = extent(visiblePoints, (d) => d.coordinates[0]); + const [minLat, maxLat] = extent(visiblePoints, (d) => d.coordinates[1]); + + symbolsBbox = [ + [minLng, minLat], + [maxLng, maxLat], + ] as BBox; + } } if (shapesBbox !== undefined) { diff --git a/app/charts/map/map-state.tsx b/app/charts/map/map-state.tsx index edf64184e..c17e72345 100644 --- a/app/charts/map/map-state.tsx +++ b/app/charts/map/map-state.tsx @@ -27,13 +27,7 @@ import { MapFields, SequentialPaletteType, } from "../../configurator/config-types"; -import { - GeoData, - GeoFeature, - GeoShapes, - isGeoShapesDimension, - Observation, -} from "../../domain/data"; +import { GeoData, isGeoShapesDimension, Observation } from "../../domain/data"; import { useOptionalNumericVariable, useStringVariable, @@ -142,12 +136,10 @@ const useMapState = ({ measures, dimensions, baseLayer, - geoShapes, }: Pick & { features: GeoData; fields: MapFields; baseLayer: BaseLayer; - geoShapes?: GeoShapes; }): MapState => { const width = useWidth(); const { areaLayer, symbolLayer } = fields; @@ -171,10 +163,11 @@ const useMapState = ({ const dimension = dimensions.find((d) => d.iri === geoDimensionIri); // Right now hierarchies are only created for geoShapes - if (isGeoShapesDimension(dimension) && geoShapes) { - const hierarchyLabels = ( - (geoShapes as any).topology.objects.shapes.geometries as GeoFeature[] - ) + if ( + isGeoShapesDimension(dimension) && + features.areaLayer?.shapes?.features + ) { + const hierarchyLabels = features.areaLayer.shapes.features .filter((d) => d.properties.hierarchyLevel === hierarchyLevel) .map((d) => d.properties.label); @@ -183,7 +176,7 @@ const useMapState = ({ return data; }, - [data, dimensions, geoShapes] + [data, dimensions, features.areaLayer?.shapes.features] ); const areaData = useMemo( @@ -317,14 +310,12 @@ const MapChartProvider = ({ measures, dimensions, baseLayer, - geoShapes, children, }: Pick & { features: GeoData; children: ReactNode; fields: MapFields; baseLayer: BaseLayer; - geoShapes?: GeoShapes; }) => { const state = useMapState({ data, @@ -333,7 +324,6 @@ const MapChartProvider = ({ measures, dimensions, baseLayer, - geoShapes, }); return ( {children} @@ -347,13 +337,11 @@ export const MapChart = ({ measures, dimensions, baseLayer, - geoShapes, children, }: Pick & { features: GeoData; fields: MapFields; baseLayer: BaseLayer; - geoShapes?: GeoShapes; children: ReactNode; }) => { return ( @@ -366,7 +354,6 @@ export const MapChart = ({ fields={fields} measures={measures} dimensions={dimensions} - geoShapes={geoShapes} baseLayer={baseLayer} > {children} diff --git a/app/configurator/map/map-chart-options.tsx b/app/configurator/map/map-chart-options.tsx index a1ab95588..93fe1eeef 100644 --- a/app/configurator/map/map-chart-options.tsx +++ b/app/configurator/map/map-chart-options.tsx @@ -23,6 +23,7 @@ import { ChartOptionSelectField, ColorPickerField, } from "../components/field"; +import { DimensionValuesMultiFilter } from "../components/filters"; export const MapColumnOptions = ({ state, @@ -323,6 +324,18 @@ export const AreaLayerSettings = memo( )} + {!isHidden && ( + + Filter + + + + + )} ); } @@ -436,6 +449,16 @@ export const SymbolLayerSettings = memo( /> + + Filter + + + + ); }