From 23abc9408ba50982bb74316a0aa4f34a1941124e Mon Sep 17 00:00:00 2001 From: Gjore Milevski Date: Wed, 13 Nov 2024 11:39:35 +0100 Subject: [PATCH 1/4] Introduce and export a VedauiConfigProvider that handles env variables --- .../components/common/blocks/block-map.tsx | 65 +++++++++----- .../common/blocks/scrollytelling/index.tsx | 89 ++++++++++++------- .../common/map/controls/geocoder.tsx | 33 ++++--- .../map/controls/map-options/basemap.ts | 61 ++++++------- .../common/map/controls/map-options/index.tsx | 9 +- .../common/map/controls/map-options/types.ts | 1 + .../components/common/map/map-component.tsx | 13 ++- .../common/map/style-generators/basemap.tsx | 19 ++-- .../style-generators/raster-timeseries.tsx | 24 +++-- .../style-generators/vector-timeseries.tsx | 36 +++----- .../map/style-generators/zarr-timeseries.tsx | 21 ++++- app/scripts/components/common/map/types.d.ts | 3 + .../components/exploration/analysis-data.ts | 12 ++- .../exploration/components/map/index.tsx | 13 +-- .../exploration/components/map/layer.tsx | 12 ++- .../hooks/use-analysis-data-request.ts | 7 +- .../hooks/use-stac-metadata-datasets.ts | 15 ++-- app/scripts/context/config-context.tsx | 27 ++++++ app/scripts/index.ts | 8 +- app/scripts/main.tsx | 14 ++- 20 files changed, 319 insertions(+), 163 deletions(-) create mode 100644 app/scripts/context/config-context.tsx diff --git a/app/scripts/components/common/blocks/block-map.tsx b/app/scripts/components/common/blocks/block-map.tsx index 5007293b9..0263c6cb0 100644 --- a/app/scripts/components/common/blocks/block-map.tsx +++ b/app/scripts/components/common/blocks/block-map.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState, useEffect } from 'react'; +import React, { useMemo, useState, useEffect, useContext } from 'react'; import styled from 'styled-components'; import { MapboxOptions } from 'mapbox-gl'; import * as dateFns from 'date-fns'; @@ -11,10 +11,7 @@ import { Basemap } from '../map/style-generators/basemap'; import { LayerLegend, LayerLegendContainer } from '../map/layer-legend'; import MapCoordsControl from '../map/controls/coords'; import MapMessage from '../map/map-message'; -import { - formatCompareDate, - formatSingleDate, -} from '../map/utils'; +import { formatCompareDate, formatSingleDate } from '../map/utils'; import { BasemapId, DEFAULT_MAP_STYLE_URL @@ -34,9 +31,13 @@ import { DatasetStatus } from '$components/exploration/types.d.ts'; -import { reconcileDatasets, getDatasetLayers } from '$components/exploration/data-utils-no-faux-module'; +import { + reconcileDatasets, + getDatasetLayers +} from '$components/exploration/data-utils-no-faux-module'; import { useReconcileWithStacMetadata } from '$components/exploration/hooks/use-stac-metadata-datasets'; import { ProjectionOptions, VedaDatum, DatasetData } from '$types/veda'; +import { VedauiConfigContext } from '$context/config-context'; export const mapHeight = '32rem'; const Carto = styled.div` @@ -125,7 +126,10 @@ interface MapBlockProps { layerId: string; } -const getDataLayer = (layerIndex: number, layers: VizDataset[] | undefined): (VizDatasetSuccess | null) => { +const getDataLayer = ( + layerIndex: number, + layers: VizDataset[] | undefined +): VizDatasetSuccess | null => { if (!layers || layers.length <= layerIndex) return null; const layer = layers[layerIndex]; // @NOTE: What to do when data returns ERROR @@ -177,16 +181,18 @@ function MapBlock(props: MapBlockProps) { totalLayers = [...totalLayers, compareMapStaticData]; } return totalLayers; - },[layerId]); + }, [layerId]); const [layers, setLayers] = useState(layersToFetch); - useReconcileWithStacMetadata(layers, setLayers); + const config = useContext(VedauiConfigContext); + + useReconcileWithStacMetadata(layers, setLayers, config.envApiStacEndpoint); - const selectedDatetime: (Date | undefined) = dateTime + const selectedDatetime: Date | undefined = dateTime ? utcString2userTzDate(dateTime) : undefined; - const selectedCompareDatetime: (Date | undefined) = compareDateTime + const selectedCompareDatetime: Date | undefined = compareDateTime ? utcString2userTzDate(compareDateTime) : undefined; @@ -210,8 +216,14 @@ function MapBlock(props: MapBlockProps) { const [, setProjection] = useState(projectionStart); - const baseDataLayer: (VizDatasetSuccess | null) = useMemo(() => getDataLayer(0, layers), [layers]); - const compareDataLayer: (VizDatasetSuccess | null) = useMemo(() => getDataLayer(1, layers), [layers]); + const baseDataLayer: VizDatasetSuccess | null = useMemo( + () => getDataLayer(0, layers), + [layers] + ); + const compareDataLayer: VizDatasetSuccess | null = useMemo( + () => getDataLayer(1, layers), + [layers] + ); const baseTimeDensity = baseDataLayer?.data.timeDensity; const compareTimeDensity = compareDataLayer?.data.timeDensity; @@ -262,9 +274,16 @@ function MapBlock(props: MapBlockProps) { if (compareLabel) return compareLabel as string; // Use label function from originalData.Compare else if (baseDataLayer?.data.compare?.mapLabel) { - if (typeof baseDataLayer.data.compare.mapLabel === 'string') return baseDataLayer.data.compare.mapLabel; - const labelFn = baseDataLayer.data.compare.mapLabel as (unknown) => string; - return labelFn({dateFns, datetime: selectedDatetime, compareDatetime: compareToDate }); + if (typeof baseDataLayer.data.compare.mapLabel === 'string') + return baseDataLayer.data.compare.mapLabel; + const labelFn = baseDataLayer.data.compare.mapLabel as ( + unknown + ) => string; + return labelFn({ + dateFns, + datetime: selectedDatetime, + compareDatetime: compareToDate + }); } // Default to date comparison. @@ -356,13 +375,13 @@ function MapBlock(props: MapBlockProps) { {compareDataLayer && ( - - )} + + )} )} diff --git a/app/scripts/components/common/blocks/scrollytelling/index.tsx b/app/scripts/components/common/blocks/scrollytelling/index.tsx index bec6264f3..5f161618e 100644 --- a/app/scripts/components/common/blocks/scrollytelling/index.tsx +++ b/app/scripts/components/common/blocks/scrollytelling/index.tsx @@ -1,6 +1,8 @@ import React, { - Children, ReactElement, + Children, + ReactElement, useCallback, + useContext, useEffect, useMemo, useRef, @@ -33,12 +35,24 @@ import { useSlidingStickyHeaderProps } from '$components/common/layout-root/useS import { HEADER_TRANSITION_DURATION } from '$utils/use-sliding-sticky-header'; import { Basemap } from '$components/common/map/style-generators/basemap'; import Map from '$components/common/map'; -import { LayerLegend, LayerLegendContainer } from '$components/common/map/layer-legend'; +import { + LayerLegend, + LayerLegendContainer +} from '$components/common/map/layer-legend'; import { Layer } from '$components/exploration/components/map/layer'; import { MapLoading } from '$components/common/loading-skeleton'; -import { DatasetData, DatasetStatus, VizDataset, VizDatasetSuccess } from '$components/exploration/types.d.ts'; +import { + DatasetData, + DatasetStatus, + VizDataset, + VizDatasetSuccess +} from '$components/exploration/types.d.ts'; import { useReconcileWithStacMetadata } from '$components/exploration/hooks/use-stac-metadata-datasets'; -import { formatSingleDate, reconcileVizDataset } from '$components/common/map/utils'; +import { + formatSingleDate, + reconcileVizDataset +} from '$components/common/map/utils'; +import { VedauiConfigContext } from '$context/config-context'; type ResolvedScrollyMapLayer = { vizDataset: VizDatasetSuccess; @@ -125,10 +139,10 @@ function getChapterLayerKey(ch: ScrollyChapter) { * * @param {array} chList List of chapters with related layers. */ -function useMapLayersFromChapters(chList: ScrollyChapter[]): [ - ResolvedScrollyMapLayer[], - string[] -] { +function useMapLayersFromChapters( + chList: ScrollyChapter[], + envApiStacEndpoint: string +): [ResolvedScrollyMapLayer[], string[]] { // The layers are unique based on the dataset, layer id and datetime. // First we filter out any scrollytelling block that doesn't have layer. const uniqueChapterLayers = useMemo(() => { @@ -141,7 +155,6 @@ function useMapLayersFromChapters(chList: ScrollyChapter[]): [ }, {}); return Object.values(unique); - }, [chList]); // Create an array of datasetId & layerId pairs which we can easily validate when creating @@ -149,31 +162,37 @@ function useMapLayersFromChapters(chList: ScrollyChapter[]): [ const uniqueLayerRefs = useMemo(() => { return uniqueChapterLayers.map(({ datasetId, layerId }) => ({ datasetId, - layerId, + layerId })); }, [uniqueChapterLayers]); // Validate that all layers are defined in the configuration. // They must be defined in the configuration otherwise it is not possible to load them. - const reconciledVizDatasets = uniqueLayerRefs.map(({ datasetId, layerId }) => { - const layers = datasets[datasetId]?.data.layers; + const reconciledVizDatasets = uniqueLayerRefs.map( + ({ datasetId, layerId }) => { + const layers = datasets[datasetId]?.data.layers; - const layer = layers?.find( - (l) => l.id === layerId - ) as DatasetData | null; + const layer = layers?.find((l) => l.id === layerId) as DatasetData | null; - if (!layer) { - throw new Error( - `Layer [${layerId}] not found in dataset [${datasetId}]` - ); - } + if (!layer) { + throw new Error( + `Layer [${layerId}] not found in dataset [${datasetId}]` + ); + } - return reconcileVizDataset(layer); - }); + return reconcileVizDataset(layer); + } + ); - const [resolvedDatasetsWithStac, setResolvedDatasetsWithStac] = useState([]); + const [resolvedDatasetsWithStac, setResolvedDatasetsWithStac] = useState< + VizDataset[] + >([]); - useReconcileWithStacMetadata(reconciledVizDatasets, setResolvedDatasetsWithStac); + useReconcileWithStacMetadata( + reconciledVizDatasets, + setResolvedDatasetsWithStac, + envApiStacEndpoint + ); // Each resolved layer will be an object with: // layer: The resolved layerData @@ -241,6 +260,8 @@ const MAP_OPTIONS = { function Scrollytelling(props) { const { children } = props; + const config = useContext(VedauiConfigContext); + const { isHeaderHidden, headerHeight, wrapperHeight } = useSlidingStickyHeaderProps(); @@ -250,13 +271,16 @@ function Scrollytelling(props) { // Extract the props from the chapters. const chapterProps = useChapterPropsFromChildren(children); - const [resolvedLayers, resolvedStatus] = - useMapLayersFromChapters(chapterProps); + const [resolvedLayers, resolvedStatus] = useMapLayersFromChapters( + chapterProps, + config.envApiStacEndpoint + ); const [activeChapter, setActiveChapter] = useState( null ); - const [projection, setProjection] = useState(projectionDefault); + const [projection, setProjection] = + useState(projectionDefault); // All layers must be loaded, resolved, and added to the map before we // initialize scrollama. This is needed because in a scrollytelling map we @@ -334,9 +358,12 @@ function Scrollytelling(props) { : // Otherwise it's the full header height. wrapperHeight; - const activeChapterLayerData = activeChapterLayer ? activeChapterLayer.vizDataset.data : null; + const activeChapterLayerData = activeChapterLayer + ? activeChapterLayer.vizDataset.data + : null; - const { description, id, name, legend, timeDensity } = activeChapterLayerData ?? {}; + const { description, id, name, legend, timeDensity } = + activeChapterLayerData ?? {}; return ( <> @@ -438,7 +465,7 @@ function Scrollytelling(props) { ...vizDataset, settings: { opacity: 100, - isVisible: !isHidden, + isVisible: !isHidden } }} selectedDay={runtimeData.datetime ?? new Date()} @@ -461,4 +488,4 @@ Scrollytelling.propTypes = { export function ScrollytellingBlock(props) { return ; -} \ No newline at end of file +} diff --git a/app/scripts/components/common/map/controls/geocoder.tsx b/app/scripts/components/common/map/controls/geocoder.tsx index 30b343030..9b645704c 100644 --- a/app/scripts/components/common/map/controls/geocoder.tsx +++ b/app/scripts/components/common/map/controls/geocoder.tsx @@ -1,26 +1,33 @@ import { useCallback } from 'react'; import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder'; - import { useControl } from 'react-map-gl'; import { getZoomFromBbox } from '$components/common/map/utils'; -export default function GeocoderControl() { - const handleGeocoderResult = useCallback((map, geocoder) => ({ result }) => { - geocoder.clear(); - geocoder._inputEl.blur(); - // Pass arbiturary number for zoom if there is no bbox - const zoom = result.bbox? getZoomFromBbox(result.bbox): 14; - map.flyTo({ - center: result.center, - zoom - }); - }, []); +export default function GeocoderControl({ + mapboxToken +}: { + mapboxToken: string; +}) { + const handleGeocoderResult = useCallback( + (map, geocoder) => + ({ result }) => { + geocoder.clear(); + geocoder._inputEl.blur(); + // Pass arbiturary number for zoom if there is no bbox + const zoom = result.bbox ? getZoomFromBbox(result.bbox) : 14; + map.flyTo({ + center: result.center, + zoom + }); + }, + [] + ); useControl( ({ map }) => { const geocoder = new MapboxGeocoder({ - accessToken: process.env.MAPBOX_TOKEN, + accessToken: mapboxToken, marker: false, collapsed: true, // Because of Mapbox issue: https://github.com/mapbox/mapbox-gl-js/issues/12565 diff --git a/app/scripts/components/common/map/controls/map-options/basemap.ts b/app/scripts/components/common/map/controls/map-options/basemap.ts index 4096e6a09..f00d51763 100644 --- a/app/scripts/components/common/map/controls/map-options/basemap.ts +++ b/app/scripts/components/common/map/controls/map-options/basemap.ts @@ -9,35 +9,36 @@ export const BASE_STYLE_PATH = 'https://api.mapbox.com/styles/v1/covid-nasa'; -export const getStyleUrl = (mapboxId: string) => - `${BASE_STYLE_PATH}/${mapboxId}?access_token=${process.env.MAPBOX_TOKEN}`; +export const getStyleUrl = (mapboxId: string, mapboxToken: string) => + `${BASE_STYLE_PATH}/${mapboxId}?access_token=${mapboxToken}`; -export const BASEMAP_STYLES = [ - { - id: 'satellite', - label: 'Satellite', - mapboxId: 'cldu1cb8f00ds01p6gi583w1m', - thumbnailUrl: `https://api.mapbox.com/styles/v1/covid-nasa/cldu1cb8f00ds01p6gi583w1m/static/-9.14,38.7,10.5,0/480x320?access_token=${process.env.MAPBOX_TOKEN}` - }, - { - id: 'dark', - label: 'Default dark', - mapboxId: 'cldu14gii006801mgq3dn1jpd', - thumbnailUrl: `https://api.mapbox.com/styles/v1/mapbox/dark-v10/static/-9.14,38.7,10.5,0/480x320?access_token=${process.env.MAPBOX_TOKEN}` - }, - { - id: 'light', - label: 'Default light', - mapboxId: 'cldu0tceb000701qnrl7p9woh', - thumbnailUrl: `https://api.mapbox.com/styles/v1/mapbox/light-v10/static/-9.14,38.7,10.5,0/480x320?access_token=${process.env.MAPBOX_TOKEN}` - }, - { - id: 'topo', - label: 'Topo', - mapboxId: 'cldu1yayu00au01qqrbdahb3m', - thumbnailUrl: `https://api.mapbox.com/styles/v1/covid-nasa/cldu1yayu00au01qqrbdahb3m/static/-9.14,38.7,10.5,0/480x320?access_token=${process.env.MAPBOX_TOKEN}` - } -] as const; +export const getBasemapStyles = (mapboxToken: string | undefined) => + [ + { + id: 'satellite', + label: 'Satellite', + mapboxId: 'cldu1cb8f00ds01p6gi583w1m', + thumbnailUrl: `https://api.mapbox.com/styles/v1/covid-nasa/cldu1cb8f00ds01p6gi583w1m/static/-9.14,38.7,10.5,0/480x320?access_token=${mapboxToken}` + }, + { + id: 'dark', + label: 'Default dark', + mapboxId: 'cldu14gii006801mgq3dn1jpd', + thumbnailUrl: `https://api.mapbox.com/styles/v1/mapbox/dark-v10/static/-9.14,38.7,10.5,0/480x320?access_token=${mapboxToken}` + }, + { + id: 'light', + label: 'Default light', + mapboxId: 'cldu0tceb000701qnrl7p9woh', + thumbnailUrl: `https://api.mapbox.com/styles/v1/mapbox/light-v10/static/-9.14,38.7,10.5,0/480x320?access_token=${mapboxToken}` + }, + { + id: 'topo', + label: 'Topo', + mapboxId: 'cldu1yayu00au01qqrbdahb3m', + thumbnailUrl: `https://api.mapbox.com/styles/v1/covid-nasa/cldu1yayu00au01qqrbdahb3m/static/-9.14,38.7,10.5,0/480x320?access_token=${mapboxToken}` + } + ] as const; export const BASEMAP_ID_DEFAULT = 'satellite'; @@ -59,8 +60,8 @@ export const GROUPS_BY_OPTION: Record = { ] }; -export type Basemap = typeof BASEMAP_STYLES[number]; +export type Basemap = ReturnType[number]; -export type BasemapId = typeof BASEMAP_STYLES[number]['id']; +export type BasemapId = Basemap['id']; export type Option = 'labels' | 'boundaries'; diff --git a/app/scripts/components/common/map/controls/map-options/index.tsx b/app/scripts/components/common/map/controls/map-options/index.tsx index 396707451..327887b7d 100644 --- a/app/scripts/components/common/map/controls/map-options/index.tsx +++ b/app/scripts/components/common/map/controls/map-options/index.tsx @@ -20,7 +20,7 @@ import { } from './projection-items'; import { MapOptionsProps } from './types'; import { projectionsList } from './projections'; -import { BASEMAP_STYLES } from './basemap'; +import { getBasemapStyles } from './basemap'; import { SelectorButton } from '$components/common/map/style/button'; @@ -110,9 +110,12 @@ function MapOptions(props: MapOptionsProps) { onBasemapStyleIdChange, labelsOption, boundariesOption, - onOptionChange + onOptionChange, + mapboxToken } = props; + const basemapStyles = getBasemapStyles(mapboxToken); + return ( ( @@ -137,7 +140,7 @@ function MapOptions(props: MapOptionsProps) { - {BASEMAP_STYLES.map((basemap) => ( + {basemapStyles.map((basemap) => (
  • void; + mapboxToken: string; } export interface ProjectionConicOptions { diff --git a/app/scripts/components/common/map/map-component.tsx b/app/scripts/components/common/map/map-component.tsx index 6891228de..3c584bd7d 100644 --- a/app/scripts/components/common/map/map-component.tsx +++ b/app/scripts/components/common/map/map-component.tsx @@ -1,4 +1,10 @@ -import React, { useCallback, ReactElement, useMemo, Ref } from 'react'; +import React, { + useCallback, + ReactElement, + useMemo, + Ref, + useContext +} from 'react'; import ReactMapGlMap, { LngLatBoundsLike, MapRef } from 'react-map-gl'; import { debounce } from 'lodash'; import useMapStyle from './hooks/use-map-style'; @@ -7,6 +13,7 @@ import { convertProjectionToMapbox } from './controls/map-options/projections'; import { ProjectionOptions } from '$types/veda'; import 'mapbox-gl/dist/mapbox-gl.css'; import 'mapbox-gl-compare/dist/mapbox-gl-compare.css'; +import { VedauiConfigContext } from '$context/config-context'; const maxMapBounds: LngLatBoundsLike = [ [-540, -90], // SW @@ -28,6 +35,8 @@ export default function MapComponent({ onMapLoad?: () => void; interactive?: boolean; }) { + const config = useContext(VedauiConfigContext); + const { initialViewState, setInitialViewState, mainId, comparedId } = useMapsContext(); const { style } = useMapStyle(); @@ -69,7 +78,7 @@ export default function MapComponent({ (undefined); + const basemapStyles = useMemo( + () => getBasemapStyles(config.mapboxToken), + [config.mapboxToken] + ); + const { data: styleJson } = useQuery( ['basemap', basemapStyleId], async ({ signal }) => { const mapboxId = basemapStyleId - ? BASEMAP_STYLES.find((b) => b.id === basemapStyleId)!.mapboxId - : BASEMAP_STYLES[0].mapboxId; + ? basemapStyles.find((b) => b.id === basemapStyleId)!.mapboxId + : basemapStyles[0].mapboxId; try { - const url = getStyleUrl(mapboxId); + const url = getStyleUrl(mapboxId, config.mapboxToken); const styleRaw = await fetch(url, { signal }); const styleJson = await styleRaw.json(); return styleJson; diff --git a/app/scripts/components/common/map/style-generators/raster-timeseries.tsx b/app/scripts/components/common/map/style-generators/raster-timeseries.tsx index 271bf74ac..ccaaeb3d5 100644 --- a/app/scripts/components/common/map/style-generators/raster-timeseries.tsx +++ b/app/scripts/components/common/map/style-generators/raster-timeseries.tsx @@ -63,6 +63,8 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { stacApiEndpoint, tileApiEndpoint, colorMap, + envApiStacEndpoint, + envApiRasterEndpoint } = props; const { current: mapInstance } = useMaps(); @@ -73,10 +75,8 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { const minZoom = zoomExtent?.[0] ?? 0; const generatorId = `raster-timeseries-${id}`; - const stacApiEndpointToUse = - stacApiEndpoint ?? process.env.API_STAC_ENDPOINT ?? ''; - const tileApiEndpointToUse = - tileApiEndpoint ?? process.env.API_RASTER_ENDPOINT ?? ''; + const stacApiEndpointToUse = stacApiEndpoint ?? envApiStacEndpoint ?? ''; + const tileApiEndpointToUse = tileApiEndpoint ?? envApiRasterEndpoint ?? ''; // Status tracking. // A raster timeseries layer has a base layer and may have markers. @@ -270,7 +270,9 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { controller }); const mosaicUrl = responseData.links[1].href; - setMosaicUrl(mosaicUrl.replace('/{tileMatrixSetId}', '/WebMercatorQuad')); + setMosaicUrl( + mosaicUrl.replace('/{tileMatrixSetId}', '/WebMercatorQuad') + ); } catch (error) { // @NOTE: conditional logic TO BE REMOVED once new BE endpoints have moved to prod... Fallback on old request url if new endpoints error with nonexistance... if (error.request) { @@ -284,10 +286,14 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { const mosaicUrl = responseData.links[1].href; setMosaicUrl(mosaicUrl); } else { - LOG && + LOG && /* eslint-disable-next-line no-console */ - console.log('Titiler /register %cEndpoint error', 'color: red;', error); - throw error; + console.log( + 'Titiler /register %cEndpoint error', + 'color: red;', + error + ); + throw error; } } @@ -361,7 +367,7 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { { assets: 'cog_default', ...(sourceParams ?? {}), - ...colorMap && {colormap_name: colorMap} + ...(colorMap && { colormap_name: colorMap }) }, // Temporary solution to pass different tile parameters for hls data { diff --git a/app/scripts/components/common/map/style-generators/vector-timeseries.tsx b/app/scripts/components/common/map/style-generators/vector-timeseries.tsx index cd2973f1e..bdc06cfe8 100644 --- a/app/scripts/components/common/map/style-generators/vector-timeseries.tsx +++ b/app/scripts/components/common/map/style-generators/vector-timeseries.tsx @@ -1,10 +1,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import qs from 'qs'; -import { - AnyLayer, - AnySourceImpl, - VectorSourceImpl -} from 'mapbox-gl'; +import { AnyLayer, AnySourceImpl, VectorSourceImpl } from 'mapbox-gl'; import { useTheme } from 'styled-components'; import endOfDay from 'date-fns/endOfDay'; import startOfDay from 'date-fns/startOfDay'; @@ -15,21 +11,14 @@ import { Feature } from 'geojson'; import { BaseGeneratorParams } from '../types'; import useMapStyle from '../hooks/use-map-style'; -import { - requestQuickCache -} from '../utils'; +import { requestQuickCache } from '../utils'; import useFitBbox from '../hooks/use-fit-bbox'; import useLayerInteraction from '../hooks/use-layer-interaction'; import { MARKER_LAYOUT } from '../hooks/use-custom-marker'; import useMaps from '../hooks/use-maps'; import useGeneratorParams from '../hooks/use-generator-params'; -import { - ActionStatus, - S_FAILED, - S_LOADING, - S_SUCCEEDED -} from '$utils/status'; +import { ActionStatus, S_FAILED, S_LOADING, S_SUCCEEDED } from '$utils/status'; import { userTzDate2utcString } from '$utils/date'; export interface VectorTimeseriesProps extends BaseGeneratorParams { @@ -42,9 +31,9 @@ export interface VectorTimeseriesProps extends BaseGeneratorParams { onStatusChange?: (result: { status: ActionStatus; id: string }) => void; isPositionSet?: boolean; stacApiEndpoint?: string; + envApiStacEndpoint: string; } - export function VectorTimeseries(props: VectorTimeseriesProps) { const { id, @@ -57,7 +46,8 @@ export function VectorTimeseries(props: VectorTimeseriesProps) { isPositionSet, hidden, opacity, - stacApiEndpoint + stacApiEndpoint, + envApiStacEndpoint } = props; const { current: mapInstance } = useMaps(); @@ -68,11 +58,10 @@ export function VectorTimeseries(props: VectorTimeseriesProps) { const [featuresBbox, setFeaturesBbox] = useState<[number, number, number, number]>(); - const [minZoom, maxZoom] = zoomExtent ?? [0, 20]; + const [minZoom, maxZoom] = zoomExtent ?? [0, 20]; const generatorId = `vector-timeseries-${id}`; - const stacApiEndpointToUse = - stacApiEndpoint ?? process.env.API_STAC_ENDPOINT ?? ''; + const stacApiEndpointToUse = stacApiEndpoint ?? envApiStacEndpoint ?? ''; // // Get the tiles url @@ -119,7 +108,6 @@ export function VectorTimeseries(props: VectorTimeseriesProps) { }; }, [id, stacCol, stacApiEndpointToUse, onStatusChange]); - // // Generate Mapbox GL layers and sources for vector timeseries // @@ -157,7 +145,7 @@ export function VectorTimeseries(props: VectorTimeseriesProps) { source: id, 'source-layer': 'default', paint: { - 'line-opacity': hidden ? 0 : vectorOpacity, + 'line-opacity': hidden ? 0 : vectorOpacity, 'line-opacity-transition': { duration: 320 }, @@ -186,7 +174,7 @@ export function VectorTimeseries(props: VectorTimeseriesProps) { source: id, 'source-layer': 'default', paint: { - 'line-opacity': hidden ? 0 : vectorOpacity, + 'line-opacity': hidden ? 0 : vectorOpacity, 'line-opacity-transition': { duration: 320 }, @@ -213,11 +201,11 @@ export function VectorTimeseries(props: VectorTimeseriesProps) { source: id, 'source-layer': 'default', paint: { - 'fill-opacity': hidden ? 0 : Math.min(vectorOpacity, 0.8), + 'fill-opacity': hidden ? 0 : Math.min(vectorOpacity, 0.8), 'fill-opacity-transition': { duration: 320 }, - 'fill-color': theme.color?.infographicB, + 'fill-color': theme.color?.infographicB }, filter: ['==', '$type', 'Polygon'], minzoom: minZoom, diff --git a/app/scripts/components/common/map/style-generators/zarr-timeseries.tsx b/app/scripts/components/common/map/style-generators/zarr-timeseries.tsx index a3bb05344..54fcaee61 100644 --- a/app/scripts/components/common/map/style-generators/zarr-timeseries.tsx +++ b/app/scripts/components/common/map/style-generators/zarr-timeseries.tsx @@ -12,14 +12,27 @@ export function ZarrTimeseries(props: BaseTimeseriesProps) { date, onStatusChange, sourceParams, + envApiStacEndpoint } = props; - const stacApiEndpointToUse = stacApiEndpoint?? process.env.API_STAC_ENDPOINT; - const assetUrl = useZarr({id, stacCol, stacApiEndpointToUse, date, onStatusChange}); + const stacApiEndpointToUse = stacApiEndpoint ?? envApiStacEndpoint; + const assetUrl = useZarr({ + id, + stacCol, + stacApiEndpointToUse, + date, + onStatusChange + }); const tileParams = { url: assetUrl, datetime: date, - ...sourceParams, + ...sourceParams }; - return ; + return ( + + ); } diff --git a/app/scripts/components/common/map/types.d.ts b/app/scripts/components/common/map/types.d.ts index 899931d39..8eb8bb8c1 100644 --- a/app/scripts/components/common/map/types.d.ts +++ b/app/scripts/components/common/map/types.d.ts @@ -54,6 +54,8 @@ export interface BaseTimeseriesProps extends BaseGeneratorParams { zoomExtent?: number[]; onStatusChange?: (result: { status: ActionStatus; id: string }) => void; colorMap?: string; + envApiStacEndpoint: string; + envApiRasterEndpoint: string; } // export interface ZarrTimeseriesProps extends BaseTimeseriesProps { @@ -63,6 +65,7 @@ export interface BaseTimeseriesProps extends BaseGeneratorParams { export interface RasterTimeseriesProps extends BaseTimeseriesProps { bounds?: number[]; isPositionSet?: boolean; + envApiStacEndpoint: string; } interface AssetUrlReplacement { diff --git a/app/scripts/components/exploration/analysis-data.ts b/app/scripts/components/exploration/analysis-data.ts index 3b6850721..5a380b5a0 100644 --- a/app/scripts/components/exploration/analysis-data.ts +++ b/app/scripts/components/exploration/analysis-data.ts @@ -61,7 +61,9 @@ async function getDatasetAssets( ); return { assets: searchReqRes.data.features.map((o) => ({ - date: utcString2userTzDate(o.properties.start_datetime || o.properties.datetime), + date: utcString2userTzDate( + o.properties.start_datetime || o.properties.datetime + ), url: o.assets[assets].href })) }; @@ -76,6 +78,8 @@ interface TimeseriesRequesterParams { queryClient: QueryClient; concurrencyManager: ConcurrencyManagerInstance; onProgress: (data: TimelineDatasetAnalysis) => void; + envApiRasterEndpoint: string; + envApiStacEndpoint: string; } /** @@ -90,6 +94,8 @@ export async function requestDatasetTimeseriesData({ dataset, queryClient, concurrencyManager, + envApiRasterEndpoint, + envApiStacEndpoint, onProgress }: TimeseriesRequesterParams): Promise { const datasetData = dataset.data; @@ -129,7 +135,7 @@ export async function requestDatasetTimeseriesData({ }); const stacApiEndpointToUse = - datasetData.stacApiEndpoint ?? process.env.API_STAC_ENDPOINT ?? ''; + datasetData.stacApiEndpoint ?? envApiStacEndpoint ?? ''; try { const layerInfoFromSTAC = await concurrencyManager.queue( @@ -200,7 +206,7 @@ export async function requestDatasetTimeseriesData({ let loaded = 0; //new Array(assets.length).fill(0); const tileEndpointToUse = - datasetData.tileApiEndpoint ?? process.env.API_RASTER_ENDPOINT ?? ''; + datasetData.tileApiEndpoint ?? envApiRasterEndpoint ?? ''; const analysisParams = datasetData.analysis?.sourceParams ?? {}; diff --git a/app/scripts/components/exploration/components/map/index.tsx b/app/scripts/components/exploration/components/map/index.tsx index c853ff7c2..b7058d369 100644 --- a/app/scripts/components/exploration/components/map/index.tsx +++ b/app/scripts/components/exploration/components/map/index.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useContext, useEffect, useState } from 'react'; import { ProjectionOptions } from 'veda'; import { useReconcileWithStacMetadata } from '../../hooks/use-stac-metadata-datasets'; @@ -26,6 +26,7 @@ import { usePreviousValue } from '$utils/use-effect-previous'; import { ExtendedStyle } from '$components/common/map/styles'; import DrawControl from '$components/common/map/controls/aoi'; import CustomAoIControl from '$components/common/map/controls/aoi/custom-aoi-control'; +import { VedauiConfigContext } from '$context/config-context'; interface ExplorationMapProps { datasets: TimelineDataset[]; @@ -35,6 +36,8 @@ interface ExplorationMapProps { } export function ExplorationMap(props: ExplorationMapProps) { + const { envApiStacEndpoint, mapboxToken } = useContext(VedauiConfigContext); + const { datasets, setDatasets, selectedDay, selectedCompareDay } = props; const [projection, setProjection] = @@ -48,7 +51,7 @@ export function ExplorationMap(props: ExplorationMapProps) { onOptionChange } = useBasemap(); - useReconcileWithStacMetadata(datasets, setDatasets); + useReconcileWithStacMetadata(datasets, setDatasets, envApiStacEndpoint); // Different datasets may have a different default projection. // When datasets are selected the first time, we set the map projection to the @@ -85,8 +88,7 @@ export function ExplorationMap(props: ExplorationMapProps) { // eslint-disable-next-line fp/no-mutating-methods const loadedDatasets = datasets .filter( - (d): d is TimelineDatasetSuccess => - d.status === DatasetStatus.SUCCESS + (d): d is TimelineDatasetSuccess => d.status === DatasetStatus.SUCCESS ) .slice() .reverse(); @@ -147,8 +149,9 @@ export function ExplorationMap(props: ExplorationMapProps) { } /> - +