From e9eac6f4bfeb2cddc9d5c5a5a77d6a23ee358b27 Mon Sep 17 00:00:00 2001 From: Hanbyul Jo Date: Wed, 20 Sep 2023 14:58:40 -0400 Subject: [PATCH 1/4] Use collection endpoint instead of search for analysis page --- .../analysis/define/use-stac-search.ts | 73 ++++++++------- package.json | 2 + yarn.lock | 92 ++++++++++++++++++- 3 files changed, 129 insertions(+), 38 deletions(-) diff --git a/app/scripts/components/analysis/define/use-stac-search.ts b/app/scripts/components/analysis/define/use-stac-search.ts index 3e0f9481d..98f8c4db3 100644 --- a/app/scripts/components/analysis/define/use-stac-search.ts +++ b/app/scripts/components/analysis/define/use-stac-search.ts @@ -1,10 +1,13 @@ import { DatasetLayer } from 'veda'; import { FeatureCollection, Polygon } from 'geojson'; import { useEffect, useState } from 'react'; -import { uniq } from 'lodash'; import axios from 'axios'; -import { getFilterPayload } from '../utils'; +import booleanIntersects from '@turf/boolean-intersects'; +import bboxPolygon from '@turf/bbox-polygon'; +import { areIntervalsOverlapping } from 'date-fns'; + import { allAvailableDatasetsLayers } from '.'; +import { utcString2userTzDate } from '$utils/date'; import { ActionStatus, S_FAILED, @@ -22,7 +25,6 @@ interface UseStacSearchProps { export function useStacSearch({ start, end, aoi }: UseStacSearchProps) { const readyToLoadDatasets = !!(start && end && aoi); - const [selectableDatasetLayers, setSelectableDatasetLayers] = useState< DatasetLayer[] >([]); @@ -37,43 +39,44 @@ export function useStacSearch({ start, end, aoi }: UseStacSearchProps) { const load = async () => { setStacSearchStatus(S_LOADING); try { - const url = `${process.env.API_STAC_ENDPOINT}/search`; - - const allAvailableDatasetsLayersSTACIds = allAvailableDatasetsLayers.map( - (layer) => layer.stacCol - ); - const payload = { - 'filter-lang': 'cql2-json', - filter: getFilterPayload( - start, - end, - aoi, - allAvailableDatasetsLayersSTACIds - ), - limit: 100, - fields: { - exclude: [ - 'links', - 'assets', - 'bbox', - 'geometry', - 'properties', - 'stac_extensions', - 'stac_version', - 'type' - ] - } - }; - const response = await axios.post(url, payload, { + const collectionUrl = `${process.env.API_STAC_ENDPOINT}/collections`; + const collectionResponse = await axios.get(collectionUrl, { signal: controller.signal }); + + const matchingCollectionIds = collectionResponse.data.collections + .filter( + (col) => col.extent.spatial.bbox && col.extent.temporal.interval + ) + .map((col) => { + return { + id: col.id, + bbox: col.extent.spatial.bbox[0], // Check + start: utcString2userTzDate(col.extent.temporal.interval[0][0]), + end: utcString2userTzDate(col.extent.temporal.interval[0][1]) + }; + }) + .filter((col) => { + return ( + aoi.features.some((feature) => + booleanIntersects(feature, bboxPolygon(col.bbox)) + ) && + areIntervalsOverlapping( + { start: new Date(start), end: new Date(end) }, + { + start: new Date(col.start), + end: new Date(col.end) + } + ) + ); + }) + .map((c) => c.id); + setStacSearchStatus(S_SUCCEEDED); - const itemsParentCollections: string[] = uniq( - response.data.features.map((feature) => feature.collection) - ); + setSelectableDatasetLayers( allAvailableDatasetsLayers.filter((l) => - itemsParentCollections.includes(l.stacCol) + matchingCollectionIds.includes(l.stacCol) ) ); } catch (error) { diff --git a/package.json b/package.json index c13932149..cec2d9cd4 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,8 @@ "@tippyjs/react": "^4.2.6", "@turf/area": "^6.5.0", "@turf/bbox": "^6.5.0", + "@turf/bbox-polygon": "^6.5.0", + "@turf/boolean-intersects": "^6.5.0", "@turf/centroid": "^6.5.0", "@turf/simplify": "^6.5.0", "@turf/union": "^6.5.0", diff --git a/yarn.lock b/yarn.lock index c20d61031..2743ae5a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3058,7 +3058,14 @@ "@turf/helpers" "^6.5.0" "@turf/meta" "^6.5.0" -"@turf/bbox@^6.5.0": +"@turf/bbox-polygon@^6.5.0": + version "6.5.0" + resolved "http://verdaccio.ds.io:4873/@turf%2fbbox-polygon/-/bbox-polygon-6.5.0.tgz#f18128b012eedfa860a521d8f2b3779cc0801032" + integrity sha512-+/r0NyL1lOG3zKZmmf6L8ommU07HliP4dgYToMoTxqzsWzyLjaj/OzgQ8rBmv703WJX+aS6yCmLuIhYqyufyuw== + dependencies: + "@turf/helpers" "^6.5.0" + +"@turf/bbox@*", "@turf/bbox@^6.5.0": version "6.5.0" resolved "http://verdaccio.ds.io:4873/@turf%2fbbox/-/bbox-6.5.0.tgz#bec30a744019eae420dac9ea46fb75caa44d8dc5" integrity sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw== @@ -3066,6 +3073,34 @@ "@turf/helpers" "^6.5.0" "@turf/meta" "^6.5.0" +"@turf/boolean-disjoint@^6.5.0": + version "6.5.0" + resolved "http://verdaccio.ds.io:4873/@turf%2fboolean-disjoint/-/boolean-disjoint-6.5.0.tgz#e291d8f8f8cce7f7bb3c11e23059156a49afc5e4" + integrity sha512-rZ2ozlrRLIAGo2bjQ/ZUu4oZ/+ZjGvLkN5CKXSKBcu6xFO6k2bgqeM8a1836tAW+Pqp/ZFsTA5fZHsJZvP2D5g== + dependencies: + "@turf/boolean-point-in-polygon" "^6.5.0" + "@turf/helpers" "^6.5.0" + "@turf/line-intersect" "^6.5.0" + "@turf/meta" "^6.5.0" + "@turf/polygon-to-line" "^6.5.0" + +"@turf/boolean-intersects@^6.5.0": + version "6.5.0" + resolved "http://verdaccio.ds.io:4873/@turf%2fboolean-intersects/-/boolean-intersects-6.5.0.tgz#df2b831ea31a4574af6b2fefe391f097a926b9d6" + integrity sha512-nIxkizjRdjKCYFQMnml6cjPsDOBCThrt+nkqtSEcxkKMhAQj5OO7o2CecioNTaX8EayqwMGVKcsz27oP4mKPTw== + dependencies: + "@turf/boolean-disjoint" "^6.5.0" + "@turf/helpers" "^6.5.0" + "@turf/meta" "^6.5.0" + +"@turf/boolean-point-in-polygon@^6.5.0": + version "6.5.0" + resolved "http://verdaccio.ds.io:4873/@turf%2fboolean-point-in-polygon/-/boolean-point-in-polygon-6.5.0.tgz#6d2e9c89de4cd2e4365004c1e51490b7795a63cf" + integrity sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A== + dependencies: + "@turf/helpers" "^6.5.0" + "@turf/invariant" "^6.5.0" + "@turf/centroid@^6.5.0": version "6.5.0" resolved "http://verdaccio.ds.io:4873/@turf%2fcentroid/-/centroid-6.5.0.tgz#ecaa365412e5a4d595bb448e7dcdacfb49eb0009" @@ -3089,7 +3124,7 @@ dependencies: "@turf/helpers" "^6.5.0" -"@turf/helpers@^6.5.0": +"@turf/helpers@6.x", "@turf/helpers@^6.5.0": version "6.5.0" resolved "http://verdaccio.ds.io:4873/@turf%2fhelpers/-/helpers-6.5.0.tgz#f79af094bd6b8ce7ed2bd3e089a8493ee6cae82e" integrity sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw== @@ -3101,13 +3136,41 @@ dependencies: "@turf/helpers" "^6.5.0" -"@turf/meta@^6.5.0": +"@turf/line-intersect@^6.5.0": + version "6.5.0" + resolved "http://verdaccio.ds.io:4873/@turf%2fline-intersect/-/line-intersect-6.5.0.tgz#dea48348b30c093715d2195d2dd7524aee4cf020" + integrity sha512-CS6R1tZvVQD390G9Ea4pmpM6mJGPWoL82jD46y0q1KSor9s6HupMIo1kY4Ny+AEYQl9jd21V3Scz20eldpbTVA== + dependencies: + "@turf/helpers" "^6.5.0" + "@turf/invariant" "^6.5.0" + "@turf/line-segment" "^6.5.0" + "@turf/meta" "^6.5.0" + geojson-rbush "3.x" + +"@turf/line-segment@^6.5.0": + version "6.5.0" + resolved "http://verdaccio.ds.io:4873/@turf%2fline-segment/-/line-segment-6.5.0.tgz#ee73f3ffcb7c956203b64ed966d96af380a4dd65" + integrity sha512-jI625Ho4jSuJESNq66Mmi290ZJ5pPZiQZruPVpmHkUw257Pew0alMmb6YrqYNnLUuiVVONxAAKXUVeeUGtycfw== + dependencies: + "@turf/helpers" "^6.5.0" + "@turf/invariant" "^6.5.0" + "@turf/meta" "^6.5.0" + +"@turf/meta@6.x", "@turf/meta@^6.5.0": version "6.5.0" resolved "http://verdaccio.ds.io:4873/@turf%2fmeta/-/meta-6.5.0.tgz#b725c3653c9f432133eaa04d3421f7e51e0418ca" integrity sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA== dependencies: "@turf/helpers" "^6.5.0" +"@turf/polygon-to-line@^6.5.0": + version "6.5.0" + resolved "http://verdaccio.ds.io:4873/@turf%2fpolygon-to-line/-/polygon-to-line-6.5.0.tgz#4dc86db66168b32bb83ce448cf966208a447d952" + integrity sha512-5p4n/ij97EIttAq+ewSnKt0ruvuM+LIDzuczSzuHTpq4oS7Oq8yqg5TQ4nzMVuK41r/tALCk7nAoBuw3Su4Gcw== + dependencies: + "@turf/helpers" "^6.5.0" + "@turf/invariant" "^6.5.0" + "@turf/simplify@^6.5.0": version "6.5.0" resolved "http://verdaccio.ds.io:4873/@turf%2fsimplify/-/simplify-6.5.0.tgz#ec435460bde0985b781618b05d97146c32c8bc16" @@ -3421,6 +3484,11 @@ resolved "http://verdaccio.ds.io:4873/@types%2fgeojson/-/geojson-7946.0.10.tgz#6dfbf5ea17142f7f9a043809f1cd4c448cb68249" integrity sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA== +"@types/geojson@7946.0.8": + version "7946.0.8" + resolved "http://verdaccio.ds.io:4873/@types%2fgeojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca" + integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA== + "@types/graceful-fs@^4.1.3": version "4.1.5" resolved "http://verdaccio.ds.io:4873/@types%2fgraceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -6560,6 +6628,17 @@ geojson-flatten@^1.0.4: resolved "http://verdaccio.ds.io:4873/geojson-flatten/-/geojson-flatten-1.1.1.tgz#601aae07ba6406281ebca683573dcda69eba04c7" integrity sha512-k/6BCd0qAt7vdqdM1LkLfAy72EsLDy0laNwX0x2h49vfYCiQkRc4PSra8DNEdJ10EKRpwEvDXMb0dBknTJuWpQ== +geojson-rbush@3.x: + version "3.2.0" + resolved "http://verdaccio.ds.io:4873/geojson-rbush/-/geojson-rbush-3.2.0.tgz#8b543cf0d56f99b78faf1da52bb66acad6dfc290" + integrity sha512-oVltQTXolxvsz1sZnutlSuLDEcQAKYC/uXt9zDzJJ6bu0W+baTI8LZBaTup5afzibEH4N3jlq2p+a152wlBJ7w== + dependencies: + "@turf/bbox" "*" + "@turf/helpers" "6.x" + "@turf/meta" "6.x" + "@types/geojson" "7946.0.8" + rbush "^3.0.1" + geojson-validation@^1.0.2: version "1.0.2" resolved "http://verdaccio.ds.io:4873/geojson-validation/-/geojson-validation-1.0.2.tgz#5c11a83afbec9a1cb9d76c73d47843dbd154d3ff" @@ -10509,6 +10588,13 @@ raf@^3.1.0: dependencies: performance-now "^2.1.0" +rbush@^3.0.1: + version "3.0.1" + resolved "http://verdaccio.ds.io:4873/rbush/-/rbush-3.0.1.tgz#5fafa8a79b3b9afdfe5008403a720cc1de882ecf" + integrity sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w== + dependencies: + quickselect "^2.0.0" + react-calendar@^3.3.0: version "3.7.0" resolved "http://verdaccio.ds.io:4873/react-calendar/-/react-calendar-3.7.0.tgz#951d56e91afb33b1c1e019cb790349fbffcc6894" From f8329226d7bdf9144e59a64828f3701ee2d0f526 Mon Sep 17 00:00:00 2001 From: Hanbyul Jo Date: Thu, 21 Sep 2023 15:55:53 -0400 Subject: [PATCH 2/4] Change hook name to reflect the change of codebase --- app/scripts/components/analysis/define/index.tsx | 12 +++++++++--- ...-stac-search.ts => use-stac-collection-search.ts} | 0 2 files changed, 9 insertions(+), 3 deletions(-) rename app/scripts/components/analysis/define/{use-stac-search.ts => use-stac-collection-search.ts} (100%) diff --git a/app/scripts/components/analysis/define/index.tsx b/app/scripts/components/analysis/define/index.tsx index 4c8583e09..789f1615e 100644 --- a/app/scripts/components/analysis/define/index.tsx +++ b/app/scripts/components/analysis/define/index.tsx @@ -25,7 +25,7 @@ import { datasets, DatasetLayer, VedaDatum, DatasetData } from 'veda'; import { useAnalysisParams } from '../results/use-analysis-params'; import AoiSelector from './aoi-selector'; import PageHeroActions from './page-hero-actions'; -import { useStacSearch } from './use-stac-search'; +import { useStacCollectionSearch } from './use-stac-collection-search'; import { variableGlsp } from '$styles/variable-utils'; import { PageMainContent } from '$styles/page'; @@ -184,7 +184,11 @@ export default function Analysis() { ); const { selectableDatasetLayers, stacSearchStatus, readyToLoadDatasets } = - useStacSearch({ start, end, aoi: aoiDrawState.featureCollection }); + useStacCollectionSearch({ + start, + end, + aoi: aoiDrawState.featureCollection + }); // Update datasetsLayers when stac search is refreshed in case some // datasetsLayers are not available anymore @@ -367,7 +371,9 @@ export default function Analysis() { false } > - From: {findParentDataset(datasetLayer.id)?.name} + + From: {findParentDataset(datasetLayer.id)?.name} + {datasetLayer.name} ))} diff --git a/app/scripts/components/analysis/define/use-stac-search.ts b/app/scripts/components/analysis/define/use-stac-collection-search.ts similarity index 100% rename from app/scripts/components/analysis/define/use-stac-search.ts rename to app/scripts/components/analysis/define/use-stac-collection-search.ts From 5eaa81961161045696174076fc0123d49811fd54 Mon Sep 17 00:00:00 2001 From: Hanbyul Jo Date: Thu, 21 Sep 2023 15:56:56 -0400 Subject: [PATCH 3/4] Use react query to fetch collection data --- .../define/use-stac-collection-search.ts | 111 ++++++++++-------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/app/scripts/components/analysis/define/use-stac-collection-search.ts b/app/scripts/components/analysis/define/use-stac-collection-search.ts index 98f8c4db3..4f63f08d1 100644 --- a/app/scripts/components/analysis/define/use-stac-collection-search.ts +++ b/app/scripts/components/analysis/define/use-stac-collection-search.ts @@ -2,6 +2,7 @@ import { DatasetLayer } from 'veda'; import { FeatureCollection, Polygon } from 'geojson'; import { useEffect, useState } from 'react'; import axios from 'axios'; +import { useQuery } from '@tanstack/react-query'; import booleanIntersects from '@turf/boolean-intersects'; import bboxPolygon from '@turf/bbox-polygon'; import { areIntervalsOverlapping } from 'date-fns'; @@ -22,7 +23,13 @@ interface UseStacSearchProps { aoi?: FeatureCollection | null; } -export function useStacSearch({ start, end, aoi }: UseStacSearchProps) { +const collectionUrl = `${process.env.API_STAC_ENDPOINT}/collections`; + +export function useStacCollectionSearch({ + start, + end, + aoi +}: UseStacSearchProps) { const readyToLoadDatasets = !!(start && end && aoi); const [selectableDatasetLayers, setSelectableDatasetLayers] = useState< @@ -32,66 +39,66 @@ export function useStacSearch({ start, end, aoi }: UseStacSearchProps) { const [stacSearchStatus, setStacSearchStatus] = useState(S_IDLE); - useEffect(() => { - if (!readyToLoadDatasets) return; - const controller = new AbortController(); - - const load = async () => { + const { data: collectionData } = useQuery({ + queryKey: ['stacCollection'], + queryFn: async ({ signal }) => { setStacSearchStatus(S_LOADING); try { - const collectionUrl = `${process.env.API_STAC_ENDPOINT}/collections`; const collectionResponse = await axios.get(collectionUrl, { - signal: controller.signal + signal }); - - const matchingCollectionIds = collectionResponse.data.collections - .filter( - (col) => col.extent.spatial.bbox && col.extent.temporal.interval - ) - .map((col) => { - return { - id: col.id, - bbox: col.extent.spatial.bbox[0], // Check - start: utcString2userTzDate(col.extent.temporal.interval[0][0]), - end: utcString2userTzDate(col.extent.temporal.interval[0][1]) - }; - }) - .filter((col) => { - return ( - aoi.features.some((feature) => - booleanIntersects(feature, bboxPolygon(col.bbox)) - ) && - areIntervalsOverlapping( - { start: new Date(start), end: new Date(end) }, - { - start: new Date(col.start), - end: new Date(col.end) - } - ) - ); - }) - .map((c) => c.id); - setStacSearchStatus(S_SUCCEEDED); - - setSelectableDatasetLayers( - allAvailableDatasetsLayers.filter((l) => - matchingCollectionIds.includes(l.stacCol) - ) - ); - } catch (error) { - if (!controller.signal.aborted) { + return collectionResponse.data.collections; + } catch (e) { + if (!signal?.aborted) { setStacSearchStatus(S_FAILED); } } - }; - - load(); + }, + enabled: readyToLoadDatasets + }); - return () => { - controller.abort(); - }; - }, [start, end, aoi, readyToLoadDatasets]); + useEffect(() => { + if (!collectionData || !readyToLoadDatasets) return; + try { + setStacSearchStatus(S_LOADING); + const matchingCollectionIds = collectionData + .filter( + (col) => col.extent.spatial.bbox && col.extent.temporal.interval + ) + .map((col) => { + return { + id: col.id, + bbox: col.extent.spatial.bbox[0], + start: utcString2userTzDate(col.extent.temporal.interval[0][0]), + end: utcString2userTzDate(col.extent.temporal.interval[0][1]) + }; + }) + .filter((col) => { + return ( + aoi.features.some((feature) => + booleanIntersects(feature, bboxPolygon(col.bbox)) + ) && + areIntervalsOverlapping( + { start: new Date(start), end: new Date(end) }, + { + start: new Date(col.start), + end: new Date(col.end) + } + ) + ); + }) + .map((c) => c.id); + setSelectableDatasetLayers( + allAvailableDatasetsLayers.filter((l) => + matchingCollectionIds.includes(l.stacCol) + ) + ); + } catch (e) { + setStacSearchStatus(S_FAILED); + } + setStacSearchStatus(S_SUCCEEDED); + }, [collectionData, start, end, aoi, readyToLoadDatasets]); return { selectableDatasetLayers, stacSearchStatus, readyToLoadDatasets }; } From 4e395e44858bc9a8f717a156861261a3c3142757 Mon Sep 17 00:00:00 2001 From: Daniel da Silva Date: Fri, 22 Sep 2023 15:05:10 +0100 Subject: [PATCH 4/4] Simplify use Stac Collection --- .../define/use-stac-collection-search.ts | 133 +++++++++--------- 1 file changed, 65 insertions(+), 68 deletions(-) diff --git a/app/scripts/components/analysis/define/use-stac-collection-search.ts b/app/scripts/components/analysis/define/use-stac-collection-search.ts index 4f63f08d1..2fed3097f 100644 --- a/app/scripts/components/analysis/define/use-stac-collection-search.ts +++ b/app/scripts/components/analysis/define/use-stac-collection-search.ts @@ -1,6 +1,5 @@ -import { DatasetLayer } from 'veda'; +import { useMemo } from 'react'; import { FeatureCollection, Polygon } from 'geojson'; -import { useEffect, useState } from 'react'; import axios from 'axios'; import { useQuery } from '@tanstack/react-query'; import booleanIntersects from '@turf/boolean-intersects'; @@ -8,14 +7,8 @@ import bboxPolygon from '@turf/bbox-polygon'; import { areIntervalsOverlapping } from 'date-fns'; import { allAvailableDatasetsLayers } from '.'; + import { utcString2userTzDate } from '$utils/date'; -import { - ActionStatus, - S_FAILED, - S_IDLE, - S_LOADING, - S_SUCCEEDED -} from '$utils/status'; interface UseStacSearchProps { start?: Date; @@ -32,73 +25,77 @@ export function useStacCollectionSearch({ }: UseStacSearchProps) { const readyToLoadDatasets = !!(start && end && aoi); - const [selectableDatasetLayers, setSelectableDatasetLayers] = useState< - DatasetLayer[] - >([]); - - const [stacSearchStatus, setStacSearchStatus] = - useState(S_IDLE); - - const { data: collectionData } = useQuery({ + const result = useQuery({ queryKey: ['stacCollection'], queryFn: async ({ signal }) => { - setStacSearchStatus(S_LOADING); - try { - const collectionResponse = await axios.get(collectionUrl, { - signal - }); - setStacSearchStatus(S_SUCCEEDED); - return collectionResponse.data.collections; - } catch (e) { - if (!signal?.aborted) { - setStacSearchStatus(S_FAILED); - } - } + const collectionResponse = await axios.get(collectionUrl, { + signal + }); + return collectionResponse.data.collections; }, enabled: readyToLoadDatasets }); - useEffect(() => { - if (!collectionData || !readyToLoadDatasets) return; + const selectableDatasetLayers = useMemo(() => { try { - setStacSearchStatus(S_LOADING); - const matchingCollectionIds = collectionData - .filter( - (col) => col.extent.spatial.bbox && col.extent.temporal.interval - ) - .map((col) => { - return { - id: col.id, - bbox: col.extent.spatial.bbox[0], - start: utcString2userTzDate(col.extent.temporal.interval[0][0]), - end: utcString2userTzDate(col.extent.temporal.interval[0][1]) - }; - }) - .filter((col) => { - return ( - aoi.features.some((feature) => - booleanIntersects(feature, bboxPolygon(col.bbox)) - ) && - areIntervalsOverlapping( - { start: new Date(start), end: new Date(end) }, - { - start: new Date(col.start), - end: new Date(col.end) - } - ) - ); - }) - .map((c) => c.id); - setSelectableDatasetLayers( - allAvailableDatasetsLayers.filter((l) => - matchingCollectionIds.includes(l.stacCol) - ) - ); + return getInTemporalAndSpatialExtent(result.data, aoi, { + start, + end + }); } catch (e) { - setStacSearchStatus(S_FAILED); + return []; + } + }, [result.data, aoi, start, end]); + + return { + selectableDatasetLayers: selectableDatasetLayers, + stacSearchStatus: result.status, + readyToLoadDatasets + }; +} + +function getInTemporalAndSpatialExtent(collectionData, aoi, timeRange) { + const matchingCollectionIds = collectionData.reduce((acc, col) => { + const id = col.id; + + // Is is a dataset defined in the app? + // If not, skip other calculations. + const isAppDataset = allAvailableDatasetsLayers.some( + (l) => l.stacCol === id + ); + + if ( + !isAppDataset || + !col.extent.spatial.bbox || + !col.extent.temporal.interval + ) { + return acc; + } + + const bbox = col.extent.spatial.bbox[0]; + const start = utcString2userTzDate(col.extent.temporal.interval[0][0]); + const end = utcString2userTzDate(col.extent.temporal.interval[0][1]); + + const isInAOI = aoi.features.some((feature) => + booleanIntersects(feature, bboxPolygon(bbox)) + ); + + const isInTOI = areIntervalsOverlapping( + { start: new Date(timeRange.start), end: new Date(timeRange.end) }, + { + start: new Date(start), + end: new Date(end) + } + ); + + if (isInAOI && isInTOI) { + return [...acc, id]; + } else { + return acc; } - setStacSearchStatus(S_SUCCEEDED); - }, [collectionData, start, end, aoi, readyToLoadDatasets]); + }, []); - return { selectableDatasetLayers, stacSearchStatus, readyToLoadDatasets }; + return allAvailableDatasetsLayers.filter((l) => + matchingCollectionIds.includes(l.stacCol) + ); }