Skip to content

Commit

Permalink
feat(leaflet): new config scaleIncludeUnmatchedChoropleth
Browse files Browse the repository at this point in the history
  • Loading branch information
k6sdevbob committed Jul 17, 2023
1 parent f531296 commit d6a8c20
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Fragment, forwardRef, useEffect, useMemo, useRef } from "react";
import React, { Fragment, forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from "react";
import { CircleMarker, MapContainer, Polygon, Marker, TileLayer, Tooltip } from "react-leaflet";
import { type Map, divIcon } from "leaflet";
import type { DeepReadonly, IRow, IViewField, VegaGlobalConfig } from "../../interfaces";
Expand All @@ -21,6 +21,7 @@ export interface IChoroplethRendererProps {
text: DeepReadonly<IViewField> | undefined;
details: readonly DeepReadonly<IViewField>[];
vegaConfig: VegaGlobalConfig;
scaleIncludeUnmatchedChoropleth: boolean;
}

export interface IChoroplethRendererRef {}
Expand Down Expand Up @@ -85,7 +86,9 @@ const resolveCenter = (coordinates: [lat: number, lng: number][]): [lng: number,
};

const ChoroplethRenderer = forwardRef<IChoroplethRendererRef, IChoroplethRendererProps>(function ChoroplethRenderer (props, ref) {
const { data, allFields, features, geoKey, defaultAggregated, geoId, color, opacity, text, details, vegaConfig } = props;
const { data, allFields, features, geoKey, defaultAggregated, geoId, color, opacity, text, details, vegaConfig, scaleIncludeUnmatchedChoropleth } = props;

useImperativeHandle(ref, () => ({}));

const geoIndices = useMemo(() => {
if (geoId) {
Expand All @@ -94,14 +97,19 @@ const ChoroplethRenderer = forwardRef<IChoroplethRendererRef, IChoroplethRendere
return [];
}, [geoId, data]);

const geoShapes = useMemo(() => {
const [indices, geoShapes] = useMemo<[indices: number[], geoShapes: (FeatureCollection['features'][number] | undefined)[]]>(() => {
if (geoIndices.length && geoKey && features) {
return geoIndices.map(id => {
const indices: number[] = [];
const shapes = geoIndices.map((id, i) => {
const feature = id ? features.features.find(f => f.properties?.[geoKey] === id) : undefined;
if (feature) {
indices.push(i);
}
return feature;
});
return [indices, shapes];
}
return [];
return [[], []];
}, [geoIndices, features, geoKey]);

useEffect(() => {
Expand Down Expand Up @@ -149,8 +157,15 @@ const ChoroplethRenderer = forwardRef<IChoroplethRendererRef, IChoroplethRendere
return [[[-180, -90], [180, 90]], [0, 0]];
}, [lngLat]);

const opacityScale = useOpacityScale(data, opacity, defaultAggregated);
const colorScale = useColorScale(data, color, defaultAggregated, vegaConfig);
const distribution = useMemo(() => {
if (scaleIncludeUnmatchedChoropleth) {
return data;
}
return indices.map(i => data[i]);
}, [data, indices, scaleIncludeUnmatchedChoropleth]);

const opacityScale = useOpacityScale(distribution, opacity, defaultAggregated);
const colorScale = useColorScale(distribution, color, defaultAggregated, vegaConfig);

const tooltipFields = useMemo(() => {
return details.concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const LEAFLET_DEFAULT_HEIGHT = 600;
const LeafletRenderer = forwardRef<ILeafletRendererRef, ILeafletRendererProps>(function LeafletRenderer (props, ref) {
const { draggableFieldState, data, visualConfig, vegaConfig = {} } = props;
const { latitude: [lat], longitude: [lng], geoId: [geoId], dimensions, measures, size: [size], color: [color], opacity: [opacity], text: [text], details } = draggableFieldState;
const { defaultAggregated, geoms: [markType], geojson, geoKey = '' } = visualConfig;
const { defaultAggregated, geoms: [markType], geojson, geoKey = '', scaleIncludeUnmatchedChoropleth = false } = visualConfig;
const allFields = useMemo(() => [...dimensions, ...measures], [dimensions, measures]);
const latField = useMemo(() => allFields.find((f) => f.geoRole === 'latitude'), [allFields]);
const lngField = useMemo(() => allFields.find((f) => f.geoRole === 'longitude'), [allFields]);
Expand Down Expand Up @@ -55,6 +55,7 @@ const LeafletRenderer = forwardRef<ILeafletRendererRef, ILeafletRendererProps>(f
text={text}
details={details}
vegaConfig={vegaConfig}
scaleIncludeUnmatchedChoropleth={scaleIncludeUnmatchedChoropleth}
/>
);
}
Expand Down
15 changes: 15 additions & 0 deletions packages/graphic-walker/src/components/visualConfig/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const VisualConfigPanel: React.FC = (props) => {
const { commonStore, vizStore } = useGlobalStore();
const { showVisualConfigPanel } = commonStore;
const { visualConfig } = vizStore;
const { coordSystem, geoms: [markType] } = visualConfig;
const isChoropleth = coordSystem === 'geographic' && markType === 'choropleth';
const { t } = useTranslation();
const formatConfigList: (keyof IVisualConfig['format'])[] = [
'numberFormat',
Expand All @@ -25,6 +27,7 @@ const VisualConfigPanel: React.FC = (props) => {
normalizedNumberFormat: visualConfig.format.normalizedNumberFormat,
});
const [zeroScale, setZeroScale] = useState<boolean>(visualConfig.zeroScale);
const [scaleIncludeUnmatchedChoropleth, setScaleIncludeUnmatchedChoropleth] = useState<boolean>(visualConfig.scaleIncludeUnmatchedChoropleth ?? false);

return (
<Modal
Expand Down Expand Up @@ -72,6 +75,17 @@ const VisualConfigPanel: React.FC = (props) => {
}}
/>
</div>
{isChoropleth && (
<div className="my-2">
<Toggle
label="include unmatched choropleth in scale"
enabled={scaleIncludeUnmatchedChoropleth}
onChange={(en) => {
setScaleIncludeUnmatchedChoropleth(en);
}}
/>
</div>
)}
<div className="mt-4">
<PrimaryButton
text={t('actions.confirm')}
Expand All @@ -80,6 +94,7 @@ const VisualConfigPanel: React.FC = (props) => {
runInAction(() => {
vizStore.setVisualConfig('format', format);
vizStore.setVisualConfig('zeroScale', zeroScale);
vizStore.setVisualConfig('scaleIncludeUnmatchedChoropleth', scaleIncludeUnmatchedChoropleth);
commonStore.setShowVisualConfigPanel(false);
})
}}
Expand Down
2 changes: 2 additions & 0 deletions packages/graphic-walker/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ export interface IVisualConfig {
interactiveScale: boolean;
sorted: 'none' | 'ascending' | 'descending';
zeroScale: boolean;
/** @default false */
scaleIncludeUnmatchedChoropleth?: boolean;
format: {
numberFormat?: string;
timeFormat?: string;
Expand Down
3 changes: 2 additions & 1 deletion packages/graphic-walker/src/store/visualSpecStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export function initVisualConfig(): IVisualConfig {
interactiveScale: false,
sorted: "none",
zeroScale: true,
scaleIncludeUnmatchedChoropleth: false,
size: {
mode: "auto",
width: 320,
Expand Down Expand Up @@ -373,7 +374,7 @@ export class VizSpecStore {
public setVisualConfig<K extends keyof IVisualConfig>(configKey: K, value: IVisualConfig[K]) {
this.useMutable(({ config }) => {
switch (true) {
case ["defaultAggregated", "defaultStack", "showActions", "interactiveScale"].includes(configKey): {
case ["defaultAggregated", "defaultStack", "showActions", "interactiveScale", "scaleIncludeUnmatchedChoropleth"].includes(configKey): {
return ((config as unknown as { [k: string]: boolean })[configKey] = Boolean(value));
}
case configKey === "geoms" && Array.isArray(value):
Expand Down

0 comments on commit d6a8c20

Please sign in to comment.