feat: Map component API and docs improvements

This commit is contained in:
Demenech
2024-04-09 17:30:45 -03:00
parent 3d73ac422e
commit b859d48f17
3 changed files with 56 additions and 30 deletions

View File

@@ -2,6 +2,7 @@ import { CSSProperties, useEffect, useState } from 'react';
import LoadingSpinner from './LoadingSpinner'; import LoadingSpinner from './LoadingSpinner';
import loadData from '../lib/loadData'; import loadData from '../lib/loadData';
import chroma from 'chroma-js'; import chroma from 'chroma-js';
import { GeospatialData } from '../types/properties';
import { import {
MapContainer, MapContainer,
TileLayer, TileLayer,
@@ -14,26 +15,25 @@ import * as L from 'leaflet';
export type MapProps = { export type MapProps = {
layers: { layers: {
data: string | GeoJSON.GeoJSON; data: GeospatialData;
name: string; name: string;
colorScale?: { colorScale?: {
starting: string; starting: string;
ending: string; ending: string;
}; };
tooltip?: tooltip?:
| { | {
propNames: string[]; propNames: string[];
} }
| boolean; | boolean;
_id?: number;
}[]; }[];
title?: string; title?: string;
center?: { latitude: number | undefined; longitude: number | undefined }; center?: { latitude: number | undefined; longitude: number | undefined };
zoom?: number; zoom?: number;
style?: CSSProperties; style?: CSSProperties;
autoZoomConfiguration?: { autoZoomConfiguration?: {
layerName: string layerName: string;
} };
}; };
export function Map({ export function Map({
@@ -56,17 +56,19 @@ export function Map({
useEffect(() => { useEffect(() => {
const loadDataPromises = layers.map(async (layer) => { const loadDataPromises = layers.map(async (layer) => {
const url = layer.data.url;
const geojson = layer.data.geojson;
let layerData: any; let layerData: any;
if (typeof layer.data === 'string') { if (url) {
// If "data" is string, assume it's a URL // If "data" is string, assume it's a URL
setIsLoading(true); setIsLoading(true);
layerData = await loadData(layer.data).then((res: any) => { layerData = await loadData(url).then((res: any) => {
return JSON.parse(res); return JSON.parse(res);
}); });
} else { } else {
// Else, expect raw GeoJSON // Else, expect raw GeoJSON
layerData = layer.data; layerData = geojson;
} }
if (layer.colorScale) { if (layer.colorScale) {
@@ -111,23 +113,23 @@ export function Map({
// Create the title box // Create the title box
var info = new L.Control() as any; var info = new L.Control() as any;
info.onAdd = function() { info.onAdd = function () {
this._div = L.DomUtil.create('div', 'info'); this._div = L.DomUtil.create('div', 'info');
this.update(); this.update();
return this._div; return this._div;
}; };
info.update = function() { info.update = function () {
this._div.innerHTML = `<h4 style="font-weight: 600; background: #f9f9f9; padding: 5px; border-radius: 5px; color: #464646;">${title}</h4>`; this._div.innerHTML = `<h4 style="font-weight: 600; background: #f9f9f9; padding: 5px; border-radius: 5px; color: #464646;">${title}</h4>`;
}; };
if (title) info.addTo(map.target); if (title) info.addTo(map.target);
if(!autoZoomConfiguration) return; if (!autoZoomConfiguration) return;
let layerToZoomBounds = L.latLngBounds(L.latLng(0, 0), L.latLng(0, 0)); let layerToZoomBounds = L.latLngBounds(L.latLng(0, 0), L.latLng(0, 0));
layers.forEach((layer) => { layers.forEach((layer) => {
if(layer.name === autoZoomConfiguration.layerName) { if (layer.name === autoZoomConfiguration.layerName) {
const data = layersData.find( const data = layersData.find(
(layerData) => layerData.name === layer.name (layerData) => layerData.name === layer.name
)?.data; )?.data;

View File

@@ -4,8 +4,15 @@
* Based on vega. * Based on vega.
* *
*/ */
type URL = string; // Just in case we want to transform it into an object with configurations
export interface Data { export interface Data {
url?: string; url?: URL;
values?: { [key: string]: number | string }[]; values?: { [key: string]: number | string }[];
csv?: string; csv?: string;
} }
export interface GeospatialData {
url?: URL;
geojson?: GeoJSON.GeoJSON;
}

View File

@@ -10,7 +10,11 @@ const meta: Meta = {
argTypes: { argTypes: {
layers: { layers: {
description: description:
'Data to be displayed.\n\n GeoJSON Object \n\nOR\n\n URL to GeoJSON Object', 'Array of layers to be displayed on the map. Should be an object with: \n\n \
`data`: object with either a `url` property pointing to a GeoJSON file or a `geojson` property with a GeoJSON object. \n\n \
`name`: name of the layer. \n\n \
`colorscale`: object with a `starting` and `ending` colors that will be used to create a gradient and color the map. \n\n \
`tooltip`: `true` to show all available features on the tooltip, object with a `propNames` property as an array of strings to choose which features to display. \n\n',
}, },
title: { title: {
description: 'Title to display on the map.', description: 'Title to display on the map.',
@@ -19,14 +23,15 @@ const meta: Meta = {
description: 'Initial coordinates of the center of the map', description: 'Initial coordinates of the center of the map',
}, },
zoom: { zoom: {
description: 'Zoom level', description: 'Initial zoom level',
}, },
style: { style: {
description: "Styles for the container" description: "CSS styles to be applied to the map's container.",
}, },
autoZoomConfiguration: { autoZoomConfiguration: {
description: "Configuration to auto zoom in the specified layer data" description:
} "Pass a layer's name to automatically zoom to the bounding area of a layer.",
},
}, },
}; };
@@ -40,7 +45,9 @@ export const GeoJSONPolygons: Story = {
args: { args: {
layers: [ layers: [
{ {
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson', data: {
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
},
name: 'Polygons', name: 'Polygons',
tooltip: { propNames: ['name'] }, tooltip: { propNames: ['name'] },
colorScale: { colorScale: {
@@ -60,7 +67,9 @@ export const GeoJSONPoints: Story = {
args: { args: {
layers: [ layers: [
{ {
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson', data: {
url: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
},
name: 'Points', name: 'Points',
tooltip: { propNames: ['Location'] }, tooltip: { propNames: ['Location'] },
}, },
@@ -76,12 +85,16 @@ export const GeoJSONMultipleLayers: Story = {
args: { args: {
layers: [ layers: [
{ {
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson', data: {
url: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
},
name: 'Points', name: 'Points',
tooltip: true, tooltip: true,
}, },
{ {
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson', data: {
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
},
name: 'Polygons', name: 'Polygons',
tooltip: true, tooltip: true,
colorScale: { colorScale: {
@@ -94,19 +107,23 @@ export const GeoJSONMultipleLayers: Story = {
center: { latitude: 45, longitude: 0 }, center: { latitude: 45, longitude: 0 },
zoom: 2, zoom: 2,
}, },
} };
export const GeoJSONMultipleLayersWithAutoZoomInSpecifiedLayer: Story = { export const GeoJSONMultipleLayersWithAutoZoomInSpecifiedLayer: Story = {
name: 'GeoJSON polygons and points map with auto zoom in the points layer', name: 'GeoJSON polygons and points map with auto zoom in the points layer',
args: { args: {
layers: [ layers: [
{ {
data: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson', data: {
url: 'https://opendata.arcgis.com/datasets/9c58741995174fbcb017cf46c8a42f4b_25.geojson',
},
name: 'Points', name: 'Points',
tooltip: true, tooltip: true,
}, },
{ {
data: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson', data: {
url: 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_marine_polys.geojson',
},
name: 'Polygons', name: 'Polygons',
tooltip: true, tooltip: true,
colorScale: { colorScale: {
@@ -119,7 +136,7 @@ export const GeoJSONMultipleLayersWithAutoZoomInSpecifiedLayer: Story = {
center: { latitude: 45, longitude: 0 }, center: { latitude: 45, longitude: 0 },
zoom: 2, zoom: 2,
autoZoomConfiguration: { autoZoomConfiguration: {
layerName: 'Points' layerName: 'Points',
} },
}, },
}; };