diff --git a/src/components/Interactive.js b/src/components/Interactive.js new file mode 100644 index 0000000000000000000000000000000000000000..9ba219db463f3dc15c3ff14fea76442992a3a822 --- /dev/null +++ b/src/components/Interactive.js @@ -0,0 +1,6 @@ +import React from "react"; +import { Alert } from "react-bootstrap"; + +export default function Interactive() { + return <Alert variant="info">This service is under development!</Alert>; +} diff --git a/src/components/Rucio.js b/src/components/Rucio.js new file mode 100644 index 0000000000000000000000000000000000000000..22e27122d5931b78a1cc6d9b88f52e063b89ed0b --- /dev/null +++ b/src/components/Rucio.js @@ -0,0 +1,13 @@ +import React from "react"; +import { Alert } from "react-bootstrap"; + +export default function Rucio() { + return ( + <Alert variant="warning"> + <p>You will leave ESAP GUI and be redirected to</p> + <a target="_blank" href="https://escape-dios-dl.cern.ch/ui/"> + Rucio Web UI + </a> + </Alert> + ); +} diff --git a/src/components/archives/ArchiveDetails.js b/src/components/archives/ArchiveDetails.js index fa5e2759f7f3762805d243068fb24a3203407bfa..9ac3f575b9c86d70dadaf4a61da50d5b033ffa68 100644 --- a/src/components/archives/ArchiveDetails.js +++ b/src/components/archives/ArchiveDetails.js @@ -1,23 +1,23 @@ import React, { useContext } from "react"; import { useParams } from "react-router-dom"; import { GlobalContext } from "../../contexts/GlobalContext"; -import { Container, Row, Col, Card, Table, Alert, Image } from "react-bootstrap"; +import { + Container, + Row, + Col, + Card, + Table, + Alert, + Image, +} from "react-bootstrap"; import DataProductCategories from "./DataProductCategories"; export default function ArchiveDetails(props) { const { uri } = useParams(); console.log(uri); - const { archives, defaultConfigName, setConfigName } = useContext(GlobalContext); + const { archives } = useContext(GlobalContext); if (!archives) return null; - /* This is a nasty hack. There must be a better way! */ - if (uri.search("zooniverse") >= 0){ - setConfigName("zooniverse"); - } - else{ - setConfigName(defaultConfigName); - } - const archive = archives.find((archive) => archive.uri === uri); if (!archive) return <Alert variant="danger">No Archive found!</Alert>; console.log(archive); @@ -46,15 +46,19 @@ export default function ArchiveDetails(props) { </tbody> </Table> <Card> - <Image - className="mx-auto d-block" - src={archive.thumbnail} - alt="" - rounded - fluid - /> - <Card.Title className="text-center h4 pt-3">{archive.short_description}</Card.Title> - <Card.Text className="text-justify m-3">{archive.long_description}</Card.Text> + <Image + className="mx-auto d-block" + src={archive.thumbnail} + alt="" + rounded + fluid + /> + <Card.Title className="text-center h4 pt-3"> + {archive.short_description} + </Card.Title> + <Card.Text className="text-justify m-3"> + {archive.long_description} + </Card.Text> </Card> </Card.Body> </Card> diff --git a/src/components/archives/Archives.js b/src/components/archives/Archives.js index a53113a9c2846f1adcf2410c40ca3bf47dda8fa0..f2148c055ddd5cfab06cfe00ec15b63f65f5be7c 100644 --- a/src/components/archives/Archives.js +++ b/src/components/archives/Archives.js @@ -1,23 +1,19 @@ import React, { useContext } from "react"; -import { CardColumns} from "react-bootstrap"; +import { CardColumns } from "react-bootstrap"; import ArchiveCard from "./ArchiveCard"; import { GlobalContext } from "../../contexts/GlobalContext"; export function Archives() { - const { archives, defaultConfigName, setConfigName} = useContext(GlobalContext); + const { archives } = useContext(GlobalContext); if (!archives) return null; - setConfigName(defaultConfigName); - console.log("archives: ", { archives }); return ( <CardColumns className="row-2"> - {archives.map((archive) => { - let key = "archive-" + archive.id; - return ( - <ArchiveCard key={key} archive={archive} /> - ); - })} + {archives.map((archive) => { + let key = "archive-" + archive.id; + return <ArchiveCard key={key} archive={archive} />; + })} </CardColumns> ); } diff --git a/src/components/archives/DataProductCategories.js b/src/components/archives/DataProductCategories.js index 3846156353758d54215d96e93c8d37161a02f970..d7f4d71f5be66d7bcf2a123e35784e95ad746f56 100644 --- a/src/components/archives/DataProductCategories.js +++ b/src/components/archives/DataProductCategories.js @@ -1,12 +1,6 @@ import React, { useState, useContext, useEffect } from "react"; import { NavLink } from "react-router-dom"; -import { - ListGroup, - Card, - Button, - Row, - Col, -} from "react-bootstrap"; +import { ListGroup, Card, Button, Row, Col } from "react-bootstrap"; import { GlobalContext } from "../../contexts/GlobalContext"; import axios from "axios"; @@ -37,13 +31,15 @@ export default function DataProductCategories({ archive }) { {categories .filter((category) => archive.datasets.includes(category.uri)) .map((category) => { - console.log(category); + console.log("category:", category); let button; let extra_info; let documentation; if (category.service_connector) { + let query_url = `${category.archive_uri_derived}/query`; + console.log("query_url:", query_url); button = ( - <Button as={NavLink} variant="outline-info" to="/query"> + <Button as={NavLink} variant="outline-info" to={query_url}> Browse Catalog & Run Queries </Button> ); diff --git a/src/components/query/QueryCatalogs.js b/src/components/query/QueryCatalogs.js index c5709c393b687fb1cf5c41bd34fbbb0466296052..a7554b7e7601288333cc71f8bf1c7eb2f42874b2 100644 --- a/src/components/query/QueryCatalogs.js +++ b/src/components/query/QueryCatalogs.js @@ -1,4 +1,5 @@ import React, { useContext, useEffect } from "react"; +import { useParams } from "react-router-dom"; import axios from "axios"; import { Container } from "react-bootstrap"; import Form from "react-jsonschema-form"; @@ -14,16 +15,38 @@ export default function QueryCatalogs() { // "status": "fetching|fechted", // "results": null} const { queryMap, formData, setFormData } = useContext(QueryContext); - const { config, api_host } = useContext(GlobalContext); + const { config, api_host, setConfigName } = useContext(GlobalContext); + const { uri } = useParams(); + console.log(uri); - console.log(config.query_schema); + // set ConfigName for archive useEffect(() => { + switch (uri) { + case "adex": + setConfigName("adex"); + break; + case "apertif": + setConfigName("apertif"); + break; + case "zooniverse": + setConfigName("zooniverse"); + break; + case "astron_vo": + setConfigName("astron_vo"); + break; + case "lofar": + setConfigName("lofar"); + break; + default: + setConfigName("esap_ivoa"); + } + }, [uri]); + + useEffect(() => { + console.log(config.query_schema); if (!formData) return; - let catalogs = config.query_schema.properties.catalog.enum.filter( - (name) => name !== "all" - ); let gui = config.query_schema.name; - const queries = parseQueryForm(gui, formData, catalogs); + const queries = parseQueryForm(gui, formData); // Ideally query for each catalog is sent to ESAP API Gateway, and query results is returned // This is under development in the backend at the moment @@ -78,7 +101,7 @@ export default function QueryCatalogs() { console.log("queryMap", Array.from(queryMap.values())); - const uiSchemaProp = config.ui_schema ? { uiSchema : config.ui_schema } : {}; + const uiSchemaProp = config.ui_schema ? { uiSchema: config.ui_schema } : {}; return ( <Container fluid> <Form diff --git a/src/contexts/GlobalContext.js b/src/contexts/GlobalContext.js index 0b828c476758051005a753ec2cca6c2594127260..04ccbf45edf45304985dff5f28588436dfc9f275 100644 --- a/src/contexts/GlobalContext.js +++ b/src/contexts/GlobalContext.js @@ -8,17 +8,16 @@ export function GlobalContextProvider({ children }) { console.log("ASTRON ESAP version 14 aug 2020"); const api_host = process.env.NODE_ENV === "development" - ? "http://sdc.astron.nl:15671/esap-api/" + ? "http://localhost:8000/esap-api/" : "/esap-api/"; const [config, setConfig] = useState(); - const [configName, setConfigName] = useState("esap_config"); - const [defaultConfigName, setDefaultConfigName] = useState("esap_config"); + const [configName, setConfigName] = useState("esap_ivoa"); useEffect(() => { - let configNameString="" - if (configName){ - configNameString=`?name=${configName}` + let configNameString = ""; + if (configName) { + configNameString = `?name=${configName}`; } axios .get(api_host + "query/configuration" + configNameString) @@ -63,7 +62,7 @@ export function GlobalContextProvider({ children }) { archives, handleLogin, handleLogout, - setConfigName + setConfigName, }} > {children} diff --git a/src/routes/Routes.js b/src/routes/Routes.js index e28032c493e06f280a9c7d9067f4091b3785911c..319cd3b8deffef20ab98d3eb8105f8755cf38b12 100644 --- a/src/routes/Routes.js +++ b/src/routes/Routes.js @@ -7,6 +7,8 @@ import QueryCatalogs from "../components/query/QueryCatalogs"; import { BrowserRouter as Router } from "react-router-dom"; import NavBar from "../components/NavBar"; import { QueryContextProvider } from "../contexts/QueryContext"; +import Rucio from "../components/Rucio"; +import Interactive from "../components/Interactive"; export default function Routes() { const { config, handleLogin, handleLogout } = useContext(GlobalContext); @@ -22,14 +24,25 @@ export default function Routes() { <Route exact path="/archives"> <Archives /> </Route> - <Route path="/query"> + <Route exact path="/query"> <QueryContextProvider> <QueryCatalogs /> </QueryContextProvider> </Route> + <Route exact path="/rucio"> + <Rucio /> + </Route> + <Route exact path="/interactive"> + <Interactive /> + </Route> <Route exact path="/login" component={handleLogin} /> <Route exact path="/logout" component={handleLogout} /> - <Route path="/archives/:uri" component={ArchiveDetails} /> + <Route exact path="/archives/:uri" component={ArchiveDetails} /> + <Route exact path="/archives/:uri/query"> + <QueryContextProvider> + <QueryCatalogs /> + </QueryContextProvider> + </Route> </Switch> </Router> ); diff --git a/src/utils/form/parseADEXForm.js b/src/utils/form/parseADEXForm.js index c4f17bd8a42aa373f5cd0652ba8e2353c099f662..d2f9460dc23fc6ea74995f1f051a881a8590194f 100644 --- a/src/utils/form/parseADEXForm.js +++ b/src/utils/form/parseADEXForm.js @@ -1,4 +1,5 @@ -export default function ParseADEXForm(formData, catalogs) { +export default function ParseADEXForm(formData) { + let catalogs = ["apertif", "astron_vo"]; let queries = []; // queries is an array of dictionaries, where each dictionary consists of // {"catalog": "catalogname", diff --git a/src/utils/form/parseASTRONVOForm.js b/src/utils/form/parseASTRONVOForm.js new file mode 100644 index 0000000000000000000000000000000000000000..3c4a4694f0f8f66d6dcc14186d89d456185fe2d8 --- /dev/null +++ b/src/utils/form/parseASTRONVOForm.js @@ -0,0 +1,44 @@ +export default function ParseASTRONVOForm(formData) { + let catalogs = "astron_vo"; + let queries = []; + // queries is an array of dictionaries, where each dictionary consists of + // {"catalog": "catalogname", + // "esapquery": "querystring"} + let query = ""; + let formInput = Object.entries(formData); + console.log(formInput); + + for (let [key, value] of formInput) { + console.log(`${key}: ${value}`); + if (value && value !== "all" && key !== "catalog") { + query += `${`${query}` ? "&" : ""}` + key + "=" + value; + } + } + console.log("Query:", query); + // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname", + // "catalogquery": "querystring", + // "status": "null|fetching|fetched", + // "results": null} + let catalog = formInput.find(([key]) => key === "catalog")[1]; + if (catalog === "all") { + console.log("Catalogs:", catalogs); + catalogs.map((catalog) => { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + return null; + }); + } else { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + } + console.log("Queries:", queries); + return queries; +} diff --git a/src/utils/form/parseApertifForm.js b/src/utils/form/parseApertifForm.js new file mode 100644 index 0000000000000000000000000000000000000000..1540ce1a41be4dba8b0b8dd8001f68257949cd1b --- /dev/null +++ b/src/utils/form/parseApertifForm.js @@ -0,0 +1,44 @@ +export default function ParseApertifForm(formData) { + let catalogs = "apertif"; + let queries = []; + // queries is an array of dictionaries, where each dictionary consists of + // {"catalog": "catalogname", + // "esapquery": "querystring"} + let query = ""; + let formInput = Object.entries(formData); + console.log("formInput:", formInput); + + for (let [key, value] of formInput) { + console.log(`${key}: ${value}`); + if (value && value !== "all" && key !== "catalog") { + query += `${`${query}` ? "&" : ""}` + key + "=" + value; + } + } + console.log("Query:", query); + // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname", + // "catalogquery": "querystring", + // "status": "null|fetching|fetched", + // "results": null} + let catalog = formInput.find(([key]) => key === "catalog")[1]; + if (catalog === "all") { + console.log("Catalogs:", catalogs); + catalogs.map((catalog) => { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + return null; + }); + } else { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + } + console.log("Queries:", queries); + return queries; +} diff --git a/src/utils/form/parseIVOAForm.js b/src/utils/form/parseIVOAForm.js new file mode 100644 index 0000000000000000000000000000000000000000..3df6e0ee67420e98962b0186bde9a857de1b9e51 --- /dev/null +++ b/src/utils/form/parseIVOAForm.js @@ -0,0 +1,44 @@ +export default function ParseIVOAForm(formData) { + let catalogs = "ivoa"; + let queries = []; + // queries is an array of dictionaries, where each dictionary consists of + // {"catalog": "catalogname", + // "esapquery": "querystring"} + let query = ""; + let formInput = Object.entries(formData); + console.log(formInput); + + for (let [key, value] of formInput) { + console.log(`${key}: ${value}`); + if (value && value !== "all" && key !== "catalog") { + query += `${`${query}` ? "&" : ""}` + key + "=" + value; + } + } + console.log("Query:", query); + // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname", + // "catalogquery": "querystring", + // "status": "null|fetching|fetched", + // "results": null} + let catalog = formInput.find(([key]) => key === "catalog")[1]; + if (catalog === "all") { + console.log("Catalogs:", catalogs); + catalogs.map((catalog) => { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + return null; + }); + } else { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + } + console.log("Queries:", queries); + return queries; +} diff --git a/src/utils/form/parseLOFARForm.js b/src/utils/form/parseLOFARForm.js new file mode 100644 index 0000000000000000000000000000000000000000..7446420a0e15f91534608c5a5448fb5580669309 --- /dev/null +++ b/src/utils/form/parseLOFARForm.js @@ -0,0 +1,44 @@ +export default function ParseLOFARForm(formData) { + let catalogs = "lofar"; + let queries = []; + // queries is an array of dictionaries, where each dictionary consists of + // {"catalog": "catalogname", + // "esapquery": "querystring"} + let query = ""; + let formInput = Object.entries(formData); + console.log(formInput); + + for (let [key, value] of formInput) { + console.log(`${key}: ${value}`); + if (value && value !== "all" && key !== "catalog") { + query += `${`${query}` ? "&" : ""}` + key + "=" + value; + } + } + console.log("Query:", query); + // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname", + // "catalogquery": "querystring", + // "status": "null|fetching|fetched", + // "results": null} + let catalog = formInput.find(([key]) => key === "catalog")[1]; + if (catalog === "all") { + console.log("Catalogs:", catalogs); + catalogs.map((catalog) => { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + return null; + }); + } else { + let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; + + queries.push({ + catalog: catalog, + esapquery: esapquery, + }); + } + console.log("Queries:", queries); + return queries; +} diff --git a/src/utils/form/parseQueryForm.js b/src/utils/form/parseQueryForm.js index 21f9315428e7af25435b27b52d64b99f2cde7adb..3b6aa52313083712aab068003b2df983a77756a3 100644 --- a/src/utils/form/parseQueryForm.js +++ b/src/utils/form/parseQueryForm.js @@ -1,12 +1,24 @@ import parseADEXForm from "./parseADEXForm"; import parseZooniverseForm from "./parseZooniverseForm"; +import parseLOFARForm from "./parseLOFARForm"; +import parseIVOAForm from "./parseIVOAForm"; +import parseApertifForm from "./parseApertifForm"; +import parseASTRONVOForm from "./parseASTRONVOForm"; -export default function parseQueryForm(gui, formData, catalogs) { +export default function parseQueryForm(gui, formData) { switch (gui) { case "adex": - return parseADEXForm(formData, catalogs); + return parseADEXForm(formData); case "zooniverse": - return parseZooniverseForm(formData, catalogs); + return parseZooniverseForm(formData); + case "lofar": + return parseLOFARForm(formData); + case "apertif": + return parseApertifForm(formData); + case "astron_vo": + return parseASTRONVOForm(formData); + case "ivoa": + return parseIVOAForm(formData); default: return null; } diff --git a/src/utils/form/parseZooniverseForm.js b/src/utils/form/parseZooniverseForm.js index c4fa8ceabc4b7fbbaab45686ea5328dad23fa783..8d12202f0a3a777b692f079fbbb7972d42a1afbe 100644 --- a/src/utils/form/parseZooniverseForm.js +++ b/src/utils/form/parseZooniverseForm.js @@ -1,4 +1,5 @@ -export default function parseZooniverseForm(formData, catalogs) { +export default function parseZooniverseForm(formData) { + let catalogs = "zooniverse"; let queries = []; // queries is an array of dictionaries, where each dictionary consists of // {"catalog": "catalogname", @@ -23,7 +24,11 @@ export default function parseZooniverseForm(formData, catalogs) { if (catalog === "all") { console.log(`Catalogs: ${catalogs}`); catalogs.map((catalog) => { - let esapquery = [query, "archive_uri=zooniverse", `catalog=${catalog}`].join("&"); + let esapquery = [ + query, + "archive_uri=zooniverse", + `catalog=${catalog}`, + ].join("&"); queries.push({ catalog: catalog, @@ -32,7 +37,11 @@ export default function parseZooniverseForm(formData, catalogs) { return null; }); } else { - let esapquery = [query, "archive_uri=zooniverse", `catalog=${catalog}`].join("&"); + let esapquery = [ + query, + "archive_uri=zooniverse", + `catalog=${catalog}`, + ].join("&"); queries.push({ catalog: catalog,