Skip to content
Snippets Groups Projects
Commit a2c40f3a authored by Nico Vermaas's avatar Nico Vermaas
Browse files

Merge branch 'esap-gui-dev' into 'master'

Esap gui dev

See merge request astron-sdc/esap-gui!5
parents cecd7bfb df490ca9
No related branches found
No related tags found
1 merge request!5Esap gui dev
Showing
with 618 additions and 184 deletions
......@@ -16,7 +16,8 @@
"react-jsonschema-form-layout-grid": "^2.1.0",
"react-router-dom": "^5.1.2",
"react-scripts": "^3.4.1",
"styled-components": "^4.4.1"
"styled-components": "^4.4.1",
"deep-equal": "^2.0.4"
},
"scripts": {
"start": "react-scripts start",
......
......@@ -20,74 +20,3 @@
.App-link {
color: #1315c4;
}
.Observations-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: inherit;
font-size: calc(10px + 2vmin);
color: white;
}
.card-img-top {
width: 30vh;
height: 15vw;
object-fit: cover;
background-color: darkgrey;
}
.card-datasource {
display: flex;
object-fit: cover;
background-color: #d4d4d4;
}
.card-description {
display: flex;
//background-color: #BBDEFB;
font-family: Raleway;
//font-size: 14pt;
}
.card-telescope {
display: flex;
width: 40vh;
height: 35vw;
}
.card-query {
display: inline;
align-items: flex-start;
justify-content: inherit;
background-color: lightgrey;
}
.key {
font-weight: bold;
}
.value {
font-style: italic;
}
@media (min-width:400px) {
.card-columns {
column-count: 1;
}
}
@media (min-width:800px) {
.card-columns {
column-count: 2;
}
}
@media (min-width:1200px) {
.card-columns {
column-count: 3;
}
}
......@@ -2,6 +2,7 @@ import React from "react";
import "./App.css";
import Routes from "./routes/Routes";
import { GlobalContextProvider } from "./contexts/GlobalContext";
import { QueryContextProvider } from "./contexts/QueryContext";
// This is the App, only application global stuff goes here, like the global state provider.
......@@ -9,7 +10,9 @@ export default function App() {
return (
<div>
<GlobalContextProvider>
<Routes />
<QueryContextProvider>
<Routes />
</QueryContextProvider>
</GlobalContextProvider>
</div>
);
......
......@@ -3,6 +3,13 @@ import { Alert } from "react-bootstrap";
export default function Interactive() {
return (
// <div class="embed-responsive embed-responsive-16by9">
// <iframe
// class="embed-responsive-item"
// src="http://130.246.212.44/escape/"
// allowfullscreen
// ></iframe>
// </div>
<Alert variant="warning">
<p>You will leave ESAP GUI and be redirected to</p>
<a
......
......@@ -3,10 +3,10 @@ import { Navbar, Nav } from "react-bootstrap";
import { NavLink } from "react-router-dom";
import AuthControl from "./auth/authControl";
import { GlobalContext } from "../contexts/GlobalContext";
import { QueryContext } from "../contexts/QueryContext";
export default function NavBar() {
const { config } = useContext(GlobalContext);
const { config } = useContext(QueryContext);
if (!config) return null;
// construct the navigation bar based on the configuration
const navlist = config.navbar;
......
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"
rel="noopener noreferrer"
href="https://escape-dios-dl.cern.ch/ui/"
>
Rucio Web UI
</a>
</Alert>
<div className="embed-responsive embed-responsive-16by9">
<iframe
title="rucio"
className="embed-responsive-item"
src="https://escape-rucio.cern.ch"
allowFullScreen
></iframe>
</div>
);
}
import React from "react";
import { Card, Container, Row, Button, Image } from "react-bootstrap";
import { Card, Button, Image } from "react-bootstrap";
import { NavLink } from "react-router-dom";
// display a single archive on a card
export default function ArchiveCard({ archive }) {
return (
<Card className="card-description">
<Card>
<Card.Body>
<Card.Title className="h2">{archive.name}</Card.Title>
<Container fluid>
<Row>
<Card className="card-description">
<Card className="card-description">
<Card.Body>
<Image
className="mx-auto d-block"
......@@ -21,19 +19,24 @@ export default function ArchiveCard({ archive }) {
<Card.Title className="h3 pt-3">{archive.short_description}</Card.Title>
<Card.Text className="text-justify">{archive.long_description}</Card.Text>
</Card.Body>
</Card>
{/* <Container fluid>
<Row>
</Card>
</Row>
<Row className="p-2">
<Button
className="mx-auto"
</Row>
</Container> */}
<Button
className="mt-3"
as={NavLink}
variant="outline-info"
to={`/archives/${archive.uri}`}
>
Visit {archive.name} Archives
</Button>
</Row>
</Container>
</Button>
</Card.Body>
</Card>
);
......
import React, { useContext } from "react";
import { CardColumns } from "react-bootstrap";
import { Container, Row, Col } from "react-bootstrap";
import ArchiveCard from "./ArchiveCard";
import { GlobalContext } from "../../contexts/GlobalContext";
......@@ -9,11 +9,13 @@ export function Archives() {
console.log("archives: ", { archives });
return (
<CardColumns className="row-2">
<Container fluid>
<Row>
{archives.map((archive) => {
let key = "archive-" + archive.id;
return <ArchiveCard key={key} archive={archive} />;
return <Col><ArchiveCard key={key} archive={archive} /></Col>;
})}
</CardColumns>
</Row>
</Container>
);
}
import React, { useState, useContext, useEffect } from "react";
import { NavLink } from "react-router-dom";
import { useHistory } from "react-router-dom";
import { ListGroup, Card, Button, Row, Col } from "react-bootstrap";
import { GlobalContext } from "../../contexts/GlobalContext";
import { QueryContext } from "../../contexts/QueryContext";
import axios from "axios";
export default function DataProductCategories({ archive }) {
const { api_host } = useContext(GlobalContext);
const { setDPLevel, setCollection } = useContext(QueryContext);
const [categories, setCategories] = useState([]);
const history = useHistory();
useEffect(() => {
axios
......@@ -39,9 +42,18 @@ export default function DataProductCategories({ archive }) {
let query_url = `${category.archive_uri_derived}/query`;
console.log("query_url:", query_url);
button = (
<Button as={NavLink} variant="outline-info" to={query_url}>
// need to add level (e.g raw) and category (e.g imaging) infomation to send to the form
// probably need to define onSubmit instead of point to query_url
<Button
onClick={() => {
console.log('onClick', category)
setDPLevel(category.level);
setCollection(category.collection);
history.push(query_url);}}
>
Browse Catalog & Run Queries
</Button>
);
} else if (category.catalog_user_url_derived) {
button = (
......
import React, { useState } from "react";
import React, { useContext } from "react";
import * as deepEqual from "deep-equal";
import { Form } from "react-bootstrap";
import { GlobalContext } from "../../contexts/GlobalContext";
import { BasketContext } from "../../contexts/BasketContext";
export default function Addtobasket({ add }) {
const [info, setInfo] = useState("");
export default function Addtobasket(props) {
const { isAuthenticated } = useContext(GlobalContext);
const basketContext = useContext(BasketContext);
return (
// input field is only here for testing
// this will be replaced by real dataset later.
<div className="Item">
<input
type="text"
placeholder="New dataset info"
value={info}
onChange={(e) => setInfo(e.target.value)}
></input>
<button onClick={() => add(info)}>Add to basket</button>
</div>
);
function isInBasket(testBasketItem) {
const found = basketContext.datasets.some(basketItem => deepEqual(basketItem, testBasketItem));
return found;
}
function addToBasket(addToBasketItem) {
basketContext.add(addToBasketItem);
console.log([addToBasketItem, basketContext]);
}
function removeFromBasket(removeFromBasketItem) {
basketContext.remove(removeFromBasketItem);
console.log([removeFromBasketItem, basketContext]);
}
if (isAuthenticated){
return (
<Form.Check id={props.id} type="checkbox" onChange={(event) => {
const action = event.target.checked ? addToBasket : removeFromBasket;
action(props.item);
}} checked={isInBasket(props.item) ? "checked" : ""} />
);
}
else{
return (
<Form.Check id={props.id} type="checkbox" disabled />
);
}
}
import React, { useContext } from "react";
import { Button } from "react-bootstrap";
import { GlobalContext } from "../../contexts/GlobalContext";
import { BasketContext } from "../../contexts/BasketContext";
import axios from "axios";
export default function SaveBasket(props) {
const { api_host, isAuthenticated } = useContext(GlobalContext);
const basketContext = useContext(BasketContext);
function saveBasket(basketData){
const payload = {shopping_cart: basketData};
console.log(payload);
const profileUrl = api_host + "accounts/user-profiles/";
axios
.get(profileUrl, {withCredentials: true})
.then((response) => {
const userProfileUrl = profileUrl + response.data.results[0].user_name + "/";
axios
.patch(userProfileUrl, payload, {withCredentials: true})
.then((response) => {
console.log("patch", response);
})
.catch((error) => {
console.log(error);
});
})
.catch((error) => {
console.log(error);
});
}
if(isAuthenticated){
return (
<Button
type="button"
variant="primary"
onClick={() => saveBasket(basketContext.datasets)}
{...props}
>Save Data Selection</Button>
);
}
else{
return (<>
<Button variant="warning" disabled {...props}>
Log In to Enable Data Selection
</Button>
</>
);
}
}
......@@ -3,16 +3,30 @@ import { Table, Alert } from "react-bootstrap";
import { QueryContext } from "../../contexts/QueryContext";
import LoadingSpinner from "../LoadingSpinner";
import Paginate from "../Paginate";
import HandlePreview from "./HandlePreview";
import Preview from "./Preview";
export default function ASTRONVOResults({ catalog }) {
const { queryMap } = useContext(QueryContext);
const { queryMap, page, setPage, preview } = useContext(QueryContext);
if (!queryMap) return null;
if (queryMap.get(catalog).status === "fetched") {
if (!("results" in queryMap.get(catalog).results))
return <Alert variant="warning">{queryMap.get(catalog).results}</Alert>;
if (queryMap.get(catalog).results.results.length === 0)
return <Alert variant="warning">No matching results found!</Alert>;
const numPages = queryMap.get(catalog).results.pages;
console.log(queryMap.get(catalog).results.results);
return (
<>
<Paginate
getNewPage={(args) => {
return args.target ? setPage(parseFloat(args.target.text)) : null;
}}
currentPage={page}
numAdjacent={3}
numPages={numPages}
/>
<Table className="mt-3" responsive>
<thead>
<tr className="bg-light">
......@@ -29,30 +43,45 @@ export default function ASTRONVOResults({ catalog }) {
<th>Calibration Level</th>
<th>Size</th>
<th>Link to data</th>
<th></th>
</tr>
</thead>
<tbody>
{queryMap.get(catalog).results.results.map((result) => {
return (
<tr key={result.result}>
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<td>{result.obs_collection}</td>
<td>{Number(result.ra).toFixed(1)}</td>
<td>{Number(result.dec).toFixed(1)}</td>
<td>{Number(result.fov).toFixed(1)}</td>
<td>{result.dataproduct_type}</td>
<td>{result.calibration_level}</td>
<td>{Number((result.size / 1024).toFixed(1))} MB</td>
<td>
<a href={result.url} rel="noopener noreferrer" download>
Download
</a>
</td>
</tr>
<>
<tr key={result.url}>
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<td>{result.obs_collection}</td>
<td>{Number(result.ra).toFixed(1)}</td>
<td>{Number(result.dec).toFixed(1)}</td>
<td>{Number(result.fov).toFixed(1)}</td>
<td>{result.dataproduct_type}</td>
<td>{result.calibration_level}</td>
<td>{Number((result.size / 1024).toFixed(1))} MB</td>
<td>
<a href={result.url} rel="noopener noreferrer" download>
Download data
</a>
</td>
<td>
<HandlePreview result={result} />
</td>
</tr>
{preview === result.url &&
<tr key={result.url}>
<td></td>
<td></td>
<td></td>
<td></td>
<td colSpan="4" ><Preview /></td>
<td></td>
</tr>}
</>
);
})}
</tbody>
......
......@@ -3,16 +3,30 @@ import { Table, Alert } from "react-bootstrap";
import { QueryContext } from "../../contexts/QueryContext";
import LoadingSpinner from "../LoadingSpinner";
import Paginate from "../Paginate";
import HandlePreview from "./HandlePreview";
import Preview from "./Preview";
export default function ApertifResults({ catalog }) {
const { queryMap } = useContext(QueryContext);
const { queryMap, page, setPage, preview } = useContext(QueryContext);
if (!queryMap) return null;
if (queryMap.get(catalog).status === "fetched") {
if (!("results" in queryMap.get(catalog).results))
return <Alert variant="warning">{queryMap.get(catalog).results}</Alert>;
if (queryMap.get(catalog).results.results.length === 0)
return <Alert variant="warning">No matching results found!</Alert>;
const numPages = queryMap.get(catalog).results.pages;
console.log("Query results:", queryMap.get(catalog).results.results);
return (
<>
<Paginate
getNewPage={(args) => {
return args.target ? setPage(parseFloat(args.target.text)) : null;
}}
currentPage={page}
numAdjacent={3}
numPages={numPages}
/>
<Table className="mt-3" responsive>
<thead>
<tr className="bg-light">
......@@ -29,11 +43,13 @@ export default function ApertifResults({ catalog }) {
<th>Data Product Type</th>
<th>Data Product Subtype</th>
<th>Link to data</th>
<th></th>
</tr>
</thead>
<tbody>
{queryMap.get(catalog).results.results.map((result) => {
return (
<>
<tr key={result.PID}>
{/* <th>
<InputGroup>
......@@ -52,26 +68,29 @@ export default function ApertifResults({ catalog }) {
href={result.url}
target="_blank"
rel="noopener noreferrer"
download
>
View data
Download data
</a>
{result.dataProductSubType === "continuumMF" ? (
<a
href={result.thumbnail}
target="_blank"
rel="noopener noreferrer"
className="ml-3"
>
Thumbnail
</a>
) : null}
</td>
<td>
<HandlePreview result={result} />
</td>
</tr>
{preview === result.url &&
<tr key={result.url}>
<td></td>
<td></td>
<td></td>
<td></td>
<td colSpan="4" ><Preview /></td>
<td></td>
</tr>}
</>
);
})}
</tbody>
</Table>
{/* <Paginate /> */}
</>
);
} else {
......
import React, { useContext } from 'react';
import { Button } from 'react-bootstrap';
import { QueryContext } from '../../contexts/QueryContext';
export default function HandlePreview({ result }) {
const { preview, setPreview, setDS9, setURL } = useContext(QueryContext);
return (
<>
{/* if results is in .fits format and is smaller than 10 MB,
display it with js9 */}
{((result.url.includes('fits') || (result.url.includes('FITS'))) &&
Number(result.size) < 10000) ?
(<Button
onClick={() => {
preview ? setPreview("") : setPreview(result.url);
setURL(result.url);
setDS9(true);
}}
>View fits with DS9</Button>) :
(result.thumbnail && (
<Button
onClick={()=>{
preview ? setPreview("") : setPreview(result.url);
setURL(result.thumbnail);
}}
>
View Thumbnail
</Button>
))
}
</>
)
}
import React, { useContext } from "react";
import { Table, Alert } from "react-bootstrap";
import { QueryContext } from "../../contexts/QueryContext";
import LoadingSpinner from "../LoadingSpinner";
export default function LOFARResults({ catalog }) {
const { queryMap } = useContext(QueryContext);
if (!queryMap) return null;
if (queryMap.get(catalog).status === "fetched") {
if (!("results" in queryMap.get(catalog).results))
return <Alert variant="warning">{queryMap.get(catalog).results}</Alert>;
if (queryMap.get(catalog).results.results.length === 0)
return <Alert variant="warning">No matching results found!</Alert>;
//const numPages = queryMap.get(catalog).results.pages;
console.log("Query results:", queryMap.get(catalog).results.results);
return (
<>
{/* <Paginate
getNewPage={(args) => {
return args.target ? setPage(parseFloat(args.target.text)) : null;
}}
currentPage={page}
numAdjacent={3}
numPages={numPages}
/> */}
<Table className="mt-3" responsive>
<thead>
<tr className="bg-light">
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<th>Project</th>
<th>SAS ID</th>
<th>Target Name</th>
<th>RA</th>
<th>Dec</th>
<th>Release Date</th>
<th>Start Time</th>
<th>Duration</th>
<th>Pipeline</th>
<th>Antenna Set</th>
<th>Instrument Filter</th>
</tr>
</thead>
<tbody>
{queryMap.get(catalog).results.results.map((result) => {
return (
<tr key={result.PID}>
{/* <th>
<InputGroup>
<InputGroup.Checkbox />
</InputGroup>
</th> */}
<td>{result.project}</td>
<td>{result.sas_id}</td>
<td>{result.target}</td>
<td>{Number(result.ra).toFixed(1)}</td>
<td>{Number(result.dec).toFixed(1)}</td>
<td>{result.releaseDate}</td>
<td>{result.startTime}</td>
<td>{result.duration}</td>
<td>{result.pipeline}</td>
<td>{result.antennaSet}</td>
<td>{result.instrumentFilter}</td>
{/* <td>
<a
href={result.url}
target="_blank"
rel="noopener noreferrer"
>
View data
</a>
{result.dataProductSubType === "continuumMF" ? (
<a
href={result.thumbnail}
target="_blank"
rel="noopener noreferrer"
className="ml-3"
>
Thumbnail
</a>
) : null}
</td> */}
</tr>
);
})}
</tbody>
</Table>
</>
);
} else {
return <LoadingSpinner />;
}
}
import React, { useContext } from 'react';
import { Image } from 'react-bootstrap';
import { QueryContext } from '../../contexts/QueryContext';
export default function Preview() {
const { preview, ds9, url } = useContext(QueryContext);
return (
<>
{console.log("preview: ", preview)}
{console.log("url: ", url)}
{(preview &&
(ds9 ?
<iframe
title="DS9"
className="embed-responsive-item"
height="700"
width="700"
src={"https://js9.si.edu/js9/js9.html?url="+JSON.parse(JSON.stringify(url))+"&colormap=viridis&scale=log"}
allowFullScreen
></iframe>
:
<Image
width={700}
className={"mt-3"}
src={url}
alt=""
/>)
)}
</>
)
}
import React, { useContext, useEffect } from "react";
import { useParams, useHistory } from "react-router-dom";
import axios from "axios";
import { Container } from "react-bootstrap";
import Form from "react-jsonschema-form";
import { GlobalContext } from "../../contexts/GlobalContext";
import { QueryContext } from "../../contexts/QueryContext";
import QueryResults from "./QueryResults";
import parseQueryForm from "../../utils/form/parseQueryForm";
export default function QueryCatalogs() {
// queryMap is a map of dictionaries, where each dictionary consists of
// {"catalog": "catalogname",
// "catalogquery": "querystring",
// "status": "fetching|fechted",
// "results": null}
const { config, setConfigName, defaultConf, queryMap, formData, setFormData, page } = useContext(QueryContext);
const { api_host } = useContext(
GlobalContext
);
const { uri } = useParams();
const history = useHistory();
console.log("uri:", uri);
console.log("default conf:", defaultConf);
// 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;
}
return () => {
console.log("cleaned up");
queryMap.clear();
setFormData();
setConfigName(uri);
};
}, [uri]);
useEffect(() => {
console.log(config.query_schema);
if (!formData) return;
const gui = config.query_schema.name;
const queries = parseQueryForm(gui, formData, page);
// 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
queryMap.clear();
queries.forEach((query) => {
queryMap.set(query.catalog, {
catalog: query.catalog,
esapquery: query.esapquery,
status: "fetching",
results: null,
});
const url = api_host + "query/query/?" + query.esapquery;
axios
.get(url)
.then((queryResponse) => {
queryMap.set(query.catalog, {
catalog: query.catalog,
esapquery: query.esapquery,
status: "fetched",
results: queryResponse.data,
});
})
.catch(() => {
queryMap.set(query.catalog, {
catalog: query.catalog,
esapquery: query.esapquery,
status: "error",
results: null,
});
});
});
}, [formData, page]);
function formTemplate({ TitleField, properties, title, description }) {
return (
<div>
<TitleField title={title} />
<div className="row">
{properties.map((prop) => (
<div
className="col-lg-2 col-md-4 col-sm-6 col-xs-12"
key={prop.content.key}
>
{prop.content}
</div>
))}
</div>
{description}
</div>
);
}
console.log("queryMap", Array.from(queryMap.values()));
const uiSchemaProp = config.ui_schema ? { uiSchema: config.ui_schema } : {};
return (
<Container fluid>
<Form
schema={config.query_schema}
ObjectFieldTemplate={formTemplate}
formData={formData}
onBlur={(field, value) => {
if (field == "root_catalog") {
console.log("Change query catalog to : ", value);
if (value == "adex") {
history.push("/query");
} else {
history.push("/archives/" + value + "/query");
}
}
}}
onSubmit={({ formData }) => setFormData(formData)}
{...uiSchemaProp}
></Form>
{Array.from(queryMap.keys()).map((catalog) => {
console.log("catalog:", catalog);
const details = queryMap.get(catalog);
console.log("Details:", details);
console.log("Results:", details.results);
let catalogName =
config.query_schema.properties.catalog.enumNames[
config.query_schema.properties.catalog.enum.findIndex(
(name) => name === catalog
)
];
return (
<div key={catalog} className="mt-3">
<h4>Query results for {catalogName}</h4>
<QueryResults catalog={catalog} />
</div>
);
})}
</Container>
);
}
......@@ -4,6 +4,7 @@ import axios from "axios";
import { Container } from "react-bootstrap";
import Form from "react-jsonschema-form";
import { GlobalContext } from "../../contexts/GlobalContext";
import { BasketContextProvider } from "../../contexts/BasketContext"
import { QueryContext } from "../../contexts/QueryContext";
import QueryResults from "./QueryResults";
import parseQueryForm from "../../utils/form/parseQueryForm";
......@@ -14,10 +15,13 @@ export default function QueryCatalogs() {
// "catalogquery": "querystring",
// "status": "fetching|fechted",
// "results": null}
const { queryMap, formData, setFormData, page } = useContext(QueryContext);
const { config, api_host, setConfigName } = useContext(GlobalContext);
const { config, setConfigName, defaultConf, queryMap, formData, setFormData, page } = useContext(QueryContext);
const { api_host } = useContext(
GlobalContext
);
const { uri } = useParams();
console.log(uri);
console.log("uri:", uri);
console.log("default conf:", defaultConf);
// set ConfigName for archive
useEffect(() => {
......@@ -31,6 +35,9 @@ export default function QueryCatalogs() {
case "zooniverse":
setConfigName("zooniverse");
break;
case "esap_rucio":
setConfigName("esap_rucio");
break;
case "astron_vo":
setConfigName("astron_vo");
break;
......@@ -38,11 +45,13 @@ export default function QueryCatalogs() {
setConfigName("lofar");
break;
default:
setConfigName("esap_ivoa");
break;
}
return () => {
console.log("cleaned up");
setConfigName("esap_ivoa");
queryMap.clear();
setFormData();
setConfigName(defaultConf);
};
}, [uri]);
......@@ -129,7 +138,9 @@ export default function QueryCatalogs() {
return (
<div key={catalog} className="mt-3">
<h4>Query results for {catalogName}</h4>
<QueryResults catalog={catalog} />
<BasketContextProvider>
<QueryResults catalog={catalog} />
</BasketContextProvider>
</div>
);
})}
......
......@@ -17,11 +17,16 @@ export default function QueryIVOARegistry() {
// "catalogquery": "querystring",
// "status": "fetching|fechted",
// "results": null}
const { queryMap, formData, setFormData } = useContext(QueryContext);
const { config, api_host, setConfigName } = useContext(GlobalContext);
const { selectedRegistry, queryStep, setQueryStep } = useContext(IVOAContext);
const { config, setConfigName, defaultConf, queryMap, formData, setFormData, page } = useContext(QueryContext);
const { api_host } = useContext(
GlobalContext
);
const { selectedRegistry, queryStep, setQueryStep, regPage } = useContext(
IVOAContext
);
const { uri } = useParams();
console.log("uri:", uri);
console.log("default conf: ", defaultConf);
// set ConfigName for archive
useEffect(() => {
......@@ -46,7 +51,7 @@ export default function QueryIVOARegistry() {
}
return () => {
console.log("Set configuration back to default!");
setConfigName("esap_ivoa");
setConfigName(defaultConf);
};
}, [uri]);
......@@ -59,16 +64,17 @@ export default function QueryIVOARegistry() {
if (queryStep === "run-query") {
selectedRegistry.forEach((access_url) => {
queries = [...queries, ...parseVOServiceForm(formData, access_url)];
queries = [
...queries,
...parseVOServiceForm(formData, access_url, page),
];
});
} else {
queries = parseQueryForm(gui, formData);
queries = parseQueryForm(gui, formData, regPage);
}
console.log("queries:", queries);
// 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
queryMap.clear();
queries.forEach((query) => {
queryMap.set(query.catalog, {
......@@ -82,25 +88,43 @@ export default function QueryIVOARegistry() {
axios
.get(url)
.then((queryResponse) => {
queryMap.set(query.catalog, {
catalog: query.catalog,
service_type: query.service_type,
esapquery: query.esapquery,
status: "fetched",
results: queryResponse.data,
});
if(queryStep === "run-query") {
let tf_url = api_host + "query/get-tables-fields/?dataset_uri=vo_reg&access_url=" + query.catalog;
console.log("table fields url: ", tf_url);
axios
.get(tf_url)
.then((tfResponse) => {
queryMap.set(query.catalog, {
catalog: query.catalog,
service_type: query.service_type,
vo_table_schema: tfResponse.data.results.find((item) => item.table_name === "ivoa.obscore"),
esapquery: query.esapquery,
status: "fetched",
results: queryResponse.data,
});
})
}
else {
queryMap.set(query.catalog, {
catalog: query.catalog,
service_type: query.service_type,
esapquery: query.esapquery,
status: "fetched",
results: queryResponse.data,
})};
})
.catch(() => {
queryMap.set(query.catalog, {
catalog: query.catalog,
service_type: query.service_type,
vo_table_schema:"",
esapquery: query.esapquery,
status: "error",
results: null,
});
});
});
}, [formData]);
}, [formData, page, regPage]);
function formTemplate({ TitleField, properties, title, description }) {
return (
......@@ -132,6 +156,7 @@ export default function QueryIVOARegistry() {
query: { "ui:widget": "textarea" },
keyword: { "ui:widget": "hidden" },
tap_schema: { "ui:widget": "hidden" },
waveband: { "ui:widget": "hidden" },
};
console.log("new ui schema:", uiSchemaProp);
return (
......@@ -176,7 +201,7 @@ export default function QueryIVOARegistry() {
{...uiSchemaProp}
>
<div>
<Button type="submit">Get Registry Services</Button>
<Button type="submit">Query VO Registry</Button>
</div>
</Form>
{Array.from(queryMap.keys()).map((catalog) => {
......@@ -184,17 +209,17 @@ export default function QueryIVOARegistry() {
const details = queryMap.get(catalog);
console.log("Details:", details);
console.log("Results:", details.results);
let catalogName =
config.query_schema.properties.catalog.enumNames[
config.query_schema.properties.catalog.enum.findIndex(
(name) => name === catalog
)
];
// let catalogName =
// config.query_schema.properties.catalog.enumNames[
// config.query_schema.properties.catalog.enum.findIndex(
// (name) => name === catalog
// )
// ];
return (
<div key={catalog} className="mt-3">
<Row>
<Col>
<h4>List of registries</h4>
<h4>List of resources</h4>
</Col>
<Col>
{selectedRegistry.length === 0 ? (
......@@ -206,7 +231,7 @@ export default function QueryIVOARegistry() {
setQueryStep("run-query");
}}
>
Query selected registry
Query selected resources
</Button>
)}
</Col>
......
......@@ -2,7 +2,9 @@ import React from "react";
import ApertifResults from "./ApertifResults";
import ASTRONVOResults from "./ASTRONVOResults";
import ZooniverseResults from "./ZooniverseResults";
import VORegistryResults from "./VORegistryResults";
import VORegListResults from "./VORegListResults";
import LOFARResults from "./LOFARResults";
import RucioResults from "./RucioResults";
export default function QueryResults({ catalog }) {
switch (catalog) {
......@@ -15,7 +17,11 @@ export default function QueryResults({ catalog }) {
case "zooniverse_workflows":
return <ZooniverseResults catalog={catalog} />;
case "vo_reg":
return <VORegistryResults catalog={catalog} />;
return <VORegListResults catalog={catalog} />;
case "lofar":
return <LOFARResults catalog={catalog} />;
case "rucio":
return <RucioResults catalog={catalog} />;
default:
return null;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment