diff --git a/src/components/panes/eva/eva-right-eva-info.tsx b/src/components/panes/eva/eva-right-eva-info.tsx index fb8fcca0..642163c3 100644 --- a/src/components/panes/eva/eva-right-eva-info.tsx +++ b/src/components/panes/eva/eva-right-eva-info.tsx @@ -91,6 +91,7 @@ const EvaRightEvaInfo: FunctionComponent<{ editMode: boolean }> = ({ editMode }) stations: selectEvaStations(mission, selectedEvaUuid), traverses: selectEvaTraverses(mission, selectedEvaUuid), defaultTraverseColor: mission.evas?.[selectedEvaUuid]?.traverseColor ?? undefined, + time: numericDatetimeToISO(mission.evas?.[selectedEvaUuid]?.datetime) ?? undefined, }); }, deepEqual); diff --git a/src/tests/vitest/utils/quickMap.test.ts b/src/tests/vitest/utils/quickMap.test.ts index 82fce830..49153bc0 100644 --- a/src/tests/vitest/utils/quickMap.test.ts +++ b/src/tests/vitest/utils/quickMap.test.ts @@ -43,6 +43,36 @@ describe("QuickMap URL adapter", () => { expect(omittedGeometryCount).toBe(0); }); + it("includes a timestamp when supplied", () => { + const { url } = buildQuickMapLink(baseUrl, { + ...linkState, + time: "1971-02-05T00:00:00.000Z", + }); + + expect(url.searchParams.get("time")).toBe("1971-02-05T00:00:00.000Z"); + }); + + it("includes a bounded playback range only when both ends are supplied", () => { + const { url } = buildQuickMapLink(baseUrl, { + ...linkState, + startTime: "1971-02-05T00:00:00.000Z", + stopTime: "1971-02-05T06:30:00.000Z", + }); + + expect(url.searchParams.get("startTime")).toBe("1971-02-05T00:00:00.000Z"); + expect(url.searchParams.get("stopTime")).toBe("1971-02-05T06:30:00.000Z"); + }); + + it("does not send an incomplete playback range", () => { + const { url } = buildQuickMapLink(baseUrl, { + ...linkState, + startTime: "1971-02-05T00:00:00.000Z", + }); + + expect(url.searchParams.has("startTime")).toBe(false); + expect(url.searchParams.has("stopTime")).toBe(false); + }); + it("normalizes longitude at the antimeridian", () => { expect(normalizeQuickMapLongitude(540)).toBe(180); expect(normalizeQuickMapLongitude(-540)).toBe(-180); diff --git a/src/utils/quickMap.ts b/src/utils/quickMap.ts index 4a60fa64..6ee5647d 100644 --- a/src/utils/quickMap.ts +++ b/src/utils/quickMap.ts @@ -12,6 +12,10 @@ export interface QuickMapLinkState { resolutionMetersPerPixel: number; layerIds: string[]; geometries: QuickMapGeometry[]; + /** Optional ISO 8601 time state understood by QuickMap's Cesium viewer. */ + time?: string; + startTime?: string; + stopTime?: string; } export interface QuickMapLinkResult { @@ -127,6 +131,14 @@ function createBaseUrl(baseUrl: string, state: QuickMapLinkState): URL { if (state.layerIds.length > 0) { url.searchParams.set("stack", state.layerIds.join(",")); } + if (state.time) { + url.searchParams.set("time", state.time); + } + // QuickMap enables bounded playback only when both ends are supplied. + if (state.startTime && state.stopTime) { + url.searchParams.set("startTime", state.startTime); + url.searchParams.set("stopTime", state.stopTime); + } return url; } @@ -163,12 +175,18 @@ export function createQuickMapLinkState({ stations = [], traverses = [], defaultTraverseColor, + time, + startTime, + stopTime, }: { center: AEGISPoint; additionalPoints?: QuickMapPoint[]; stations?: Station[]; traverses?: Traverse[]; defaultTraverseColor?: string; + time?: string; + startTime?: string; + stopTime?: string; }): QuickMapLinkState { const { layerIds, resolutionMetersPerPixel } = getQuickMapConfig(); const additionalPointGeometries = additionalPoints.flatMap((point): QuickMapGeometry[] => { @@ -219,6 +237,9 @@ export function createQuickMapLinkState({ resolutionMetersPerPixel, layerIds, geometries: [...additionalPointGeometries, ...stationGeometries, ...traverseGeometries], + time, + startTime, + stopTime, }; }