diff --git a/app/scripts/components/common/map/style-generators/raster-paint-layer.tsx b/app/scripts/components/common/map/style-generators/raster-paint-layer.tsx index bf5f170bf..e5aa8479d 100644 --- a/app/scripts/components/common/map/style-generators/raster-paint-layer.tsx +++ b/app/scripts/components/common/map/style-generators/raster-paint-layer.tsx @@ -13,6 +13,7 @@ interface RasterPaintLayerProps extends BaseGeneratorParams { colorMap?: string | undefined; tileParams: Record; generatorPrefix?: string; + reScale?: { min: number; max: number }; } export function RasterPaintLayer(props: RasterPaintLayerProps) { @@ -24,7 +25,8 @@ export function RasterPaintLayer(props: RasterPaintLayerProps) { hidden, opacity, colorMap, - generatorPrefix = 'raster', + reScale, + generatorPrefix = 'raster' } = props; const { updateStyle } = useMapStyle(); @@ -32,8 +34,14 @@ export function RasterPaintLayer(props: RasterPaintLayerProps) { const generatorId = `${generatorPrefix}-${id}`; const updatedTileParams = useMemo(() => { - return { ...tileParams, ...colorMap && {colormap_name: colorMap}}; - }, [tileParams, colorMap]); + return { + ...tileParams, + ...(colorMap && { + colormap_name: colorMap + }), + ...(reScale && { rescale: Object.values(reScale) }) + }; + }, [tileParams, colorMap, reScale]); // // Generate Mapbox GL layers and sources for raster timeseries @@ -47,7 +55,9 @@ export function RasterPaintLayer(props: RasterPaintLayerProps) { useEffect( () => { - const tileParamsAsString = qs.stringify(updatedTileParams, { arrayFormat: 'comma' }); + const tileParamsAsString = qs.stringify(updatedTileParams, { + arrayFormat: 'comma' + }); const zarrSource: RasterSource = { type: 'raster', @@ -63,8 +73,8 @@ export function RasterPaintLayer(props: RasterPaintLayerProps) { paint: { 'raster-opacity': hidden ? 0 : rasterOpacity, 'raster-opacity-transition': { - duration: 320, - }, + duration: 320 + } }, minzoom: minZoom, metadata: { @@ -93,7 +103,8 @@ export function RasterPaintLayer(props: RasterPaintLayerProps) { tileApiEndpoint, haveTileParamsChanged, generatorParams, - colorMap + colorMap, + reScale // generatorParams includes hidden and opacity // hidden, // opacity, 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 ccaaeb3d5..3030506ad 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,7 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { stacApiEndpoint, tileApiEndpoint, colorMap, + reScale, envApiStacEndpoint, envApiRasterEndpoint } = props; @@ -367,7 +368,8 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { { assets: 'cog_default', ...(sourceParams ?? {}), - ...(colorMap && { colormap_name: colorMap }) + ...(colorMap && { colormap_name: colorMap }), + ...(reScale && { rescale: Object.values(reScale) }) }, // Temporary solution to pass different tile parameters for hls data { @@ -495,6 +497,7 @@ export function RasterTimeseries(props: RasterTimeseriesProps) { }, [ mosaicUrl, colorMap, + reScale, points, minZoom, haveSourceParamsChanged, diff --git a/app/scripts/components/common/map/types.d.ts b/app/scripts/components/common/map/types.d.ts index 8eb8bb8c1..39af6eb5c 100644 --- a/app/scripts/components/common/map/types.d.ts +++ b/app/scripts/components/common/map/types.d.ts @@ -54,6 +54,7 @@ export interface BaseTimeseriesProps extends BaseGeneratorParams { zoomExtent?: number[]; onStatusChange?: (result: { status: ActionStatus; id: string }) => void; colorMap?: string; + reScale?: { min: number; max: number }; envApiStacEndpoint: string; envApiRasterEndpoint: string; } diff --git a/app/scripts/components/common/uswds/index.tsx b/app/scripts/components/common/uswds/index.tsx index e5410b060..fcd5abfd9 100644 --- a/app/scripts/components/common/uswds/index.tsx +++ b/app/scripts/components/common/uswds/index.tsx @@ -2,3 +2,4 @@ export { USWDSAlert } from './alert'; export { USWDSButtonGroup, USWDSButton } from './button'; export { USWDSLink } from './link'; export { USWDSBanner, USWDSBannerContent } from './banner'; +export { USWDSTextInput, USWDSTextInputMask } from './input'; \ No newline at end of file diff --git a/app/scripts/components/common/uswds/input.tsx b/app/scripts/components/common/uswds/input.tsx new file mode 100644 index 000000000..3f6385422 --- /dev/null +++ b/app/scripts/components/common/uswds/input.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { TextInput, TextInputMask } from '@trussworks/react-uswds'; + +export function USWDSTextInput(props) { + return ; +} + +export function USWDSTextInputMask(props) { + return ; +} diff --git a/app/scripts/components/exploration/atoms/hooks.ts b/app/scripts/components/exploration/atoms/hooks.ts index f6ff462c1..8cacd066b 100644 --- a/app/scripts/components/exploration/atoms/hooks.ts +++ b/app/scripts/components/exploration/atoms/hooks.ts @@ -170,3 +170,15 @@ export const useTimelineDatasetAnalysis = ( ) ); }; + +export function useTimelineDatasetColormapScale( + datasetAtom: PrimitiveAtom +) { + const colorMapScaleAtom = useMemo(() => { + return focusAtom(datasetAtom, (optic) => + optic.prop('settings').prop('scale') + ); + }, [datasetAtom]); + + return useAtom(colorMapScaleAtom); +} diff --git a/app/scripts/components/exploration/components/datasets/colormap-options.tsx b/app/scripts/components/exploration/components/datasets/colormap-options.tsx index a6ce07e21..cb76ccb22 100644 --- a/app/scripts/components/exploration/components/datasets/colormap-options.tsx +++ b/app/scripts/components/exploration/components/datasets/colormap-options.tsx @@ -1,23 +1,38 @@ import React, { useEffect, useState } from 'react'; -import { Icon } from "@trussworks/react-uswds"; +import { Icon } from '@trussworks/react-uswds'; import { CollecticonDrop } from '@devseed-ui/collecticons'; -import { sequentialColorMaps, divergingColorMaps, restColorMaps } from './colorMaps'; +import { + sequentialColorMaps, + divergingColorMaps, + restColorMaps +} from './colorMaps'; import './colormap-options.scss'; - +import { ColorRangeSlider } from './colorRangeSlider/index'; +import { colorMapScale } from '$components/exploration/types.d.ts'; export const DEFAULT_COLORMAP = 'viridis'; const CURATED_SEQUENTIAL_COLORMAPS = [ - 'viridis', 'plasma', 'inferno', 'magma', 'cividis', - 'purples', 'blues', 'reds', 'greens', 'oranges', - 'ylgnbu', 'ylgn', 'gnbu' + 'viridis', + 'plasma', + 'inferno', + 'magma', + 'cividis', + 'purples', + 'blues', + 'reds', + 'greens', + 'oranges', + 'ylgnbu', + 'ylgn', + 'gnbu' ]; -const CURATED_DIVERGING_COLORMAPS = [ - 'rdbu', 'rdylbu', 'bwr', 'coolwarm' -]; +const CURATED_DIVERGING_COLORMAPS = ['rdbu', 'rdylbu', 'bwr', 'coolwarm']; -export const classifyColormap = (colormapName: string): 'sequential' | 'diverging' | 'rest' | 'unknown' => { +export const classifyColormap = ( + colormapName: string +): 'sequential' | 'diverging' | 'rest' | 'unknown' => { const baseName = normalizeColorMap(colormapName); if (sequentialColorMaps[baseName]) { @@ -33,9 +48,16 @@ export const classifyColormap = (colormapName: string): 'sequential' | 'divergin interface ColormapOptionsProps { colorMap: string | undefined; setColorMap: (colorMap: string) => void; + min: number; + max: number; + setColorMapScale: (colorMapScale: colorMapScale) => void; + colorMapScale: colorMapScale | undefined; } -export const getColormapColors = (colormapName: string, isReversed: boolean): string[] => { +export const getColormapColors = ( + colormapName: string, + isReversed: boolean +): string[] => { const baseName = normalizeColorMap(colormapName); const colormapData = sequentialColorMaps[baseName] || @@ -49,10 +71,19 @@ export const getColormapColors = (colormapName: string, isReversed: boolean): st return `rgba(${r}, ${g}, ${b}, ${a})`; }); - return isReversed ? colors.reduceRight((acc, color) => [...acc, color], []) : colors; + return isReversed + ? colors.reduceRight((acc, color) => [...acc, color], []) + : colors; }; -export function ColormapOptions({ colorMap = DEFAULT_COLORMAP, setColorMap}: ColormapOptionsProps) { +export function ColormapOptions({ + colorMap = DEFAULT_COLORMAP, + min, + max, + setColorMap, + setColorMapScale, + colorMapScale +}: ColormapOptionsProps) { const initialIsReversed = colorMap.endsWith('_r'); const initialColorMap = normalizeColorMap(colorMap); @@ -63,9 +94,15 @@ export function ColormapOptions({ colorMap = DEFAULT_COLORMAP, setColorMap}: Col const [customColorMap, setCustomColorMap] = useState(null); useEffect(() => { - if (colormapType === 'sequential' && !CURATED_SEQUENTIAL_COLORMAPS.includes(selectedColorMap)) { + if ( + colormapType === 'sequential' && + !CURATED_SEQUENTIAL_COLORMAPS.includes(selectedColorMap) + ) { setCustomColorMap(selectedColorMap); - } else if (colormapType === 'diverging' && !CURATED_DIVERGING_COLORMAPS.includes(selectedColorMap)) { + } else if ( + colormapType === 'diverging' && + !CURATED_DIVERGING_COLORMAPS.includes(selectedColorMap) + ) { setCustomColorMap(selectedColorMap); } }, [selectedColorMap, colormapType]); @@ -74,15 +111,25 @@ export function ColormapOptions({ colorMap = DEFAULT_COLORMAP, setColorMap}: Col if (colormapType === 'sequential') { if (customColorMap) { - availableColormaps = [{ name: customColorMap }, ...CURATED_SEQUENTIAL_COLORMAPS.map(name => ({ name }))]; + availableColormaps = [ + { name: customColorMap }, + ...CURATED_SEQUENTIAL_COLORMAPS.map((name) => ({ name })) + ]; } else { - availableColormaps = CURATED_SEQUENTIAL_COLORMAPS.map(name => ({ name })); + availableColormaps = CURATED_SEQUENTIAL_COLORMAPS.map((name) => ({ + name + })); } } else if (colormapType === 'diverging') { if (customColorMap) { - availableColormaps = [{ name: customColorMap }, ...CURATED_DIVERGING_COLORMAPS.map(name => ({ name }))]; + availableColormaps = [ + { name: customColorMap }, + ...CURATED_DIVERGING_COLORMAPS.map((name) => ({ name })) + ]; } else { - availableColormaps = CURATED_DIVERGING_COLORMAPS.map(name => ({ name })); + availableColormaps = CURATED_DIVERGING_COLORMAPS.map((name) => ({ + name + })); } } else if (colormapType === 'rest') { availableColormaps = [{ name: selectedColorMap }]; @@ -105,17 +152,35 @@ export function ColormapOptions({ colorMap = DEFAULT_COLORMAP, setColorMap}: Col return (
-
Colormap options
+
+ Colormap options +
-
-
- +
+ +
+ {isReversed ? ( ) : ( )} - +
@@ -125,13 +190,21 @@ export function ColormapOptions({ colorMap = DEFAULT_COLORMAP, setColorMap}: Col return (
handleColorMapSelect(name.toLowerCase())} >