diff --git a/.gitignore b/.gitignore index 6e69c7034512eb14eeda2a55dfa035945ea0ebbb..cff4498794615013e2e0594d92ba646a02cff48e 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ app/node_modules .Trashes ehthumbs.db Thumbs.db + +# IDE generated files +.vscode \ No newline at end of file diff --git a/src/components/presentational/FootprintResults.jsx b/src/components/presentational/FootprintResults.jsx index 0cad69dfc327314ad31d0dbee6630d15bfb66fc4..2aacfc3adcd6d69f9d019c76e0c58d96153666d8 100644 --- a/src/components/presentational/FootprintResults.jsx +++ b/src/components/presentational/FootprintResults.jsx @@ -61,12 +61,8 @@ export default function FootprintResults(props) { setCollectionId(newCollectionId); setMatched(featureCollections[newCollectionId].numberMatched); - // Extract the selected collection title - const selectedCollection = props.target.collections.find(collection => collection.id === newCollectionId); - const selectedCollectionTitle = selectedCollection ? selectedCollection.title : ''; - // Call the callback function to pass the selected title to the Sidebar - props.updateSelectedTitle(selectedCollectionTitle); + props.updateAvailableQueriables(props.target.collections.find(col => col.id === newCollectionId).querTitles); props.UpdateQueryableTitles(null); diff --git a/src/components/presentational/SearchAndFilterInput.jsx b/src/components/presentational/SearchAndFilterInput.jsx index 2a27c72569af4882b53ee7ea583922ca24d793b4..9f2a7dd6368970f6d7e77c46708c0a9c3ba7e5cd 100644 --- a/src/components/presentational/SearchAndFilterInput.jsx +++ b/src/components/presentational/SearchAndFilterInput.jsx @@ -147,9 +147,6 @@ export default function SearchAndFilterInput(props) { props.setFilterString(myFilterString); } - // initialize pyGeoAPI flag - let pyGeoAPIFlag = false; - // New state for queryable titles const [queryableTitles, setQueryableTitles] = useState([]); @@ -160,57 +157,11 @@ export default function SearchAndFilterInput(props) { const isInPyAPI = collection.filter(data => data.hasOwnProperty('itemType')); // finds and assigns the selected collection from the PYGEO api - const selectedCollection = isInPyAPI.find(data => data.title === props.selectedTitle); + const selectedCollection = isInPyAPI.find(data => data.title === props.availableQueriables); // retrieves all pyGEO titles const collectionTitles = isInPyAPI.map(data => data.title); - - - // checks if correct title selected - if (collectionTitles.includes(props.selectedTitle)) - { - //set pyGeoAPI flag - pyGeoAPIFlag = true; - - // set the selected link - let QueryableDirectoryLink = selectedCollection.links.find(link => link.rel === "queryables").href; - - // creates URL to get the properties - let QueryableURL = 'https://astrogeology.usgs.gov/pygeoapi/' + QueryableDirectoryLink; - - // fetches URL to get the properties - fetch(QueryableURL) - .then(response => response.json()) - .then(data => { - - let queryableTitlesArray = []; - - // Extract the "properties" property from the JSON response - let Queryables = data.properties; - - // loop over titles - for (const property in Queryables) { - if (Queryables.hasOwnProperty(property) && Queryables[property].hasOwnProperty("title")) { - - queryableTitlesArray.push(data.properties[property].title); - - } - } - - // Set the state with the queryable titles - setQueryableTitles(queryableTitlesArray); - - - }, []) - .catch(error => { - console.error("Error fetching data:", error); - }); - } - - - - const [selectedOptions, setSelectedOptions] = useState([]); const handleOptionChange = event => { @@ -326,7 +277,7 @@ export default function SearchAndFilterInput(props) { <Collapse in={expandFilter}> <div className="panelSection panelBar"> <span> - <FormControl sx={{ minWidth: 150 }}> + <FormControl sx={{ minWidth: 180 }}> <InputLabel id="sortByLabel" size="small"> Sort By </InputLabel> @@ -357,32 +308,35 @@ export default function SearchAndFilterInput(props) { </span> </div> - {pyGeoAPIFlag && ( - <div className="panelSection panelBar"> - <span> - <FormControl sx={{ minWidth: 150 , minHeight: 40}}> - <InputLabel id="selectQueryLabel" size="small" style={{paddingTop: '0.2rem'}}> - Show Properties - </InputLabel> - <Select - labelId="selectQueryLabel" - label="Select Query" - multiple - value={selectedOptions} - onChange={handleOptionChange} - renderValue={(selected) => selected.join(', ')} - style={{height: 43}} - > - {queryableTitles.map((title) => ( - <MenuItem key={title} value={title}> - <Checkbox checked={selectedOptions.includes(title)} /> - <ListItemText primary={title} /> - </MenuItem> - ))} - </Select> - </FormControl> - </span> - </div> + {props.availableQueriables.length > 0 && ( + <> + <Divider/> + <div className="panelSection panelBar"> + <span> + <FormControl sx={{ minWidth: 180 , minHeight: 40}}> + <InputLabel id="showPropertiesLabel" size="small" style={{paddingTop: '0.2rem'}}> + Show Properties + </InputLabel> + <Select + labelId="showPropertiesLabel" + label="Show Properties" + multiple + value={selectedOptions} + onChange={handleOptionChange} + renderValue={(selected) => selected.join(', ')} + style={{height: 43}} + > + {props.availableQueriables.map((title) => ( + <MenuItem key={title} value={title}> + <Checkbox checked={selectedOptions.includes(title)} /> + <ListItemText primary={title} /> + </MenuItem> + ))} + </Select> + </FormControl> + </span> + </div> + </> )} <Divider/> diff --git a/src/components/presentational/Sidebar.jsx b/src/components/presentational/Sidebar.jsx index 6e26f8346724845b3f44642687360e008413e166..ea9a031dca3850ed1f64a4f139d0443f3c3d445c 100644 --- a/src/components/presentational/Sidebar.jsx +++ b/src/components/presentational/Sidebar.jsx @@ -44,11 +44,12 @@ export default function Sidebar(props) { }; // State to hold the selected title - const [selectedTitle, setSelectedTitle] = React.useState(""); + const [availableQueriables, setAvailableQueriables] = React.useState(""); // Callback function to update selected title - const updateSelectedTitle = (newTitle) => { - setSelectedTitle(newTitle); + const updateAvailableQueriables = (queriables) => { + console.log(queriables); + setAvailableQueriables(queriables); }; // State to hold the seleced queryables @@ -72,7 +73,7 @@ export default function Sidebar(props) { setFilterString={setFilterString} targetName={props.target.name} target={props.target} - selectedTitle={selectedTitle} + availableQueriables={availableQueriables} UpdateQueryableTitles = {UpdateQueryableTitles} /> <FootprintResults @@ -80,7 +81,7 @@ export default function Sidebar(props) { filterString={filterString} queryAddress={props.queryAddress} setQueryAddress={props.setQueryAddress} - updateSelectedTitle={updateSelectedTitle} + updateAvailableQueriables={updateAvailableQueriables} selectedQueryables = {updatedQueryableTitles} UpdateQueryableTitles = {UpdateQueryableTitles} /> diff --git a/src/js/FetchData.js b/src/js/FetchData.js index 6224fac81b448e910afa7337daf746829fa17e5a..75527bfae87b33653ce3815b20169639f68704dd 100644 --- a/src/js/FetchData.js +++ b/src/js/FetchData.js @@ -65,7 +65,7 @@ export default async function Initialize(){ } // Combine data from Astro Web Maps and STAC API into one new object - function organizeData(astroWebMaps, stacApiCollections, vectorApiCollections) { + async function organizeData(astroWebMaps, stacApiCollections, vectorApiCollections) { // Initialize Objects let mapList = { "systems" : [] }; @@ -97,6 +97,8 @@ export default async function Initialize(){ let sysIndex = mapList.systems.map(sys => sys.name).indexOf(target.system); // ID the system. This seems to get the main planet of the system. + // https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html + // "A planet is always considered to be the 99th satellite of its own barycenter" if (target.naif % 100 === 99){ mapList.systems[sysIndex].naif = target.naif; } @@ -113,7 +115,9 @@ export default async function Initialize(){ for (const collection of stacApiCollections.collections){ if (target.name == collection.summaries["ssys:targets"][0].toUpperCase()) { // Add a specification to the title in order to show what kind of data the user is requesting - collection.title = collection.title.concat(" (Raster)") + collection.dataType = "raster"; + collection.querTitles = []; + collection.title = collection.title.concat(" (Raster)"); myCollections.push(collection); } } @@ -122,8 +126,33 @@ export default async function Initialize(){ // view the collection as GEOJSON let target_name = pycollection.id.split('/')[0]; if (target.name == target_name.toUpperCase()) { + + // Set links GeoSTAC needs later pycollection.links.find(link => link.rel === "items").href = "https://astrogeology.usgs.gov/pygeoapi" + pycollection.links.find(link => link.rel === "items").href; + pycollection.itemsLink = "https://astrogeology.usgs.gov/pygeoapi" + pycollection.links.find(link => link.rel === "items").href; + pycollection.queryablesLink = "https://astrogeology.usgs.gov/pygeoapi" + pycollection.links.find(link => link.rel === "queryables").href; + + // Fetch and await queriables + fetchStatus[pycollection.queryablesLink] = "Not Started"; + fetchPromise[pycollection.queryablesLink] = "Not Started"; + jsonPromise[pycollection.queryablesLink] = "Not Started"; + mapsJson[pycollection.queryablesLink] = []; + ensureFetched(pycollection.queryablesLink); + await ensureFetched(pycollection.queryablesLink); + + // put queryable titles in array + let querData = mapsJson[pycollection.queryablesLink]; + let querTitles = []; + let querProps = querData.properties; + for (const property in querProps) { + if (querProps.hasOwnProperty(property) && querProps[property].hasOwnProperty("title")) { + querTitles.push(querData.properties[property].title); + } + } + // Add a specification to the title in order to show what kind of data the user is requesting + pycollection.dataType = "vector"; + pycollection.querTitles = querTitles; pycollection.title = pycollection.title.concat(" (Vector)"); myCollections.push(pycollection); } @@ -228,7 +257,9 @@ export default async function Initialize(){ await ensureFetched(stacApiCollections); await ensureFetched(vectorApiCollections); - return organizeData(mapsJson[astroWebMaps], mapsJson[stacApiCollections], mapsJson[vectorApiCollections]); + let organizedData = await organizeData(mapsJson[astroWebMaps], mapsJson[stacApiCollections], mapsJson[vectorApiCollections]); + + return organizedData; } aggregateMapList = await getStacAndAstroWebMapsData();