Skip to content
Snippets Groups Projects
QueryMultipleArchives.js 6.86 KiB
Newer Older
import axios from "axios";
import React, { useContext, useEffect } from "react";
import { Button, Container } from "react-bootstrap";
import Form from "react-jsonschema-form";
import { GlobalContext } from "../../contexts/GlobalContext";
import {
    FETCHED_SELECTED_QUERIES, FETCHING_SELECTED_QUERIES, MAQContext, PREPARED_QUERIES, PREPARE_QUERIES, RUN_SELECTED_QUERIES
} from "../../contexts/MAQContext";
import { QueryContext } from "../../contexts/QueryContext";
import parseQueryForm from "../../utils/form/parseQueryForm";
import { getQueryIcon } from "../../utils/styling";
import LoadingSpinner from "../LoadingSpinner";
import AvailableDatasets from "../services/query_results/AvailableDatasets";
import RunMultiQueryResults from "../services/query_results/RunMultiQueryResults";

export default function QueryMultipleArchives() {

    const { api_host } = useContext(GlobalContext);
    const { config, setConfigName, defaultConf, formData, setFormData } = useContext(QueryContext);
    const {
        selectedDatasets, setSelectedDatasets,
        availableDatasets, setAvailableDatasets,
        queryResults, setQueryResults,
        status, setStatus } = useContext(MAQContext);
    // set configuration for multi_archive query, execute once
    useEffect(() => {
        setConfigName("multiple_archives");
        return () => {
            console.log("cleaned up");
            setFormData();
            setConfigName(defaultConf);
        };
Klaas Kliffen's avatar
Klaas Kliffen committed
    }, [defaultConf, setConfigName, setFormData]);  // these should be stable


    // execute when the status changes
    useEffect(() => {

        if (status === PREPARE_QUERIES) {
            prepareQueries(config)
        }

        if (status === RUN_SELECTED_QUERIES) {
            fetchRunQueries()
        }

    }, [status]);
    // read from the config object which datasets should be queried
    function prepareQueries(config) {
        //alert('prepareQueries')
        if (!config) return null
        // list of dataset uri's from the backend
        if (config.datasets_enabled) {

            // convert the list of uri's to a list of available datasets which have all their properties
            // nv: 16nov2021, although this works and shows pretty names, it is noticably slow when users click checkboxes.
            // available_datasets.forEach((available_dataset) => {
            //    let dataset = getDataset(available_dataset)[0]
            //    available.push(dataset)
            //})

            // setSelectedDatasets(available)
            // setAvailableDatasets(available)
            // faster option
            setSelectedDatasets(config.datasets_enabled)
            setAvailableDatasets(config.datasets_enabled)
    // call to the ESAP API 'query' endpoint
    function fetchRunQueries() {
        const query_schema_name = config.query_schema.name;
        let base_query = parseQueryForm(query_schema_name, formData);
        // create a list of queries based on the filled in form
        selectedDatasets.forEach((dataset) => {
            // add archive and collection parameters
            //let url = api_host + "query/query?" + "" +
            //"&collection=" + query.result.collection +
            //    "&level=" + query.result.level +
            //    "&category=" + query.result.category

            // construct the url
            let url = api_host + "query/query?dataset_uri=" + dataset.dataset + '&' + base_query
            setStatus(FETCHING_SELECTED_QUERIES)
            console.log('status = ' + status)
            axios
                .get(url)
                .then((response) => {
                    let results = response.data.results
                    results.forEach((result) => {
                        query_results.push(result)
                    })
                    // update the object (and not just the contents) to trigger the rendering of all the results
                    const copy = query_results.slice(); // make a copy (new object)
                    setQueryResults(copy)
                    setStatus(FETCHED_SELECTED_QUERIES)
                })
                .catch((error) => {
                    alert(error)
                });
        })
    }
Nico Vermaas's avatar
Nico Vermaas committed
    // executed when the 'Run Queries' button is clicked
    function handleRunQueriesButton(formData) {
        setFormData(formData)
        setStatus(RUN_SELECTED_QUERIES)
        console.log('handleRunQueries: status = ' + status)
Nico Vermaas's avatar
Nico Vermaas committed
    // texecuted when the 'Run Queries' button is clicked
    function handleResolveNameButton() {
        alert(formData.target)
    }

    // https://react-jsonschema-form.readthedocs.io/en/latest/advanced-customization/custom-templates/#objectfieldtemplate
    function myObjectFieldTemplate({ 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}
    // RENDER
    if (!config) return <LoadingSpinner />
    if (status === PREPARE_QUERIES) {
        prepareQueries(config)
    }
    // load the GUI for this configuration
    const uiSchemaProp = config.ui_schema ? { uiSchema: config.ui_schema } : {};
    // This is the 'conditional rendering' logic to construct the GUI based on the current status
    // todo: implement later, perhaps in a different way
Nico Vermaas's avatar
Nico Vermaas committed
    let renderResolveNameButton
    if (formData) {
        renderResolveNameButton = <Button onClick={() => {
            handleResolveNameButton()
        }}>{getQueryIcon()} Resolve Target</Button>
    }
    // only render the 'Run Queries' button when one or more queries are selected
    let renderRunQueryButton = <Button type="submit" >{getQueryIcon()} Run Queries</Button>
    // Render the query results when they are fetched, otherwise show a spinner
    let renderQueryResults
    if (status === FETCHING_SELECTED_QUERIES) {
        renderQueryResults = <LoadingSpinner />;
    }
    if (status === FETCHED_SELECTED_QUERIES) {
        renderQueryResults = <RunMultiQueryResults results={queryResults} />
        <Container fluid>
            <AvailableDatasets results={availableDatasets} />
                schema={config.query_schema}
                ObjectFieldTemplate={myObjectFieldTemplate}
                formData={formData}
                onSubmit={({ formData }) => handleRunQueriesButton(formData)}
                {...uiSchemaProp}
            </Form>
            {renderQueryResults}
        </Container>