-
Date Ranges:
+ return (
+ <>
+
{
+ getDateRanges();
+ setShowRanges(!showRanges);
+ }}
+ >
+ *View Dates
+
+
+
+
Date Ranges:
+
+ {dateRanges.length === 0 && Loading...}
-
-
- {listItems}
-
-
- >
- );
- }
+
+
+ {renderListItem()}
+
+
+
+ >
+ );
}
-
-DateRanges.propTypes = {
- layer: PropTypes.object,
-};
diff --git a/web/js/components/layer/info/info.js b/web/js/components/layer/info/info.js
index 044854a8a6..37d813d7da 100644
--- a/web/js/components/layer/info/info.js
+++ b/web/js/components/layer/info/info.js
@@ -11,7 +11,6 @@ export default function LayerInfo ({ layer, measurementDescriptionPath }) {
id,
period,
startDate,
- ongoing,
} = layer;
const [layerMetadata, setLayerMetadata] = useState();
@@ -48,7 +47,7 @@ export default function LayerInfo ({ layer, measurementDescriptionPath }) {
const overlapDateRanges = hasLayerDateRange
? dateOverlap(period, dateRanges)
: [];
- return hasLayerDateRange && overlapDateRanges.overlap === false && !ongoing;
+ return hasLayerDateRange && overlapDateRanges.overlap === false;
};
const needDateRanges = getDateOverlapDateRanges();
diff --git a/web/js/components/smart-handoffs/smart-handoff-not-available-modal.js b/web/js/components/smart-handoffs/smart-handoff-not-available-modal.js
index 1d8f9902cf..bff507ec4d 100644
--- a/web/js/components/smart-handoffs/smart-handoff-not-available-modal.js
+++ b/web/js/components/smart-handoffs/smart-handoff-not-available-modal.js
@@ -16,7 +16,7 @@ export default function SmartHandoffNotAvailableModal() {
For a downloadable product similar to MODIS Corrected Reflectance,
please try the MODIS Land Surface Reflectance layers available in @NAME@.
If you would like to generate MODIS Corrected Reflectance imagery yourself, please
-
+
see this document
.
diff --git a/web/js/components/timeline/timeline-axis/timeline-axis.js b/web/js/components/timeline/timeline-axis/timeline-axis.js
index cdb2cb9d63..18728d4730 100644
--- a/web/js/components/timeline/timeline-axis/timeline-axis.js
+++ b/web/js/components/timeline/timeline-axis/timeline-axis.js
@@ -79,6 +79,7 @@ class TimelineAxis extends Component {
position,
dateA,
dateB,
+ activeLayers,
} = this.props;
const checkForPropsUpdates = nextProps.axisWidth === axisWidth
@@ -95,6 +96,7 @@ class TimelineAxis extends Component {
&& nextProps.transformX === transformX
&& nextProps.frontDate === frontDate
&& nextProps.backDate === backDate
+ && nextProps.activeLayers.length === activeLayers.length
&& lodashIsEqual(nextProps.matchingTimelineCoverage, matchingTimelineCoverage);
const {
@@ -142,7 +144,23 @@ class TimelineAxis extends Component {
draggerTimeState,
draggerTimeStateB,
timelineEndDateLimit,
+ activeLayers,
+ proj,
+ frontDate,
+ backDate,
} = this.props;
+
+ if (activeLayers.length !== prevProps.activeLayers.length || frontDate !== prevProps.frontDate || backDate !== prevProps.backDate) {
+ const backDateTime = new Date(backDate).getTime();
+ const startDateTime = new Date(frontDate).getTime();
+ const draggerTimeStateDate = new Date(draggerTimeState);
+ const draggerTimeStateTime = draggerTimeStateDate.getTime();
+ // Make sure that the dragger is within the new time range
+ const maxBackDate = draggerTimeStateTime > backDateTime ? (draggerTimeStateDate.setDate(draggerTimeStateDate.getDate() + 1), draggerTimeStateDate.toISOString()) : backDate;
+ const minFrontDate = draggerTimeStateTime < startDateTime ? (draggerTimeStateDate.setDate(draggerTimeStateDate.getDate() - 1), draggerTimeStateDate.toISOString()) : frontDate;
+ activeLayers.forEach((layer) => this.addTimeRanges(layer, proj, [minFrontDate, maxBackDate]));
+ }
+
const { wheelZoom } = this.state;
let draggerDate = draggerSelected === 'selected' ? draggerTimeState : draggerTimeStateB;
@@ -1321,6 +1339,56 @@ class TimelineAxis extends Component {
updatePositioningOnAxisStopDrag(updatePositioningArguments, hoverTimeDate);
}
+ addTimeRanges = (def, proj, dateRange) => {
+ const {
+ addGranuleDateRanges,
+ } = this.props;
+ const {
+ cmrAvailability,
+ dataAvailability,
+ id,
+ } = def;
+ // if opted in to CMR availability, get granule date ranges if needed
+ if (cmrAvailability || dataAvailability === 'cmr') {
+ const worker = new Worker('js/workers/cmr.worker.js');
+ worker.onmessage = (event) => {
+ worker.terminate();
+ addGranuleDateRanges(def, event.data);
+ };
+ worker.onerror = () => worker.terminate();
+ worker.postMessage({ operation: 'getLayerGranuleRanges', args: [def] });
+ }
+ // if opted in to DescribeDomains availability, get granule date ranges if needed
+ if (dataAvailability === 'dd') {
+ const worker = new Worker('js/workers/describe-domains.worker.js');
+ worker.onmessage = (event) => {
+ if (Array.isArray(event.data)) { // our final format is an array
+ worker.terminate(); // terminate the worker
+ return addGranuleDateRanges(def, event.data); // dispatch the action
+ }
+ // DOMParser is not available in workers so we parse the xml on the main thread before sending it back to the worker
+ const parser = new DOMParser();
+ const xmlDoc = parser.parseFromString(event.data, 'text/xml');
+ const domains = xmlDoc.querySelector('Domain')?.textContent;
+ if (!domains) worker.terminate();
+ worker.postMessage({ operation: 'mergeDomains', args: [domains, 60_000] });
+ };
+ worker.onerror = () => worker.terminate();
+ let startDate = new Date(def.startDate);
+ let endDate = def.endDate ? new Date(def.endDate).toISOString() : new Date().toISOString();
+ if (dateRange) {
+ [startDate, endDate] = dateRange;
+ }
+ const params = {
+ startDate,
+ endDate,
+ id,
+ proj: proj.crs,
+ };
+ worker.postMessage({ operation: 'requestDescribeDomains', args: [params] });
+ }
+ };
+
/**
* @desc get matching coverage line dimensions for given date range
* @returns {Object} visible, leftOffset, width
@@ -1532,6 +1600,8 @@ class TimelineAxis extends Component {
}
TimelineAxis.propTypes = {
+ activeLayers: PropTypes.array,
+ addGranuleDateRanges: PropTypes.func,
animationEndLocation: PropTypes.number,
animationStartLocation: PropTypes.number,
animEndLocationDate: PropTypes.object,
diff --git a/web/js/components/timeline/timeline-coverage/coverage-item-container.js b/web/js/components/timeline/timeline-coverage/coverage-item-container.js
index 3f188c7bef..935147c722 100644
--- a/web/js/components/timeline/timeline-coverage/coverage-item-container.js
+++ b/web/js/components/timeline/timeline-coverage/coverage-item-container.js
@@ -72,7 +72,7 @@ class CoverageItemContainer extends Component {
dateIntervalStartDates.forEach((dateIntStartDate) => {
const dateIntTime = new Date(dateIntStartDate).getTime();
// allow overwriting of subsequent date ranges
- if (dateIntTime >= startDateTime && dateIntTime < endDateTime) {
+ if (dateIntTime >= startDateTime && dateIntTime <= endDateTime) {
const dateIntFormatted = dateIntStartDate.toISOString();
multiCoverageDates[dateIntFormatted] = {
date: dateIntFormatted,
diff --git a/web/js/components/timeline/timeline-coverage/coverage-item-list.js b/web/js/components/timeline/timeline-coverage/coverage-item-list.js
index 0c797f1f5c..0dd9349b39 100644
--- a/web/js/components/timeline/timeline-coverage/coverage-item-list.js
+++ b/web/js/components/timeline/timeline-coverage/coverage-item-list.js
@@ -262,9 +262,7 @@ class CoverageItemList extends Component {
const endGreaterThanOrEqualToStartDateLimit = new Date(rangeEnd).getTime() >= startDateLimit.getTime();
if (startLessThanOrEqualToEndDateLimit && endGreaterThanOrEqualToStartDateLimit) {
// check layer date array cache and use caches date array if available, if not add date array
- if (!this.layerDateArrayCache[id]) {
- this.layerDateArrayCache[id] = {};
- }
+ this.layerDateArrayCache[id] ??= {};
const layerIdDates = `${appNow.toISOString()}-${frontDate}-${backDate}`;
if (this.layerDateArrayCache[id][layerIdDates] === undefined) {
diff --git a/web/js/components/tour/content-intro.js b/web/js/components/tour/content-intro.js
index 115556e68c..6bf1536e37 100644
--- a/web/js/components/tour/content-intro.js
+++ b/web/js/components/tour/content-intro.js
@@ -10,7 +10,7 @@ function TourIntro(props) {
Visually explore the past and the present of this dynamic planet from a satellite's perspective.
Select from an array of stories below to learn more about @NAME@ (a part of
{' '}
-
NASA Earthdata
+
NASA Earthdata
), the satellite imagery we provide and events occurring around the world.
{' '}
diff --git a/web/js/containers/timeline/timeline.js b/web/js/containers/timeline/timeline.js
index a670994b34..19769b82a2 100644
--- a/web/js/containers/timeline/timeline.js
+++ b/web/js/containers/timeline/timeline.js
@@ -54,6 +54,7 @@ import {
getNextTimeSelection,
} from '../../modules/date/util';
import { toggleActiveCompareState } from '../../modules/compare/actions';
+import { addGranuleDateRanges } from '../../modules/layers/actions';
import {
onActivate as openAnimation,
onClose as closeAnimation,
@@ -1138,6 +1139,7 @@ class Timeline extends React.Component {
render() {
const {
activeLayers,
+ addGranuleDateRanges,
animationDisabled,
animEndLocationDate,
animStartLocationDate,
@@ -1170,6 +1172,7 @@ class Timeline extends React.Component {
timeScale,
timeScaleChangeUnit,
toggleActiveCompareState,
+ proj,
} = this.props;
const {
animationEndLocation,
@@ -1281,6 +1284,8 @@ class Timeline extends React.Component {