diff --git a/web/js/components/timeline/timeline-coverage/timeline-coverage.js b/web/js/components/timeline/timeline-coverage/timeline-coverage.js index 03076f29f2..aaff6c6655 100644 --- a/web/js/components/timeline/timeline-coverage/timeline-coverage.js +++ b/web/js/components/timeline/timeline-coverage/timeline-coverage.js @@ -43,26 +43,56 @@ function mergeSortedGranuleDateRanges(granules) { }, []); } -async function getLayerGranuleRanges(layer) { - const conceptID = layer.conceptIds?.[0]?.value; - const extent = [-180, -90, 180, 90]; - const startDate = new Date(layer.startDate).toISOString(); - const endDate = layer.endDate ? new Date(layer.endDate).toISOString() : new Date().toISOString(); +async function requestGranules(params) { + const { + shortName, + extent, + startDate, + endDate, + } = params; const granules = []; let hits = Infinity; let searchAfter = false; - const url = `https://cmr.earthdata.nasa.gov/search/granules.json?collection_concept_id=${conceptID}&bounding_box=${extent.join(',')}&temporal=${startDate}/${endDate}&sort_key=start_date&pageSize=2000`; + const url = `https://cmr.earthdata.nasa.gov/search/granules.json?shortName=${shortName}&bounding_box=${extent.join(',')}&temporal=${startDate}/${endDate}&sort_key=start_date&pageSize=2000`; /* eslint-disable no-await-in-loop */ - do { - const headers = searchAfter ? { 'Cmr-Search-After': searchAfter, 'Client-Id': 'worldview' } : { 'Client-Id': 'worldview' }; + do { // run the query at least once + const headers = searchAfter ? { 'Cmr-Search-After': searchAfter, 'Client-Id': 'Worldview' } : { 'Client-Id': 'Worldview' }; const res = await fetch(url, { headers }); searchAfter = res.headers.get('Cmr-Search-After'); hits = parseInt(res.headers.get('Cmr-Hits'), 10); const data = await res.json(); granules.push(...data.feed.entry); - } while (searchAfter || hits > granules.length); + } while (searchAfter || hits > granules.length); // searchAfter will not be present if there are no more results https://cmr.earthdata.nasa.gov/search/site/docs/search/api.html#search-after + + return granules; +} + +async function getLayerGranuleRanges(layer) { + const extent = [-180, -90, 180, 90]; + const startDate = new Date(layer.startDate).toISOString(); + const endDate = layer.endDate ? new Date(layer.endDate).toISOString() : new Date().toISOString(); + const shortName = layer.conceptIds?.[0]?.shortName; + const nrtParams = { + shortName, + extent, + startDate, + endDate, + }; + const nrtGranules = await requestGranules(nrtParams); + let nonNRTGranules = []; + if (shortName.includes('_NRT')) { // if NRT, also get non-NRT granules + const nonNRTShortName = shortName.replace('_NRT', ''); + const nonNRTParams = { + shortName: nonNRTShortName, + extent, + startDate, + endDate, + }; + nonNRTGranules = await requestGranules(nonNRTParams); + } + const granules = [...nonNRTGranules, ...nrtGranules]; const granuleDateRanges = granules.map(({ time_start: timeStart, time_end: timeEnd }) => [timeStart, timeEnd]); - const mergedGranuleDateRanges = mergeSortedGranuleDateRanges(granuleDateRanges); + const mergedGranuleDateRanges = mergeSortedGranuleDateRanges(granuleDateRanges); // merge overlapping granule ranges to simplify rendering return mergedGranuleDateRanges; } diff --git a/web/js/map/granule/granule-layer-builder.js b/web/js/map/granule/granule-layer-builder.js index 71f51ec719..855215e937 100644 --- a/web/js/map/granule/granule-layer-builder.js +++ b/web/js/map/granule/granule-layer-builder.js @@ -124,21 +124,31 @@ export default function granuleLayerBuilder(cache, store, createLayerWMTS) { const { proj: { selected: { crs } } } = state; const getGranulesUrl = getGranulesUrlSelector(state); const params = getParamsForGranuleRequest(def, date, crs); + const nrtParams = getParamsForGranuleRequest(def, date, crs, true); const { shortName } = params; + const { shortName: nrtShortName } = nrtParams; let data = []; + let nrtData = []; const existingGranules = CMRDataStore[crs][shortName] || []; - const datesQueried = datesHaveBeenQueried(params.startDate, date, existingGranules); + const existingNRTGranules = CMRDataStore[crs][nrtShortName] || []; + const mergedExistingGranules = existingGranules.concat(existingNRTGranules); + const datesQueried = datesHaveBeenQueried(params.startDate, date, mergedExistingGranules); - if (existingGranules.length && datesQueried) { - return existingGranules; + if (mergedExistingGranules.length && datesQueried) { + return mergedExistingGranules; } try { showLoading(); const requestUrl = getGranulesUrl(params); + const nrtRequestUrl = getGranulesUrl(nrtParams); const response = await fetch(requestUrl, CMR_AJAX_OPTIONS); + const nrtResponse = await fetch(nrtRequestUrl, CMR_AJAX_OPTIONS); data = await response.json(); + nrtData = await nrtResponse.json(); data = data.feed.entry; - if (data.length) { + nrtData = nrtData.feed.entry; + if (data.length || nrtData.length) { + addGranuleCMRDateData(def, nrtData, nrtShortName, dateRanges); addGranuleCMRDateData(def, data, shortName, dateRanges); } else { const dateWithinRange = isWithinDateRange(date, startDate, endDate); @@ -153,7 +163,7 @@ export default function granuleLayerBuilder(cache, store, createLayerWMTS) { hideLoading(); } - return CMRDataStore[crs][shortName]; + return [...existingNRTGranules, ...existingGranules]; }; /** diff --git a/web/js/map/granule/util.js b/web/js/map/granule/util.js index 19d441334c..1fb65a30d4 100644 --- a/web/js/map/granule/util.js +++ b/web/js/map/granule/util.js @@ -163,7 +163,7 @@ export const getCMRQueryDates = (crs, selectedDate) => { * @param {*} crs * @returns */ -export const getParamsForGranuleRequest = (def, date, crs) => { +export const getParamsForGranuleRequest = (def, date, crs, nrt) => { const dayNightFilter = def.daynight[0]; const bboxForProj = { [CRS.WEB_MERCATOR]: [-180, -65, 180, 65], @@ -176,6 +176,7 @@ export const getParamsForGranuleRequest = (def, date, crs) => { const getShortName = () => { try { const { shortName } = def.conceptIds[0]; + if (nrt) return shortName; // remove _NRT from shortName return shortName.replace('_NRT', ''); } catch (e) {