Skip to content

Commit

Permalink
WV-3246 Describe Domains (#5392)
Browse files Browse the repository at this point in the history
* initial work

* fix: await processLayer in extractConfigFromWMTS.js

* feat: only show "View Dates" in the layer info if the layer is not ongoing
  • Loading branch information
PatchesMaps authored Aug 13, 2024
1 parent 1a63e18 commit 4232035
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 69 deletions.
4 changes: 2 additions & 2 deletions tasks/build-options/extractConfigFromWMTS.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ async function processEntry (entry) {
for (const gcLayer of gcContents.Layer) {
try {
layerCount += 1
processLayer(gcLayer, wvLayers, entry)
await processLayer(gcLayer, wvLayers, entry)
} catch (error) {
if (error instanceof SkipException) {
warningCount += 1
Expand Down Expand Up @@ -184,7 +184,7 @@ async function processLayer (gcLayer, wvLayers, entry) {
const dimension = gcLayer.Dimension
if (dimension['ows:Identifier']._text === 'Time') {
try {
wvLayer = await processTemporalLayer(wvLayer, dimension.Value)
wvLayer = await processTemporalLayer(wvLayer, dimension.Value, entry.source)
} catch (e) {
console.error(e)
console.error(`${prog}: ERROR: [${ident}] Error processing time values.`)
Expand Down
161 changes: 95 additions & 66 deletions tasks/build-options/processTemporalLayer.js
Original file line number Diff line number Diff line change
@@ -1,88 +1,117 @@
const moment = require('moment')
const xml2js = require('xml2js')

const projDict = {
'GIBS:geographic': 'epsg4326',
'GIBS:arctic': 'epsg3413',
'GIBS:antarctic': 'epsg3031'
}

function toList (val) {
return val instanceof Array ? val : [val]
}

async function processTemporalLayer (wvLayer, value) {
async function processTemporalLayer (wvLayer, value, source = 'GIBS:geographic') {
const dateFormat = 'YYYY-MM-DD'
const dateTimeFormat = 'YYYY-MM-DD HH:mm:ss'
try {
const ranges = toList(value)
if (ranges && ranges[0] && ranges[0]._text && ranges[0]._text.includes('T')) {
wvLayer.period = 'subdaily'
} else {
if (ranges && ranges[0] && ranges[0]._text && ranges[0]._text.endsWith('Y')) {
wvLayer.period = 'yearly'
} else if (ranges && ranges[0] && ranges[0]._text && ranges[0]._text.endsWith('M')) {
wvLayer.period = 'monthly'
} else {
wvLayer.period = 'daily'
}
}
let startDate = moment.min()
let endDate = moment.max()
const dateRangeStart = []
const dateRangeEnd = []
const rangeInterval = []
for (const range of ranges) {
const [start, end, interval] = range._text.split('/')
if (
wvLayer.period === 'daily' ||
wvLayer.period === 'monthly' ||
wvLayer.period === 'yearly'
) {
startDate = moment.min(startDate, moment(start, dateFormat))
endDate = moment.max(endDate, moment(end, dateFormat))
if (start) {
startDate = moment(start, dateFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')
dateRangeStart.push(startDate)
}
if (end) {
endDate = moment(end, dateFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')
let ranges = toList(value)
const describeDomainsUrl = `https://gibs.earthdata.nasa.gov/wmts/${projDict[source]}/best/1.0.0/${wvLayer.id}/default/250m/all/all.xml`
try {
const describeDomainsResponse = await fetch(describeDomainsUrl)
if (describeDomainsResponse?.ok) {
const describeDomainsText = await describeDomainsResponse?.text?.() || ''
const parser = new xml2js.Parser()
const describeDomainsJson = await parser.parseStringPromise(describeDomainsText)
const domain = describeDomainsJson?.Domains?.DimensionDomain?.[0]?.Domain?.[0] || ''
const domains = domain.split(',')
if (domains?.length) {
const formattedDomains = domains.map((d) => {
return {
_text: d
}
})
ranges = toList(formattedDomains)
}
if (interval !== 'P1D') {
endDate = moment.utc(endDate).add(moment.duration(interval)).format('YYYY-MM-DDTHH:mm:ss[Z]')
// For monthly products subtract 1 day
if (wvLayer.period === 'monthly') {
endDate = moment.utc(endDate).subtract(1, 'day').format('YYYY-MM-DDTHH:mm:ss[Z]')
}
}
const regex = /\d+/g
const match = regex.exec(interval)
rangeInterval.push(match)
if (endDate.endsWith('T00:00:00Z')) {
endDate = endDate.replace('T00:00:00Z', 'T23:59:59Z')
}
dateRangeEnd.push(endDate)
}
} catch (error) {
console.error(`Error fetching ${describeDomainsUrl}: ${error}`)
} finally {
if (ranges && ranges[0] && ranges[0]._text && ranges[0]._text.includes('T')) {
wvLayer.period = 'subdaily'
} else {
// Subdaily Layers
startDate = moment(start, dateTimeFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')
endDate = moment(end, dateTimeFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')

if (start) {
dateRangeStart.push(startDate)
if (ranges && ranges[0] && ranges[0]._text && ranges[0]._text.endsWith('Y')) {
wvLayer.period = 'yearly'
} else if (ranges && ranges[0] && ranges[0]._text && ranges[0]._text.endsWith('M')) {
wvLayer.period = 'monthly'
} else {
wvLayer.period = 'daily'
}
if (end) {
}
let startDate = moment.min()
let endDate = moment.max()
const dateRangeStart = []
const dateRangeEnd = []
const rangeInterval = []
for (const range of ranges) {
const [start, end, interval] = range._text.split('/')
if (
wvLayer.period === 'daily' ||
wvLayer.period === 'monthly' ||
wvLayer.period === 'yearly'
) {
startDate = moment.min(startDate, moment(start, dateFormat))
endDate = moment.max(endDate, moment(end, dateFormat))
if (start) {
startDate = moment(start, dateFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')
dateRangeStart.push(startDate)
}
if (end) {
endDate = moment(end, dateFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')
}
if (interval !== 'P1D') {
endDate = moment.utc(endDate).add(moment.duration(interval)).format('YYYY-MM-DDTHH:mm:ss[Z]')
// For monthly products subtract 1 day
if (wvLayer.period === 'monthly') {
endDate = moment.utc(endDate).subtract(1, 'day').format('YYYY-MM-DDTHH:mm:ss[Z]')
}
}
const regex = /\d+/g
const match = regex.exec(interval)
rangeInterval.push(match)
if (endDate.endsWith('T00:00:00Z')) {
endDate = endDate.replace('T00:00:00Z', 'T23:59:59Z')
}
dateRangeEnd.push(endDate)
}
} else {
// Subdaily Layers
startDate = moment(start, dateTimeFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')
endDate = moment(end, dateTimeFormat).format('YYYY-MM-DDTHH:mm:ss[Z]')

rangeInterval.push(interval.match(/\d+/)[0])
}
if (start) {
dateRangeStart.push(startDate)
}
if (end) {
dateRangeEnd.push(endDate)
}

wvLayer.startDate = dateRangeStart[0]
wvLayer.endDate = dateRangeEnd[dateRangeEnd.length - 1]
rangeInterval.push(interval.match(/\d+/)[0])
}

if (dateRangeStart.length && dateRangeEnd.length) {
wvLayer.dateRanges = dateRangeStart.map((s, i) => ({
startDate: s,
endDate: dateRangeEnd[i],
dateInterval: rangeInterval[i]
}))
wvLayer.startDate = dateRangeStart[0]
wvLayer.endDate = dateRangeEnd[dateRangeEnd.length - 1]

if (dateRangeStart.length && dateRangeEnd.length) {
wvLayer.dateRanges = dateRangeStart.map((s, i) => ({
startDate: s,
endDate: dateRangeEnd[i],
dateInterval: rangeInterval[i]
}))
}
}
}
} catch (e) {
throw new Error(`Error processing temporal layer: ${e}`)
throw new Error(`Error processing temporal layer ${wvLayer.id}: ${e}`)
}
return wvLayer
}
Expand Down
3 changes: 2 additions & 1 deletion web/js/components/layer/info/info.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default function LayerInfo ({ layer, measurementDescriptionPath }) {
id,
period,
startDate,
ongoing,
} = layer;

const [layerMetadata, setLayerMetadata] = useState();
Expand Down Expand Up @@ -47,7 +48,7 @@ export default function LayerInfo ({ layer, measurementDescriptionPath }) {
const overlapDateRanges = hasLayerDateRange
? dateOverlap(period, dateRanges)
: [];
return hasLayerDateRange && overlapDateRanges.overlap === false;
return hasLayerDateRange && overlapDateRanges.overlap === false && !ongoing;
};

const needDateRanges = getDateOverlapDateRanges();
Expand Down

0 comments on commit 4232035

Please sign in to comment.