From d5b1c8c9d764aa0677041f317a0709ae3f746afc Mon Sep 17 00:00:00 2001 From: Slesa Adhikari Date: Wed, 3 Dec 2025 16:40:00 -0600 Subject: [PATCH 01/13] Update LayoutProps in container rather than in embedded-exploration --- .../components/exploration/container.tsx | 58 ++++++++++--------- .../exploration/embed-exploration.tsx | 9 --- app/scripts/libs/index.ts | 1 + app/scripts/libs/page-components.ts | 1 + 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/app/scripts/components/exploration/container.tsx b/app/scripts/components/exploration/container.tsx index b3df56f19..623e28cda 100644 --- a/app/scripts/components/exploration/container.tsx +++ b/app/scripts/components/exploration/container.tsx @@ -38,9 +38,6 @@ export default function ExplorationAndAnalysisContainer() { if (!currentUrl.pathname?.includes(EXPLORATION_PATH)) return null; - if (isEmbedded) { - return ; - } const openModal = () => setDatasetModalRevealed(true); const closeModal = () => setDatasetModalRevealed(false); @@ -51,32 +48,41 @@ export default function ExplorationAndAnalysisContainer() { title='Exploration' description='Explore and analyze datasets' hideFooter + {...(isEmbedded && { hideNav: true, hideHeader: true })} /> - - -

There are no datasets to show with the selected filters.

-

- This tool allows the exploration and analysis of time-series - datasets in raster format. For a comprehensive list of available - datasets, please visit the{' '} - Data Catalog. -

- - } - /> + {isEmbedded ? ( + + ) : ( + <> + + +

+ There are no datasets to show with the selected filters. +

+

+ This tool allows the exploration and analysis of time-series + datasets in raster format. For a comprehensive list of + available datasets, please visit the{' '} + Data Catalog. +

+ + } + /> + + )}
); diff --git a/app/scripts/components/exploration/embed-exploration.tsx b/app/scripts/components/exploration/embed-exploration.tsx index ec9579b23..6be3b1705 100644 --- a/app/scripts/components/exploration/embed-exploration.tsx +++ b/app/scripts/components/exploration/embed-exploration.tsx @@ -20,7 +20,6 @@ import { import { useReconcileWithStacMetadata } from '$components/exploration/hooks/use-stac-metadata-datasets'; import { ProjectionOptions, TimeDensity } from '$types/veda'; import { useVedaUI } from '$context/veda-ui-provider'; -import { LayoutProps } from '$components/common/layout-root'; const Carto = styled.div` position: relative; @@ -56,14 +55,6 @@ export default function EmbeddedExploration(props: EmbeddedExplorationProps) { const [center] = useAtom(centerAtom); return ( <> - - Date: Wed, 3 Dec 2025 16:47:24 -0600 Subject: [PATCH 02/13] Fix datepicker tooltip content --- .../components/embed-exploration/embed-timeline.tsx | 4 +++- app/scripts/components/exploration/embed-exploration.tsx | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/scripts/components/exploration/components/embed-exploration/embed-timeline.tsx b/app/scripts/components/exploration/components/embed-exploration/embed-timeline.tsx index 59831bd78..d197bc296 100644 --- a/app/scripts/components/exploration/components/embed-exploration/embed-timeline.tsx +++ b/app/scripts/components/exploration/components/embed-exploration/embed-timeline.tsx @@ -28,10 +28,11 @@ interface EmbedTimelineProps { timeDensity: TimeDensity; datasets: TimelineDataset[]; label: string; + tipContent?: string; } function EmbedTimeline(props: EmbedTimelineProps) { - const { date, setDate, timeDensity, datasets, label } = props; + const { date, setDate, timeDensity, datasets, label, tipContent } = props; const lowestCommonTimeDensity = useMemo( () => @@ -85,6 +86,7 @@ function EmbedTimeline(props: EmbedTimelineProps) { minDate={minMaxTemporalExtent[0]} maxDate={minMaxTemporalExtent[1]} selectedDay={date} + tipContent={tipContent} onConfirm={(d) => { if (!d) return; setDate(new Date(d)); diff --git a/app/scripts/components/exploration/embed-exploration.tsx b/app/scripts/components/exploration/embed-exploration.tsx index 6be3b1705..628f7f38d 100644 --- a/app/scripts/components/exploration/embed-exploration.tsx +++ b/app/scripts/components/exploration/embed-exploration.tsx @@ -189,6 +189,11 @@ function EmbeddedLayersExploration(props: EmbeddedLayersExplorationProps) { setDate={setSelectedDay} datasets={layers as TimelineDataset[]} timeDensity={baseTimeDensity} + tipContent={ + selectedCompareDay + ? 'Date shown on left map' + : 'Date shown on map' + } /> )} @@ -200,6 +205,7 @@ function EmbeddedLayersExploration(props: EmbeddedLayersExplorationProps) { setDate={setSelectedComparedDay} datasets={layers as TimelineDataset[]} timeDensity={compareTimeDensity} + tipContent='Date shown on right map' /> )} From 2d87fdb0df30d57fc8535af66398d8d62fadf9ac Mon Sep 17 00:00:00 2001 From: Slesa Adhikari Date: Wed, 3 Dec 2025 16:50:41 -0600 Subject: [PATCH 03/13] Move embed-exploration to embed-exploration folder --- .../embed-exploration}/embed-exploration.tsx | 12 ++++++------ app/scripts/components/exploration/container.tsx | 2 +- app/scripts/libs/page-components.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) rename app/scripts/components/exploration/{ => components/embed-exploration}/embed-exploration.tsx (94%) diff --git a/app/scripts/components/exploration/embed-exploration.tsx b/app/scripts/components/exploration/components/embed-exploration/embed-exploration.tsx similarity index 94% rename from app/scripts/components/exploration/embed-exploration.tsx rename to app/scripts/components/exploration/components/embed-exploration/embed-exploration.tsx index 628f7f38d..201bde58a 100644 --- a/app/scripts/components/exploration/embed-exploration.tsx +++ b/app/scripts/components/exploration/components/embed-exploration/embed-exploration.tsx @@ -4,12 +4,12 @@ import { useAtom } from 'jotai'; import { convertProjectionToMapbox, projectionDefault -} from '../common/map/controls/map-options/projections'; -import { BasemapId } from '../common/map/controls/map-options/basemap'; -import { selectedCompareDateAtom, selectedDateAtom } from './atoms/dates'; -import { zoomAtom } from './atoms/zoom'; -import { centerAtom } from './atoms/center'; -import EmbedTimeline from './components/embed-exploration/embed-timeline'; +} from '../../../common/map/controls/map-options/projections'; +import { BasemapId } from '../../../common/map/controls/map-options/basemap'; +import { selectedCompareDateAtom, selectedDateAtom } from '../../atoms/dates'; +import { zoomAtom } from '../../atoms/zoom'; +import { centerAtom } from '../../atoms/center'; +import EmbedTimeline from './embed-timeline'; import MapBlock from '$components/common/blocks/block-map'; import { VizDataset, diff --git a/app/scripts/components/exploration/container.tsx b/app/scripts/components/exploration/container.tsx index 623e28cda..52519a796 100644 --- a/app/scripts/components/exploration/container.tsx +++ b/app/scripts/components/exploration/container.tsx @@ -7,7 +7,7 @@ import { DatasetSelectorModal } from './components/dataset-selector-modal'; import useTimelineDatasetAtom from './hooks/use-timeline-dataset-atom'; import { externalDatasetsAtom } from './atoms/datasetLayers'; import { isEmbeddedAtom } from './atoms/embed'; -import EmbeddedExploration from './embed-exploration'; +import EmbeddedExploration from './components/embed-exploration/embed-exploration'; import ExplorationAndAnalysis from '.'; import { allExploreDatasets } from '$data-layer/datasets'; import { urlAtom } from '$utils/params-location-atom/url'; diff --git a/app/scripts/libs/page-components.ts b/app/scripts/libs/page-components.ts index 33b71199a..a5889b686 100644 --- a/app/scripts/libs/page-components.ts +++ b/app/scripts/libs/page-components.ts @@ -1,6 +1,6 @@ export { default as CatalogContent } from '$components/common/catalog/catalog-content'; export { default as ExplorationAndAnalysis } from '$components/exploration'; -export { default as EmbeddedExploration } from '$components/exploration/embed-exploration'; +export { default as EmbeddedExploration } from '$components/exploration/components/embed-exploration/embed-exploration'; // DataSelectorModal needs to be paried with E&A, so putting this for now. export { DatasetSelectorModal } from '$components/exploration/components/dataset-selector-modal'; export { default as StoriesHubContent } from '$components/stories/hub/hub-content'; From 7996f18801952f321ea6c36e00e0a335ef94ff13 Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Mon, 8 Dec 2025 14:47:03 -0800 Subject: [PATCH 04/13] rename embed atom to viewMode --- .../components/exploration/atoms/embed.ts | 20 ------------------- .../components/exploration/atoms/viewMode.ts | 20 +++++++++++++++++++ .../components/exploration/container.tsx | 8 ++++---- 3 files changed, 24 insertions(+), 24 deletions(-) delete mode 100644 app/scripts/components/exploration/atoms/embed.ts create mode 100644 app/scripts/components/exploration/atoms/viewMode.ts diff --git a/app/scripts/components/exploration/atoms/embed.ts b/app/scripts/components/exploration/atoms/embed.ts deleted file mode 100644 index b1873c366..000000000 --- a/app/scripts/components/exploration/atoms/embed.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { atomWithUrlValueStability } from '$utils/params-location-atom/atom-with-url-value-stability'; - -const initialParams = new URLSearchParams(window.location.search); - -const hydrateBoolean = (serialized: string | null) => { - return serialized === 'true'; -}; - -const dehydrateBoolean = (value: boolean) => { - // Only add the param to the URL if it's true. - return value ? 'true' : ''; -}; - -export const isEmbeddedAtom = atomWithUrlValueStability({ - initialValue: hydrateBoolean(initialParams.get('embed')), - urlParam: 'embed', - hydrate: hydrateBoolean, - dehydrate: dehydrateBoolean, - areEqual: (prev, next) => prev === next -}); diff --git a/app/scripts/components/exploration/atoms/viewMode.ts b/app/scripts/components/exploration/atoms/viewMode.ts new file mode 100644 index 000000000..5f4e2e48a --- /dev/null +++ b/app/scripts/components/exploration/atoms/viewMode.ts @@ -0,0 +1,20 @@ +import { atomWithUrlValueStability } from '$utils/params-location-atom/atom-with-url-value-stability'; + +const initialParams = new URLSearchParams(window.location.search); + +const hydrateViewMode = (serialized: string | null) => { + if (serialized === 'simple') return serialized; + return 'default'; +}; + +const dehydrateViewMode = (value: 'simple' | 'default') => { + return value ?? 'default'; +}; + +export const viewModeAtom = atomWithUrlValueStability<'simple' | 'default'>({ + initialValue: hydrateViewMode(initialParams.get('viewMode')), + urlParam: 'viewMode', + hydrate: hydrateViewMode, + dehydrate: dehydrateViewMode, + areEqual: (prev, next) => prev === next +}); diff --git a/app/scripts/components/exploration/container.tsx b/app/scripts/components/exploration/container.tsx index 52519a796..a263d8346 100644 --- a/app/scripts/components/exploration/container.tsx +++ b/app/scripts/components/exploration/container.tsx @@ -6,7 +6,7 @@ import { useAtom, useSetAtom } from 'jotai'; import { DatasetSelectorModal } from './components/dataset-selector-modal'; import useTimelineDatasetAtom from './hooks/use-timeline-dataset-atom'; import { externalDatasetsAtom } from './atoms/datasetLayers'; -import { isEmbeddedAtom } from './atoms/embed'; +import { viewModeAtom } from './atoms/viewMode'; import EmbeddedExploration from './components/embed-exploration/embed-exploration'; import ExplorationAndAnalysis from '.'; import { allExploreDatasets } from '$data-layer/datasets'; @@ -34,7 +34,7 @@ export default function ExplorationAndAnalysisContainer() { // atomWithLocation gets initialized outside of Exploration page and returns the previous page's value // We check if url Atom actually returns the values for exploration page here. const [currentUrl] = useAtom(urlAtom); - const [isEmbedded] = useAtom(isEmbeddedAtom); + const [viewMode] = useAtom(viewModeAtom); if (!currentUrl.pathname?.includes(EXPLORATION_PATH)) return null; @@ -48,11 +48,11 @@ export default function ExplorationAndAnalysisContainer() { title='Exploration' description='Explore and analyze datasets' hideFooter - {...(isEmbedded && { hideNav: true, hideHeader: true })} + {...(viewMode === 'simple' && { hideNav: true, hideHeader: true })} /> - {isEmbedded ? ( + {viewMode === 'simple' ? ( ) : ( <> From 2a55e40bbec83bce7b4a4f4c426531741aa489ed Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Mon, 8 Dec 2025 14:59:20 -0800 Subject: [PATCH 05/13] rename embed mode components to simple view --- .../exploration-simple-view.tsx} | 12 +++++++----- .../timeline-simple-view.tsx} | 6 +++--- app/scripts/components/exploration/container.tsx | 4 ++-- app/scripts/libs/index.ts | 2 +- app/scripts/libs/page-components.ts | 2 +- 5 files changed, 14 insertions(+), 12 deletions(-) rename app/scripts/components/exploration/components/{embed-exploration/embed-exploration.tsx => exploration-simple-view/exploration-simple-view.tsx} (96%) rename app/scripts/components/exploration/components/{embed-exploration/embed-timeline.tsx => exploration-simple-view/timeline-simple-view.tsx} (95%) diff --git a/app/scripts/components/exploration/components/embed-exploration/embed-exploration.tsx b/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx similarity index 96% rename from app/scripts/components/exploration/components/embed-exploration/embed-exploration.tsx rename to app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx index 201bde58a..1fc119333 100644 --- a/app/scripts/components/exploration/components/embed-exploration/embed-exploration.tsx +++ b/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx @@ -9,7 +9,7 @@ import { BasemapId } from '../../../common/map/controls/map-options/basemap'; import { selectedCompareDateAtom, selectedDateAtom } from '../../atoms/dates'; import { zoomAtom } from '../../atoms/zoom'; import { centerAtom } from '../../atoms/center'; -import EmbedTimeline from './embed-timeline'; +import TimelineSimpleView from './timeline-simple-view'; import MapBlock from '$components/common/blocks/block-map'; import { VizDataset, @@ -42,10 +42,12 @@ const CompareTimelineContainer = styled.div` z-index: 10; `; -interface EmbeddedExplorationProps { +interface ExplorationSimpleViewProps { datasets: TimelineDataset[]; } -export default function EmbeddedExploration(props: EmbeddedExplorationProps) { +export default function ExplorationSimpleView( + props: ExplorationSimpleViewProps +) { const { datasets } = props; const [selectedDay, setSelectedDay] = useAtom(selectedDateAtom); const [selectedCompareDay, setSelectedComparedDay] = useAtom( @@ -183,7 +185,7 @@ function EmbeddedLayersExploration(props: EmbeddedLayersExplorationProps) { /> {selectedDay && ( - {selectedCompareDay && ( - void; timeDensity: TimeDensity; @@ -31,7 +31,7 @@ interface EmbedTimelineProps { tipContent?: string; } -function EmbedTimeline(props: EmbedTimelineProps) { +function TimelineSimpleView(props: TimelineSimpleViewProps) { const { date, setDate, timeDensity, datasets, label, tipContent } = props; const lowestCommonTimeDensity = useMemo( @@ -100,4 +100,4 @@ function EmbedTimeline(props: EmbedTimelineProps) { ); } -export default EmbedTimeline; +export default TimelineSimpleView; diff --git a/app/scripts/components/exploration/container.tsx b/app/scripts/components/exploration/container.tsx index a263d8346..de1bba5eb 100644 --- a/app/scripts/components/exploration/container.tsx +++ b/app/scripts/components/exploration/container.tsx @@ -7,7 +7,7 @@ import { DatasetSelectorModal } from './components/dataset-selector-modal'; import useTimelineDatasetAtom from './hooks/use-timeline-dataset-atom'; import { externalDatasetsAtom } from './atoms/datasetLayers'; import { viewModeAtom } from './atoms/viewMode'; -import EmbeddedExploration from './components/embed-exploration/embed-exploration'; +import ExplorationSimpleView from './components/exploration-simple-view/exploration-simple-view'; import ExplorationAndAnalysis from '.'; import { allExploreDatasets } from '$data-layer/datasets'; import { urlAtom } from '$utils/params-location-atom/url'; @@ -53,7 +53,7 @@ export default function ExplorationAndAnalysisContainer() { {viewMode === 'simple' ? ( - + ) : ( <> Date: Mon, 8 Dec 2025 15:08:37 -0800 Subject: [PATCH 06/13] more renaming --- .../exploration-simple-view.tsx | 43 +++++++++---------- app/scripts/libs/index.ts | 2 +- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx b/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx index 1fc119333..eabc4629c 100644 --- a/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx +++ b/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx @@ -21,20 +21,20 @@ import { useReconcileWithStacMetadata } from '$components/exploration/hooks/use- import { ProjectionOptions, TimeDensity } from '$types/veda'; import { useVedaUI } from '$context/veda-ui-provider'; -const Carto = styled.div` +const StyledDiv = styled.div` position: relative; flex-grow: 1; height: 100vh; display: flex; `; -const BaseTimelineContainer = styled.div<{ isCompareMode?: boolean }>` +const StyledDivTimelineContainer = styled.div<{ isCompareMode?: boolean }>` position: absolute; bottom: 2rem; left: ${({ isCompareMode }) => (isCompareMode ? '25%' : '50%')}; transform: translateX(-50%); z-index: 10; `; -const CompareTimelineContainer = styled.div` +const StyledDivCompareTimelineContainer = styled.div` position: absolute; bottom: 2rem; left: 75%; @@ -56,21 +56,20 @@ export default function ExplorationSimpleView( const [zoom] = useAtom(zoomAtom); const [center] = useAtom(centerAtom); return ( - <> - - + // eslint-disable-next-line react/jsx-pascal-case + ); } -interface EmbeddedLayersExplorationProps { +interface ExplorationSimpleViewProps_ { datasets: TimelineDataset[]; setSelectedDay: (x: Date) => void; setSelectedComparedDay: (x: Date) => void; @@ -101,7 +100,7 @@ const getDataLayer = ( }; }; -function EmbeddedLayersExploration(props: EmbeddedLayersExplorationProps) { +function ExplorationSimpleView_(props: ExplorationSimpleViewProps_) { const { datasets, selectedDay, @@ -166,7 +165,7 @@ function EmbeddedLayersExploration(props: EmbeddedLayersExplorationProps) { }, [basemapId]); return ( - + - + {selectedDay && ( )} - - + + {selectedCompareDay && ( )} - - + + ); } diff --git a/app/scripts/libs/index.ts b/app/scripts/libs/index.ts index a2dfa6fb9..2c628856e 100644 --- a/app/scripts/libs/index.ts +++ b/app/scripts/libs/index.ts @@ -56,7 +56,7 @@ export { export { CatalogContent, - ExplorationSimpleView as EmbeddedExploration, + ExplorationSimpleView, ExplorationAndAnalysis, StoriesHubContent, DatasetSelectorModal From f1940b4a9592616b759ca355ce0d9ad877a76e02 Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Tue, 9 Dec 2025 07:32:34 -0800 Subject: [PATCH 07/13] make viewmode type --- app/scripts/components/exploration/atoms/viewMode.ts | 5 +++-- app/scripts/components/exploration/types.d.ts.ts | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/scripts/components/exploration/atoms/viewMode.ts b/app/scripts/components/exploration/atoms/viewMode.ts index 5f4e2e48a..28f7cc8b8 100644 --- a/app/scripts/components/exploration/atoms/viewMode.ts +++ b/app/scripts/components/exploration/atoms/viewMode.ts @@ -1,3 +1,4 @@ +import { ViewMode } from '$components/exploration/types.d.ts'; import { atomWithUrlValueStability } from '$utils/params-location-atom/atom-with-url-value-stability'; const initialParams = new URLSearchParams(window.location.search); @@ -7,11 +8,11 @@ const hydrateViewMode = (serialized: string | null) => { return 'default'; }; -const dehydrateViewMode = (value: 'simple' | 'default') => { +const dehydrateViewMode = (value: ViewMode) => { return value ?? 'default'; }; -export const viewModeAtom = atomWithUrlValueStability<'simple' | 'default'>({ +export const viewModeAtom = atomWithUrlValueStability({ initialValue: hydrateViewMode(initialParams.get('viewMode')), urlParam: 'viewMode', hydrate: hydrateViewMode, diff --git a/app/scripts/components/exploration/types.d.ts.ts b/app/scripts/components/exploration/types.d.ts.ts index 5aacb23f3..6e2ce4eba 100644 --- a/app/scripts/components/exploration/types.d.ts.ts +++ b/app/scripts/components/exploration/types.d.ts.ts @@ -194,3 +194,5 @@ export interface ZoomTransformPlain { y: number; k: number; } + +export type ViewMode = 'simple' | 'default'; From 438ecc282ad8dcf611d05caa9cb1c7002e308970 Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Tue, 9 Dec 2025 07:42:39 -0800 Subject: [PATCH 08/13] PR feedback - https://github.com/NASA-IMPACT/veda-ui/pull/1950#discussion_r2602983743 --- .../exploration-simple-view.tsx | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx b/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx index eabc4629c..14a600e45 100644 --- a/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx +++ b/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx @@ -21,20 +21,20 @@ import { useReconcileWithStacMetadata } from '$components/exploration/hooks/use- import { ProjectionOptions, TimeDensity } from '$types/veda'; import { useVedaUI } from '$context/veda-ui-provider'; -const StyledDiv = styled.div` +const StyledContainer = styled.div` position: relative; flex-grow: 1; height: 100vh; display: flex; `; -const StyledDivTimelineContainer = styled.div<{ isCompareMode?: boolean }>` +const StyledTimelineContainer = styled.div<{ isCompareMode?: boolean }>` position: absolute; bottom: 2rem; left: ${({ isCompareMode }) => (isCompareMode ? '25%' : '50%')}; transform: translateX(-50%); z-index: 10; `; -const StyledDivCompareTimelineContainer = styled.div` +const StyledCompareTimelineContainer = styled.div` position: absolute; bottom: 2rem; left: 75%; @@ -57,7 +57,7 @@ export default function ExplorationSimpleView( const [center] = useAtom(centerAtom); return ( // eslint-disable-next-line react/jsx-pascal-case - void; setSelectedComparedDay: (x: Date) => void; @@ -100,7 +100,9 @@ const getDataLayer = ( }; }; -function ExplorationSimpleView_(props: ExplorationSimpleViewProps_) { +function ExplorationSimpleViewContent( + props: ExplorationSimpleViewContentProps +) { const { datasets, selectedDay, @@ -165,7 +167,7 @@ function ExplorationSimpleView_(props: ExplorationSimpleViewProps_) { }, [basemapId]); return ( - + - + {selectedDay && ( )} - - + + {selectedCompareDay && ( )} - - + + ); } From 832109b33e0da4f938bc91f8c99bb56068303f55 Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Tue, 9 Dec 2025 08:26:26 -0800 Subject: [PATCH 09/13] PR feedback - https://github.com/NASA-IMPACT/veda-ui/pull/1950#pullrequestreview-3557847487 --- .../components/exploration/container.tsx | 89 -------- app/scripts/components/exploration/index.tsx | 205 +++++++----------- .../exploration/views/default/index.tsx | 148 +++++++++++++ .../simple/index.tsx} | 15 +- .../simple}/timeline-simple-view.tsx | 9 +- app/scripts/libs/page-components.ts | 4 +- app/scripts/main.tsx | 4 +- 7 files changed, 242 insertions(+), 232 deletions(-) delete mode 100644 app/scripts/components/exploration/container.tsx create mode 100644 app/scripts/components/exploration/views/default/index.tsx rename app/scripts/components/exploration/{components/exploration-simple-view/exploration-simple-view.tsx => views/simple/index.tsx} (92%) rename app/scripts/components/exploration/{components/exploration-simple-view => views/simple}/timeline-simple-view.tsx (92%) diff --git a/app/scripts/components/exploration/container.tsx b/app/scripts/components/exploration/container.tsx deleted file mode 100644 index de1bba5eb..000000000 --- a/app/scripts/components/exploration/container.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React, { useState } from 'react'; -import { Link } from 'react-router-dom'; -import { DevTools } from 'jotai-devtools'; -import { useAtom, useSetAtom } from 'jotai'; - -import { DatasetSelectorModal } from './components/dataset-selector-modal'; -import useTimelineDatasetAtom from './hooks/use-timeline-dataset-atom'; -import { externalDatasetsAtom } from './atoms/datasetLayers'; -import { viewModeAtom } from './atoms/viewMode'; -import ExplorationSimpleView from './components/exploration-simple-view/exploration-simple-view'; -import ExplorationAndAnalysis from '.'; -import { allExploreDatasets } from '$data-layer/datasets'; -import { urlAtom } from '$utils/params-location-atom/url'; -import { PageMainContent } from '$styles/page'; -import { LayoutProps } from '$components/common/layout-root'; -import PageHero from '$components/common/page-hero'; -import { DATASETS_PATH, EXPLORATION_PATH } from '$utils/routes'; - -/** - * @LEGACY-SUPPORT - * - * @NOTE: This container component serves as a wrapper for the purpose of data management, this is ONLY to support current instances. - * veda2 instances can just use the direct component, 'ExplorationAndAnalysis', and manage data directly in their page views - */ - -export default function ExplorationAndAnalysisContainer() { - const setExternalDatasets = useSetAtom(externalDatasetsAtom); - setExternalDatasets(allExploreDatasets); - const [timelineDatasets, setTimelineDatasets] = useTimelineDatasetAtom(); - const [datasetModalRevealed, setDatasetModalRevealed] = useState( - !timelineDatasets.length - ); - // @NOTE: When Exploration page is preloaded (ex. Linked with react-router) - // atomWithLocation gets initialized outside of Exploration page and returns the previous page's value - // We check if url Atom actually returns the values for exploration page here. - const [currentUrl] = useAtom(urlAtom); - const [viewMode] = useAtom(viewModeAtom); - - if (!currentUrl.pathname?.includes(EXPLORATION_PATH)) return null; - - const openModal = () => setDatasetModalRevealed(true); - const closeModal = () => setDatasetModalRevealed(false); - - return ( - <> - - - - - {viewMode === 'simple' ? ( - - ) : ( - <> - - -

- There are no datasets to show with the selected filters. -

-

- This tool allows the exploration and analysis of time-series - datasets in raster format. For a comprehensive list of - available datasets, please visit the{' '} - Data Catalog. -

- - } - /> - - )} -
- - ); -} diff --git a/app/scripts/components/exploration/index.tsx b/app/scripts/components/exploration/index.tsx index 7c4de93bb..111a37fef 100644 --- a/app/scripts/components/exploration/index.tsx +++ b/app/scripts/components/exploration/index.tsx @@ -1,142 +1,89 @@ -import React, { useEffect, useState } from 'react'; -import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; -import styled from 'styled-components'; -import { themeVal } from '@devseed-ui/theme-provider'; -import { TourProvider } from '@reactour/tour'; - +import React, { useState } from 'react'; +import { Link } from 'react-router-dom'; +import { DevTools } from 'jotai-devtools'; import { useAtom, useSetAtom } from 'jotai'; -import Timeline from './components/timeline/timeline'; -import { ExplorationMap } from './components/map'; -import { useAnalysisController } from './hooks/use-analysis-data-request'; -import { PopoverTourComponent, TourManager } from './tour-manager'; -import { TimelineDataset } from './types.d.ts'; -import { selectedCompareDateAtom, selectedDateAtom } from './atoms/dates'; -import { CLEAR_LOCATION, urlAtom } from '$utils/params-location-atom/url'; -import { legacyGlobalStyleCSSBlock } from '$styles/legacy-global-styles'; - -// @TODO: "height: 100%" Added for exploration container to show correctly in NextJs instance but investigate why this is needed and possibly work to remove -const Container = styled.div` - display: flex; - flex-flow: column; - flex-grow: 1; - height: 100%; - - .panel-wrapper { - flex-grow: 1; - } - - .panel { - display: flex; - flex-direction: column; - position: relative; - } - * { - ${legacyGlobalStyleCSSBlock} - } - .panel-timeline { - box-shadow: 0 -1px 0 0 ${themeVal('color.base-100')}; - } - - .resize-handle { - flex: 0; - position: relative; - outline: none; - display: flex; - align-items: center; - justify-content: center; - width: 5rem; - margin: 0 auto -1.25rem auto; - padding: 0rem 0 0.25rem; - z-index: 1; - ::before { - content: ''; - display: block; - width: 2rem; - background: ${themeVal('color.base-200')}; - height: 0.25rem; - border-radius: ${themeVal('shape.ellipsoid')}; - } - } -`; +import { DatasetSelectorModal } from '$components/exploration/components/dataset-selector-modal'; +import useTimelineDatasetAtom from '$components/exploration/hooks/use-timeline-dataset-atom'; +import { externalDatasetsAtom } from '$components/exploration/atoms/datasetLayers'; +import { viewModeAtom } from '$components/exploration/atoms/viewMode'; +import ExplorationSimpleView from '$components/exploration/views/simple'; +import ExplorationAndAnalysisDefaultView from '$components/exploration/views/default'; +import { allExploreDatasets } from '$data-layer/datasets'; +import { urlAtom } from '$utils/params-location-atom/url'; +import { PageMainContent } from '$styles/page'; +import { LayoutProps } from '$components/common/layout-root'; +import PageHero from '$components/common/page-hero'; +import { DATASETS_PATH, EXPLORATION_PATH } from '$utils/routes'; -const tourProviderStyles = { - popover: (base) => ({ - ...base, - padding: '0', - background: 'none' - }) -}; +/** + * @LEGACY-SUPPORT + * + * @NOTE: This container component serves as a wrapper for the purpose of data management, this is ONLY to support current instances. + * veda2 instances can just use the direct component, 'ExplorationAndAnalysis', and manage data directly in their page views + */ -interface ExplorationAndAnalysisProps { - datasets: TimelineDataset[]; - setDatasets: (datasets: TimelineDataset[]) => void; - openDatasetsSelectionModal?: () => void; -} - -export default function ExplorationAndAnalysis( - props: ExplorationAndAnalysisProps -) { - const { datasets, setDatasets, openDatasetsSelectionModal } = props; - - const [selectedDay, setSelectedDay] = useAtom(selectedDateAtom); - - const [selectedCompareDay, setSelectedCompareDay] = useAtom( - selectedCompareDateAtom +export default function ExplorationAndAnalysisContainer() { + const setExternalDatasets = useSetAtom(externalDatasetsAtom); + setExternalDatasets(allExploreDatasets); + const [timelineDatasets, setTimelineDatasets] = useTimelineDatasetAtom(); + const [datasetModalRevealed, setDatasetModalRevealed] = useState( + !timelineDatasets.length ); + // @NOTE: When Exploration page is preloaded (ex. Linked with react-router) + // atomWithLocation gets initialized outside of Exploration page and returns the previous page's value + // We check if url Atom actually returns the values for exploration page here. + const [currentUrl] = useAtom(urlAtom); + const [viewMode] = useAtom(viewModeAtom); - // @TECH-DEBT: panelHeight needs to be passed to work around Safari CSS - const [panelHeight, setPanelHeight] = useState(0); - - const setUrl = useSetAtom(urlAtom); - const { reset: resetAnalysisController } = useAnalysisController(); + if (!currentUrl.pathname?.includes(EXPLORATION_PATH)) return null; - // Reset atoms when leaving the page. - useEffect(() => { - return () => { - resetAnalysisController(); - setUrl(CLEAR_LOCATION); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const openModal = () => setDatasetModalRevealed(true); + const closeModal = () => setDatasetModalRevealed(false); return ( - - - - - { - setPanelHeight(size); - }} - > - + + + + + {viewMode === 'simple' ? ( + + ) : ( + <> + - - - - +

+ There are no datasets to show with the selected filters. +

+

+ This tool allows the exploration and analysis of time-series + datasets in raster format. For a comprehensive list of + available datasets, please visit the{' '} + Data Catalog. +

+ + } /> -
-
-
-
+ + )} +
+ ); } diff --git a/app/scripts/components/exploration/views/default/index.tsx b/app/scripts/components/exploration/views/default/index.tsx new file mode 100644 index 000000000..607880bbc --- /dev/null +++ b/app/scripts/components/exploration/views/default/index.tsx @@ -0,0 +1,148 @@ +import React, { useEffect, useState } from 'react'; +import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; +import styled from 'styled-components'; +import { themeVal } from '@devseed-ui/theme-provider'; +import { TourProvider } from '@reactour/tour'; + +import { useAtom, useSetAtom } from 'jotai'; +import Timeline from '$components/exploration/components/timeline/timeline'; +import { ExplorationMap } from '$components/exploration/components/map'; +import { useAnalysisController } from '$components/exploration/hooks/use-analysis-data-request'; +import { + PopoverTourComponent, + TourManager +} from '$components/exploration/tour-manager'; +import { TimelineDataset } from '$components/exploration/types.d.ts'; +import { + selectedCompareDateAtom, + selectedDateAtom +} from '$components/exploration/atoms/dates'; +import { CLEAR_LOCATION, urlAtom } from '$utils/params-location-atom/url'; +import { legacyGlobalStyleCSSBlock } from '$styles/legacy-global-styles'; + +// @TODO: "height: 100%" Added for exploration container to show correctly in NextJs instance but investigate why this is needed and possibly work to remove +const Container = styled.div` + display: flex; + flex-flow: column; + flex-grow: 1; + height: 100%; + + .panel-wrapper { + flex-grow: 1; + } + + .panel { + display: flex; + flex-direction: column; + position: relative; + } + * { + ${legacyGlobalStyleCSSBlock} + } + .panel-timeline { + box-shadow: 0 -1px 0 0 ${themeVal('color.base-100')}; + } + + .resize-handle { + flex: 0; + position: relative; + outline: none; + display: flex; + align-items: center; + justify-content: center; + width: 5rem; + margin: 0 auto -1.25rem auto; + padding: 0rem 0 0.25rem; + z-index: 1; + + ::before { + content: ''; + display: block; + width: 2rem; + background: ${themeVal('color.base-200')}; + height: 0.25rem; + border-radius: ${themeVal('shape.ellipsoid')}; + } + } +`; + +const tourProviderStyles = { + popover: (base) => ({ + ...base, + padding: '0', + background: 'none' + }) +}; + +interface ExplorationAndAnalysisDefaultViewProps { + datasets: TimelineDataset[]; + setDatasets: (datasets: TimelineDataset[]) => void; + openDatasetsSelectionModal?: () => void; +} + +export default function ExplorationAndAnalysisDefaultView( + props: ExplorationAndAnalysisDefaultViewProps +) { + const { datasets, setDatasets, openDatasetsSelectionModal } = props; + + const [selectedDay, setSelectedDay] = useAtom(selectedDateAtom); + + const [selectedCompareDay, setSelectedCompareDay] = useAtom( + selectedCompareDateAtom + ); + + // @TECH-DEBT: panelHeight needs to be passed to work around Safari CSS + const [panelHeight, setPanelHeight] = useState(0); + + const setUrl = useSetAtom(urlAtom); + const { reset: resetAnalysisController } = useAnalysisController(); + + // Reset atoms when leaving the page. + useEffect(() => { + return () => { + resetAnalysisController(); + setUrl(CLEAR_LOCATION); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + + + + + { + setPanelHeight(size); + }} + > + + + + + + + + + + ); +} diff --git a/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx b/app/scripts/components/exploration/views/simple/index.tsx similarity index 92% rename from app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx rename to app/scripts/components/exploration/views/simple/index.tsx index 14a600e45..a67bfa646 100644 --- a/app/scripts/components/exploration/components/exploration-simple-view/exploration-simple-view.tsx +++ b/app/scripts/components/exploration/views/simple/index.tsx @@ -1,15 +1,18 @@ import React, { useMemo, useState, useEffect } from 'react'; import styled from 'styled-components'; import { useAtom } from 'jotai'; +import { + selectedCompareDateAtom, + selectedDateAtom +} from '$components/exploration/atoms/dates'; +import { zoomAtom } from '$components/exploration/atoms/zoom'; +import { centerAtom } from '$components/exploration/atoms/center'; +import TimelineSimpleView from '$components/exploration/views/simple/timeline-simple-view'; +import { BasemapId } from '$components/common/map/controls/map-options/basemap'; import { convertProjectionToMapbox, projectionDefault -} from '../../../common/map/controls/map-options/projections'; -import { BasemapId } from '../../../common/map/controls/map-options/basemap'; -import { selectedCompareDateAtom, selectedDateAtom } from '../../atoms/dates'; -import { zoomAtom } from '../../atoms/zoom'; -import { centerAtom } from '../../atoms/center'; -import TimelineSimpleView from './timeline-simple-view'; +} from '$components/common/map/controls/map-options/projections'; import MapBlock from '$components/common/blocks/block-map'; import { VizDataset, diff --git a/app/scripts/components/exploration/components/exploration-simple-view/timeline-simple-view.tsx b/app/scripts/components/exploration/views/simple/timeline-simple-view.tsx similarity index 92% rename from app/scripts/components/exploration/components/exploration-simple-view/timeline-simple-view.tsx rename to app/scripts/components/exploration/views/simple/timeline-simple-view.tsx index fed015144..af6dcfaba 100644 --- a/app/scripts/components/exploration/components/exploration-simple-view/timeline-simple-view.tsx +++ b/app/scripts/components/exploration/views/simple/timeline-simple-view.tsx @@ -1,12 +1,15 @@ import React, { useMemo } from 'react'; import styled from 'styled-components'; import { View } from 'react-calendar/dist/cjs/shared/types'; -import { getLabelFormat, getTemporalExtent } from '../timeline/timeline-utils'; -import { TimelineDatePicker } from '../timeline/timeline-datepicker'; -import { TimeDensity } from '../../types.d.ts'; +import { TimelineDatePicker } from '$components/exploration/components/timeline/timeline-datepicker'; +import { + getLabelFormat, + getTemporalExtent +} from '$components/exploration/components/timeline/timeline-utils'; import { getLowestCommonTimeDensity } from '$components/exploration/data-utils'; import { + TimeDensity, TimelineDataset, DatasetStatus, TimelineDatasetSuccess diff --git a/app/scripts/libs/page-components.ts b/app/scripts/libs/page-components.ts index 24064f304..ee6b10d91 100644 --- a/app/scripts/libs/page-components.ts +++ b/app/scripts/libs/page-components.ts @@ -1,6 +1,6 @@ export { default as CatalogContent } from '$components/common/catalog/catalog-content'; -export { default as ExplorationAndAnalysis } from '$components/exploration'; -export { default as ExplorationSimpleView } from '$components/exploration/components/exploration-simple-view/exploration-simple-view'; +export { default as ExplorationAndAnalysis } from '$components/exploration/views/default'; +export { default as ExplorationSimpleView } from '$components/exploration/views/simple'; // DataSelectorModal needs to be paried with E&A, so putting this for now. export { DatasetSelectorModal } from '$components/exploration/components/dataset-selector-modal'; export { default as StoriesHubContent } from '$components/stories/hub/hub-content'; diff --git a/app/scripts/main.tsx b/app/scripts/main.tsx index 5da3a471c..db18fba89 100644 --- a/app/scripts/main.tsx +++ b/app/scripts/main.tsx @@ -47,9 +47,7 @@ const DataCatalog = lazy(() => import('$components/data-catalog/container')); const DatasetsOverview = lazy(() => import('$components/datasets/s-overview')); -const ExplorationAndAnalysis = lazy( - () => import('$components/exploration/container') -); +const ExplorationAndAnalysis = lazy(() => import('$components/exploration')); const Sandbox = lazy(() => import('$components/sandbox')); From 97e1a3b24af9d990e5f67bb907cc6924da8709b8 Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Tue, 9 Dec 2025 08:35:07 -0800 Subject: [PATCH 10/13] rename simple component for consistency --- app/scripts/components/exploration/index.tsx | 4 +- .../exploration/views/simple/index.tsx | 56 +++++++++---------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/app/scripts/components/exploration/index.tsx b/app/scripts/components/exploration/index.tsx index 111a37fef..ee0588b2a 100644 --- a/app/scripts/components/exploration/index.tsx +++ b/app/scripts/components/exploration/index.tsx @@ -7,7 +7,7 @@ import { DatasetSelectorModal } from '$components/exploration/components/dataset import useTimelineDatasetAtom from '$components/exploration/hooks/use-timeline-dataset-atom'; import { externalDatasetsAtom } from '$components/exploration/atoms/datasetLayers'; import { viewModeAtom } from '$components/exploration/atoms/viewMode'; -import ExplorationSimpleView from '$components/exploration/views/simple'; +import ExplorationAndAnalysisSimpleView from '$components/exploration/views/simple'; import ExplorationAndAnalysisDefaultView from '$components/exploration/views/default'; import { allExploreDatasets } from '$data-layer/datasets'; import { urlAtom } from '$utils/params-location-atom/url'; @@ -53,7 +53,7 @@ export default function ExplorationAndAnalysisContainer() { {viewMode === 'simple' ? ( - + ) : ( <> ` - position: absolute; - bottom: 2rem; - left: ${({ isCompareMode }) => (isCompareMode ? '25%' : '50%')}; - transform: translateX(-50%); - z-index: 10; -`; -const StyledCompareTimelineContainer = styled.div` - position: absolute; - bottom: 2rem; - left: 75%; - transform: translateX(-50%); - z-index: 10; -`; - -interface ExplorationSimpleViewProps { +interface ExplorationAndAnalysisSimpleViewProps { datasets: TimelineDataset[]; } -export default function ExplorationSimpleView( - props: ExplorationSimpleViewProps +export default function ExplorationAndAnalysisSimpleView( + props: ExplorationAndAnalysisSimpleViewProps ) { const { datasets } = props; const [selectedDay, setSelectedDay] = useAtom(selectedDateAtom); @@ -60,7 +39,7 @@ export default function ExplorationSimpleView( const [center] = useAtom(centerAtom); return ( // eslint-disable-next-line react/jsx-pascal-case - void; setSelectedComparedDay: (x: Date) => void; @@ -103,8 +82,8 @@ const getDataLayer = ( }; }; -function ExplorationSimpleViewContent( - props: ExplorationSimpleViewContentProps +function ExplorationAndAnalysisSimpleViewContent( + props: ExplorationAndAnalysisSimpleViewContentProps ) { const { datasets, @@ -218,3 +197,24 @@ function ExplorationSimpleViewContent( ); } + +const StyledContainer = styled.div` + position: relative; + flex-grow: 1; + height: 100vh; + display: flex; +`; +const StyledTimelineContainer = styled.div<{ isCompareMode?: boolean }>` + position: absolute; + bottom: 2rem; + left: ${({ isCompareMode }) => (isCompareMode ? '25%' : '50%')}; + transform: translateX(-50%); + z-index: 10; +`; +const StyledCompareTimelineContainer = styled.div` + position: absolute; + bottom: 2rem; + left: 75%; + transform: translateX(-50%); + z-index: 10; +`; From 3d42ac658bf91493986479f3c23c9f84bc1ed0d0 Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Tue, 9 Dec 2025 08:39:30 -0800 Subject: [PATCH 11/13] rename for consistency - missed on --- app/scripts/libs/index.ts | 2 +- app/scripts/libs/page-components.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/libs/index.ts b/app/scripts/libs/index.ts index 2c628856e..844352d14 100644 --- a/app/scripts/libs/index.ts +++ b/app/scripts/libs/index.ts @@ -56,7 +56,7 @@ export { export { CatalogContent, - ExplorationSimpleView, + ExplorationAndAnalysisSimpleView, ExplorationAndAnalysis, StoriesHubContent, DatasetSelectorModal diff --git a/app/scripts/libs/page-components.ts b/app/scripts/libs/page-components.ts index ee6b10d91..802a5115f 100644 --- a/app/scripts/libs/page-components.ts +++ b/app/scripts/libs/page-components.ts @@ -1,6 +1,6 @@ export { default as CatalogContent } from '$components/common/catalog/catalog-content'; export { default as ExplorationAndAnalysis } from '$components/exploration/views/default'; -export { default as ExplorationSimpleView } from '$components/exploration/views/simple'; +export { default as ExplorationAndAnalysisSimpleView } from '$components/exploration/views/simple'; // DataSelectorModal needs to be paried with E&A, so putting this for now. export { DatasetSelectorModal } from '$components/exploration/components/dataset-selector-modal'; export { default as StoriesHubContent } from '$components/stories/hub/hub-content'; From 92091c54c782cb50c8aaeebe3b105d7d01c14666 Mon Sep 17 00:00:00 2001 From: Vitor George Date: Tue, 9 Dec 2025 17:51:08 +0000 Subject: [PATCH 12/13] docs: add JSDoc to exploration view mode public API Add JSDoc documentation to public API exports for the new view mode system, following existing patterns in the codebase. Documents: - viewModeAtom and ViewMode type - ExplorationAndAnalysisSimpleView and ExplorationAndAnalysisDefaultView - TimelineSimpleView component - Container routing logic Supersedes JSDoc work from #1931 after file restructuring. --- .../components/exploration/atoms/viewMode.ts | 11 +++++++++++ app/scripts/components/exploration/index.tsx | 14 +++++++++++--- app/scripts/components/exploration/types.d.ts.ts | 6 ++++++ .../components/exploration/views/default/index.tsx | 10 ++++++++++ .../components/exploration/views/simple/index.tsx | 12 ++++++++++++ .../views/simple/timeline-simple-view.tsx | 11 +++++++++++ 6 files changed, 61 insertions(+), 3 deletions(-) diff --git a/app/scripts/components/exploration/atoms/viewMode.ts b/app/scripts/components/exploration/atoms/viewMode.ts index 28f7cc8b8..2c86a2202 100644 --- a/app/scripts/components/exploration/atoms/viewMode.ts +++ b/app/scripts/components/exploration/atoms/viewMode.ts @@ -12,6 +12,17 @@ const dehydrateViewMode = (value: ViewMode) => { return value ?? 'default'; }; +/** + * Atom that manages the exploration view mode via URL parameter. + * + * - 'simple': Minimal view for embedding (no navigation/header) + * - 'default': Full exploration and analysis interface + * + * URL parameter: `?viewMode=simple` (defaults to 'default') + * + * @example + * const [viewMode] = useAtom(viewModeAtom); + */ export const viewModeAtom = atomWithUrlValueStability({ initialValue: hydrateViewMode(initialParams.get('viewMode')), urlParam: 'viewMode', diff --git a/app/scripts/components/exploration/index.tsx b/app/scripts/components/exploration/index.tsx index ee0588b2a..013d305ae 100644 --- a/app/scripts/components/exploration/index.tsx +++ b/app/scripts/components/exploration/index.tsx @@ -17,12 +17,20 @@ import PageHero from '$components/common/page-hero'; import { DATASETS_PATH, EXPLORATION_PATH } from '$utils/routes'; /** + * Container component that manages exploration view routing and data state. + * + * Routes between two view modes based on URL parameter: + * - Simple view (`?viewMode=simple`): Minimal interface for embedding + * - Default view: Full exploration and analysis interface + * * @LEGACY-SUPPORT * - * @NOTE: This container component serves as a wrapper for the purpose of data management, this is ONLY to support current instances. - * veda2 instances can just use the direct component, 'ExplorationAndAnalysis', and manage data directly in their page views + * @NOTE: This container component serves as a wrapper for the purpose of data management, + * this is ONLY to support current instances. veda2 instances can just use the direct + * component, 'ExplorationAndAnalysisDefaultView', and manage data directly in their page views + * + * @returns {JSX.Element | null} Renders the appropriate view or null if not on exploration path */ - export default function ExplorationAndAnalysisContainer() { const setExternalDatasets = useSetAtom(externalDatasetsAtom); setExternalDatasets(allExploreDatasets); diff --git a/app/scripts/components/exploration/types.d.ts.ts b/app/scripts/components/exploration/types.d.ts.ts index 6e2ce4eba..65f78f0d5 100644 --- a/app/scripts/components/exploration/types.d.ts.ts +++ b/app/scripts/components/exploration/types.d.ts.ts @@ -195,4 +195,10 @@ export interface ZoomTransformPlain { k: number; } +/** + * Exploration view mode. + * + * - 'simple': Minimal view for embedding + * - 'default': Full exploration interface + */ export type ViewMode = 'simple' | 'default'; diff --git a/app/scripts/components/exploration/views/default/index.tsx b/app/scripts/components/exploration/views/default/index.tsx index 607880bbc..318eb3f30 100644 --- a/app/scripts/components/exploration/views/default/index.tsx +++ b/app/scripts/components/exploration/views/default/index.tsx @@ -80,6 +80,16 @@ interface ExplorationAndAnalysisDefaultViewProps { openDatasetsSelectionModal?: () => void; } +/** + * Full exploration and analysis view with all features. + * + * Includes interactive map, resizable timeline panel, dataset management, + * and analysis tools. Exported as `ExplorationAndAnalysis` in the public API. + * + * @param props.datasets - Timeline datasets to display and analyze + * @param props.setDatasets - Callback to update the dataset list + * @param props.openDatasetsSelectionModal - Optional callback to open dataset selector + */ export default function ExplorationAndAnalysisDefaultView( props: ExplorationAndAnalysisDefaultViewProps ) { diff --git a/app/scripts/components/exploration/views/simple/index.tsx b/app/scripts/components/exploration/views/simple/index.tsx index 05ba265c1..8b9da440b 100644 --- a/app/scripts/components/exploration/views/simple/index.tsx +++ b/app/scripts/components/exploration/views/simple/index.tsx @@ -27,6 +27,18 @@ import { useVedaUI } from '$context/veda-ui-provider'; interface ExplorationAndAnalysisSimpleViewProps { datasets: TimelineDataset[]; } + +/** + * Simplified exploration view optimized for embedding. + * + * Renders only the map visualization and timeline controls, + * without navigation, header, or dataset selection UI. + * + * @param props.datasets - Timeline datasets to display + * + * @example + * + */ export default function ExplorationAndAnalysisSimpleView( props: ExplorationAndAnalysisSimpleViewProps ) { diff --git a/app/scripts/components/exploration/views/simple/timeline-simple-view.tsx b/app/scripts/components/exploration/views/simple/timeline-simple-view.tsx index af6dcfaba..d157ba70f 100644 --- a/app/scripts/components/exploration/views/simple/timeline-simple-view.tsx +++ b/app/scripts/components/exploration/views/simple/timeline-simple-view.tsx @@ -34,6 +34,17 @@ interface TimelineSimpleViewProps { tipContent?: string; } +/** + * Timeline date picker for the simple exploration view. + * + * Adjusts calendar view (month/year/day) based on dataset time density + * and calculates temporal extent from provided datasets. + * + * @param props.date - Currently selected date + * @param props.setDate - Callback to update the selected date + * @param props.timeDensity - Dataset time density (determines calendar view) + * @param props.datasets - Datasets used to calculate temporal extent + */ function TimelineSimpleView(props: TimelineSimpleViewProps) { const { date, setDate, timeDensity, datasets, label, tipContent } = props; From bb2186fcc5dd3f660ce33f2e1d424abbbb88c8bd Mon Sep 17 00:00:00 2001 From: Simi Damani Date: Tue, 9 Dec 2025 11:01:02 -0800 Subject: [PATCH 13/13] JS Doc updates --- app/scripts/components/exploration/atoms/viewMode.ts | 2 +- app/scripts/components/exploration/index.tsx | 2 +- app/scripts/components/exploration/views/simple/index.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/scripts/components/exploration/atoms/viewMode.ts b/app/scripts/components/exploration/atoms/viewMode.ts index 2c86a2202..6c49c0230 100644 --- a/app/scripts/components/exploration/atoms/viewMode.ts +++ b/app/scripts/components/exploration/atoms/viewMode.ts @@ -15,7 +15,7 @@ const dehydrateViewMode = (value: ViewMode) => { /** * Atom that manages the exploration view mode via URL parameter. * - * - 'simple': Minimal view for embedding (no navigation/header) + * - 'simple': Minimal view for used primarily for embedding (no navigation/header/footer/dataset selection UI or time series visualization) * - 'default': Full exploration and analysis interface * * URL parameter: `?viewMode=simple` (defaults to 'default') diff --git a/app/scripts/components/exploration/index.tsx b/app/scripts/components/exploration/index.tsx index 013d305ae..fa8d16f24 100644 --- a/app/scripts/components/exploration/index.tsx +++ b/app/scripts/components/exploration/index.tsx @@ -20,7 +20,7 @@ import { DATASETS_PATH, EXPLORATION_PATH } from '$utils/routes'; * Container component that manages exploration view routing and data state. * * Routes between two view modes based on URL parameter: - * - Simple view (`?viewMode=simple`): Minimal interface for embedding + * - Simple view (`?viewMode=simple`): Minimal interface used primarily for embedding in viewport constrained external apps * - Default view: Full exploration and analysis interface * * @LEGACY-SUPPORT diff --git a/app/scripts/components/exploration/views/simple/index.tsx b/app/scripts/components/exploration/views/simple/index.tsx index 8b9da440b..58d1c7007 100644 --- a/app/scripts/components/exploration/views/simple/index.tsx +++ b/app/scripts/components/exploration/views/simple/index.tsx @@ -32,7 +32,7 @@ interface ExplorationAndAnalysisSimpleViewProps { * Simplified exploration view optimized for embedding. * * Renders only the map visualization and timeline controls, - * without navigation, header, or dataset selection UI. + * without navigation, header, footer, dataset selection UI and time series visualization. * * @param props.datasets - Timeline datasets to display *