Skip to content

Commit

Permalink
Merge pull request #23
Browse files Browse the repository at this point in the history
Implement scale legend
  • Loading branch information
clementprdhomme authored Nov 11, 2024
2 parents 695d668 + 17fad02 commit cea989f
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 6 deletions.
2 changes: 2 additions & 0 deletions client/src/components/map/legend/item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { LayerSettings } from "@/types/layer";
import BasicLegend from "./basic-legend";
import ChoroplethLegend from "./choropleth-legend";
import GradientLegend from "./gradient-legend";
import ScaleLegend from "./scale-legend";

interface LegendItemProps {
id: number;
Expand Down Expand Up @@ -130,6 +131,7 @@ const LegendItem = ({ id, settings, sortableAttributes, sortableListeners }: Leg
{data.type === "basic" && <BasicLegend {...data} />}
{data.type === "choropleth" && <ChoroplethLegend {...data} />}
{data.type === "gradient" && <GradientLegend {...data} />}
{data.type === "scale" && <ScaleLegend {...data} />}
</>
)}
</div>
Expand Down
113 changes: 113 additions & 0 deletions client/src/components/map/legend/item/scale-legend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { useMemo } from "react";

import useLayerLegend from "@/hooks/use-layer-legend";
import { cn } from "@/lib/utils";
import { LegendLegendConfigComponentItemsItem } from "@/types/generated/strapi.schemas";

type ScaleLegendProps = ReturnType<typeof useLayerLegend>["data"];

const ScaleLegend = (data: ScaleLegendProps) => {
const itemsByGroup = useMemo(() => {
if (!data.items || data.items.length === 0) {
return undefined;
}

return data.items.reduce(
(res, item) => ({
...res,
[item.group ?? ""]: [...(res[item.group ?? ""] ?? []), item].sort(
(itemA, itemB) => (itemB.size ?? 0) - (itemA.size ?? 0),
),
}),
{} as Record<string, LegendLegendConfigComponentItemsItem[]>,
);
}, [data.items]);

const minMaxValues = useMemo(() => {
if (!itemsByGroup) {
return undefined;
}

const minValueItems = Object.values(itemsByGroup).find(
(items) =>
items[items.length - 1]?.value !== undefined && items[items.length - 1]?.value !== null,
);
const minValue = minValueItems?.[minValueItems?.length - 1].value;

const maxValue = Object.values(itemsByGroup).find(
(items) => items[0]?.value !== undefined && items[0]?.value !== null,
)?.[0].value;

return [minValue, maxValue] as const;
}, [itemsByGroup]);

if (!itemsByGroup) {
return null;
}

return (
<div className="mb-2 mt-4 flex items-stretch justify-start gap-4">
{Object.entries(itemsByGroup).map(([key, items], index) => (
<div key={key} className="relative flex flex-col items-center gap-3.5">
<div className="text-xs">{key}</div>
{minMaxValues?.[0] !== undefined && (
<div
className={cn({
"absolute h-0 border-t border-dashed border-t-casper-blue-400": true,
"left-1/2 w-[calc(50%_+_theme(spacing.4))]": index === 0,
"left-0 w-[calc(100%_+_theme(spacing.4))]": index > 0,
})}
style={{
bottom: `${items[0]?.size ?? 0}px`,
}}
/>
)}
{minMaxValues?.[1] !== undefined && (
<div
className={cn({
"absolute -bottom-px h-0 border-t border-dashed border-t-casper-blue-400": true,
"left-1/2 w-[calc(50%_+_theme(spacing.4))]": index === 0,
"left-0 w-[calc(100%_+_theme(spacing.4))]": index > 0,
})}
/>
)}
<div
className="relative"
style={{
width: `${items[0]?.size ?? 0}px`,
height: `${items[0]?.size ?? 0}px`,
}}
>
{items.map((item) => (
<div
key={item.size ?? 0}
className="absolute bottom-0 left-1/2 -translate-x-1/2 rounded-full border border-white"
style={{
width: `${item.size ?? 0}px`,
height: `${item.size ?? 0}px`,
backgroundColor: item.color,
}}
/>
))}
</div>
</div>
))}
{!!minMaxValues && (
<div className="flex flex-col pt-5">
{minMaxValues[0] !== undefined && (
<div className="relative left-1 text-xs">
<span className="relative top-px">{minMaxValues[1]}</span>
</div>
)}
{minMaxValues[1] !== undefined && (
<div className="relative left-1 top-1.5 mt-auto text-xs">
<span className="relative top-px">{minMaxValues[0]}</span>
</div>
)}
</div>
)}
</div>
);
};

export default ScaleLegend;
9 changes: 9 additions & 0 deletions client/src/types/generated/strapi.schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1001,12 +1001,15 @@ export const LegendLegendConfigComponentType = {
basic: 'basic',
choropleth: 'choropleth',
gradient: 'gradient',
scale: 'scale',
} as const;

export type LegendLegendConfigComponentItemsItem = {
color?: string;
group?: string;
id?: number;
pattern?: string;
size?: number;
value?: string;
};

Expand Down Expand Up @@ -1225,12 +1228,15 @@ export const LayerDatasetDataAttributesLayersDataItemAttributesLegendConfigType
basic: 'basic',
choropleth: 'choropleth',
gradient: 'gradient',
scale: 'scale',
} as const;

export type LayerDatasetDataAttributesLayersDataItemAttributesLegendConfigItemsItem = {
color?: string;
group?: string;
id?: number;
pattern?: string;
size?: number;
value?: string;
};

Expand Down Expand Up @@ -1598,12 +1604,15 @@ export const DatasetLayersDataItemAttributesLegendConfigType = {
basic: 'basic',
choropleth: 'choropleth',
gradient: 'gradient',
scale: 'scale',
} as const;

export type DatasetLayersDataItemAttributesLegendConfigItemsItem = {
color?: string;
group?: string;
id?: number;
pattern?: string;
size?: number;
value?: string;
};

Expand Down
6 changes: 6 additions & 0 deletions cms/config/sync/admin-role.strapi-super-admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
"legend_config.items.color",
"legend_config.items.value",
"legend_config.items.pattern",
"legend_config.items.size",
"legend_config.items.group",
"legend_config.unit",
"dataset",
"download_link"
Expand Down Expand Up @@ -97,6 +99,8 @@
"legend_config.items.color",
"legend_config.items.value",
"legend_config.items.pattern",
"legend_config.items.size",
"legend_config.items.group",
"legend_config.unit",
"dataset",
"download_link"
Expand All @@ -118,6 +122,8 @@
"legend_config.items.color",
"legend_config.items.value",
"legend_config.items.pattern",
"legend_config.items.size",
"legend_config.items.group",
"legend_config.unit",
"dataset",
"download_link"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@
"searchable": true,
"sortable": true
}
},
"size": {
"edit": {
"label": "size",
"description": "Only for legends of type “scale”",
"placeholder": "",
"visible": true,
"editable": true
},
"list": {
"label": "size",
"searchable": true,
"sortable": true
}
},
"group": {
"edit": {
"label": "group",
"description": "Only for legends of type “scale”",
"placeholder": "",
"visible": true,
"editable": true
},
"list": {
"label": "group",
"searchable": true,
"sortable": true
}
}
},
"layouts": {
Expand All @@ -85,6 +113,16 @@
"name": "value",
"size": 6
}
],
[
{
"name": "size",
"size": 4
},
{
"name": "group",
"size": 6
}
]
]
},
Expand Down
7 changes: 7 additions & 0 deletions cms/src/components/legend/items.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
},
"pattern": {
"type": "string"
},
"size": {
"type": "integer",
"min": 0
},
"group": {
"type": "string"
}
}
}
3 changes: 2 additions & 1 deletion cms/src/components/legend/legend-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"enum": [
"basic",
"choropleth",
"gradient"
"gradient",
"scale"
],
"required": true
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"x-generation-date": "2024-11-08T08:14:51.291Z"
"x-generation-date": "2024-11-11T08:14:01.299Z"
},
"x-strapi-config": {
"path": "/documentation",
Expand Down Expand Up @@ -244,7 +244,8 @@
"enum": [
"basic",
"choropleth",
"gradient"
"gradient",
"scale"
]
},
"items": {
Expand All @@ -263,6 +264,12 @@
},
"pattern": {
"type": "string"
},
"size": {
"type": "integer"
},
"group": {
"type": "string"
}
}
}
Expand Down Expand Up @@ -1094,7 +1101,8 @@
"enum": [
"basic",
"choropleth",
"gradient"
"gradient",
"scale"
]
},
"items": {
Expand All @@ -1113,6 +1121,12 @@
},
"pattern": {
"type": "string"
},
"size": {
"type": "integer"
},
"group": {
"type": "string"
}
}
}
Expand Down Expand Up @@ -1717,7 +1731,8 @@
"enum": [
"basic",
"choropleth",
"gradient"
"gradient",
"scale"
]
},
"items": {
Expand All @@ -1736,6 +1751,12 @@
},
"pattern": {
"type": "string"
},
"size": {
"type": "integer"
},
"group": {
"type": "string"
}
}
}
Expand Down
10 changes: 9 additions & 1 deletion cms/types/generated/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface LegendLegendConfig extends Schema.Component {
description: '';
};
attributes: {
type: Attribute.Enumeration<['basic', 'choropleth', 'gradient']> &
type: Attribute.Enumeration<['basic', 'choropleth', 'gradient', 'scale']> &
Attribute.Required;
items: Attribute.Component<'legend.items', true>;
unit: Attribute.String;
Expand All @@ -24,6 +24,14 @@ export interface LegendItems extends Schema.Component {
color: Attribute.String & Attribute.Required;
value: Attribute.String;
pattern: Attribute.String;
size: Attribute.Integer &
Attribute.SetMinMax<
{
min: 0;
},
number
>;
group: Attribute.String;
};
}

Expand Down

0 comments on commit cea989f

Please sign in to comment.