Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Interactive.js 13.17 KiB
import axios from "axios";
import React, { useContext, useState } from "react";
import { Button, Container, Form } from "react-bootstrap";
import "../../assets/Interactive.css";
import { GlobalContext } from "../../contexts/GlobalContext";
import LoadingSpinner from "../LoadingSpinner";

export default function Interactive() {

  const [idaSystemURL, setIdaSystemURL] = useState();
  const [workflowURL, setWorkflowURL] = useState();
  const [list_of_workflows, setList_of_workflows] = useState();
  const [list_of_idaSystems, setList_of_idaSystems] = useState();

  const { api_host } = useContext(GlobalContext);
  const [searchTerm, setSearchTerm] = useState("");
  const [showFacilities, setShowFacilities] = useState(false);
  const [showNext, setShowNext] = useState(false);
  const [showBack, setShowBack] = useState(false);
  const [showAdvanced, setShowAdvanced] = useState(false);
  const [showMoreButton, setShowMoreButton] = useState(true);
  const [showDeploy, setShowDeploy] = useState(false);
  const [showInitMenu, setShowInitMenu] = useState(true);
  const [showNotebooks, setShowNotebooks] = useState(false);
  const [numberOfitemsShown, setNumberOfitemsShown] = useState(3)
  const [loading, setLoading] = useState(false);
  const [defaultWorkflow] = "https://github.com/ESAP-WP5/binder-empty";

  const [advSearchFilters, setAdvSearchFilters] = useState({
    searchAuthorFilter: "",
    searchRuntimePlatformFilter: "",
    searchTypeFilter: ""
  });

  const [advSearchValues, setAdvSearchValues] = useState({
    searchAuthor: "",
    searchRuntimePlatform: "",
    searchType: ""
  });


  if (loading) {
    return (
      <Container className="ida" fluid>
        <h1>Interactive Analysis</h1>
        {!showFacilities ?

          <div className="workflow-div">
          </div>
          : null}
        <LoadingSpinner />
      </Container>
    )

  }

  if ((!list_of_workflows) || (!list_of_idaSystems)) {
    setList_of_idaSystems([]);
    setList_of_workflows([]);
    return null;
  }

  const handleChange = event => {
    setSearchTerm(event.target.value);
    if (event.target.value === "") {
      setNumberOfitemsShown(3);
      setShowMoreButton(true);
    } else {
      setNumberOfitemsShown(list_of_workflows.length);
      setShowMoreButton(false);
    }

  };

  let workflow_results = !searchTerm
    ?
    !showAdvanced
      ? list_of_workflows
      : list_of_workflows.filter(workflow =>
        ((typeof workflow.keywords === 'string') && workflow.keywords.toLowerCase().includes(advSearchFilters.searchTypeFilter.toLowerCase())) &&
        ((typeof workflow.runtimePlatform === 'string') && workflow.runtimePlatform.toLowerCase().includes(advSearchFilters.searchRuntimePlatformFilter.toLowerCase())) &&
        ((typeof workflow.author === 'string') && workflow.author.toLowerCase().includes(advSearchFilters.searchAuthorFilter.toLowerCase())))
    : list_of_workflows.filter(workflow =>
      ((typeof workflow.name === 'string') && workflow.name.toLowerCase().includes(searchTerm.toLocaleLowerCase())) ||
      ((typeof workflow.keywords === 'string') && workflow.keywords.toLowerCase().includes(searchTerm.toLocaleLowerCase())) ||
      ((typeof workflow.author === 'string') && workflow.author.toLowerCase().includes(searchTerm.toLocaleLowerCase())) ||
      ((typeof workflow.runtimePlatform === 'string') && workflow.runtimePlatform.toLowerCase().includes(searchTerm.toLocaleLowerCase())) ||
      ((typeof workflow.description === 'string') && workflow.description.toLowerCase().includes(searchTerm.toLocaleLowerCase()))
    );


  const facility_results = !searchTerm
    ? list_of_idaSystems
    : list_of_idaSystems.filter(facility =>
      facility.name.toLowerCase().includes(searchTerm.toLocaleLowerCase())
    );

  const setWorkflow = event => {
    setWorkflowURL(event.target.value);
    setShowNext(true)
  };

  const setFacility = event => {
    setIdaSystemURL(event.target.value);
    setShowDeploy(true);
  };

  const onClickNext = e => {
    e.preventDefault();
    setSearchTerm("");
    setShowFacilities(true);
    setShowBack(true);
    setAdvSearchValues({ "searchType": "", "searchAuthor": "", "searchRuntimePlatform": "" });
    setAdvSearchFilters({ "searchTypeFilter": "", "searchAuthorFilter": "", "searchRuntimePlatformFilter": "" });

  };

  const onClickAdvanced = e => {
    e.preventDefault();
    setShowAdvanced(!showAdvanced);
  }

  const onClickAdvancedSearch = e => {
    e.preventDefault();
    setAdvSearchFilters({ "searchTypeFilter": advSearchValues.searchType, "searchAuthorFilter": advSearchValues.searchAuthor, "searchRuntimePlatformFilter": advSearchValues.searchRuntimePlatform });
    setShowAdvanced(true);
  }

  const handleRecordTypeChange = e => {
    e.preventDefault();
    setAdvSearchValues({ "searchType": e.target.value, "searchAuthor": advSearchValues.searchAuthor, "searchRuntimePlatform": advSearchValues.searchRuntimePlatform });
  }

  const handleRecordAuthorChange = e => {
    e.preventDefault();
    setAdvSearchValues({ "searchType": advSearchValues.searchType, "searchAuthor": e.target.value, "searchRuntimePlatform": advSearchValues.searchRuntimePlatform });
  }

  const handleRuntimePlatformChange = e => {
    e.preventDefault();
    setAdvSearchValues({ "searchType": advSearchValues.searchType, "searchAuthor": advSearchValues.searchAuthor, "searchRuntimePlatform": e.target.value });
  }

  const onClickBack = e => {
    e.preventDefault();
    setSearchTerm("");
    setShowNext(false);
    setShowFacilities(false);
    setShowBack(true);
    setNumberOfitemsShown(3);
    setShowMoreButton(true);
    setWorkflowURL(defaultWorkflow);
    setAdvSearchValues({ "searchType": "", "searchAuthor": "", "searchRuntimePlatform": "" });
    setAdvSearchFilters({ "searchTypeFilter": "", "searchAuthorFilter": "", "searchRuntimePlatformFilter": "" });

  };

  const onClickNotebooks = e => {
    e.preventDefault();
    setShowInitMenu(false);
    setLoading(true);

    axios
      .get(api_host + "ida/facilities/search?facilitytype=jupyterhub")
      .then((response) => {
        setList_of_idaSystems(response.data.results);
        setIdaSystemURL(response.data.results[0].url);
      });
    axios
      .get(api_host + "ida/workflows/search")
      .then((response) => {
        setList_of_workflows(response.data.results);
        setWorkflowURL(defaultWorkflow);
        setLoading(false);
        setShowNotebooks(true);

      });

  };

  const onCLickLoadDLAAS = e => {
    e.preventDefault();
    setShowFacilities(true);
    setShowInitMenu(false);
    axios
      .get(api_host + "ida/facilities/search?facilitytype=dlaas")
      .then((response) => {
        setList_of_idaSystems(response.data.results);
        setIdaSystemURL(response.data.results[0].url);
      });

  };

  const showMore = e => {
    e.preventDefault();
    if (numberOfitemsShown + 3 <= list_of_workflows.length) {
      setNumberOfitemsShown(numberOfitemsShown + 3);
    } else {
      setNumberOfitemsShown(list_of_workflows.length);
      setShowMoreButton(false);
    }
  }

  const workflow_results_sliced = workflow_results.slice(0, numberOfitemsShown)

  return (


    <Container className="ida" fluid>
      <h1>Interactive Analysis</h1>

      {showInitMenu ?
        <div>
          <br /><br />
          <Button className="ida-menu-items" onClick={onCLickLoadDLAAS}>Data Lake Access</Button>
          <br />
          <Button className="ida-menu-items" onClick={onClickNotebooks}>Binder/Jupyter Notebooks</Button>
        </div>
        : null}


      {!showFacilities && showNotebooks ?

        <div className="workflow-div">
          <h2>Notebooks</h2>

          <Form className="mt-5">

            <div className="search-buttons">

              <input
                className="search-large"
                type="text"
                placeholder="Search for Workflows"
                value={searchTerm}
                onChange={handleChange}
              />

              <Button disabled={!showNext} className="next-button" onClick={onClickNext}>Next</Button>

              <br />
              <Button onClick={onClickAdvanced}>Advanced Search</Button>
              <br />

              {showAdvanced ?


                <div className="advanced-search">

                  <Form className="advanced-form">

                    <br />

                    <h3>Search By:</h3>
                    <hr />

                    <ul className="advanced-form-ul">
                      <li>
                        <div className="advanced-form-div"><label>User Interface type:</label>
                          <select className="form-select advanced-float-right" aria-label="record-type" id="record-type" name="record-type" onChange={handleRecordTypeChange}>
                            <option value="">All</option>
                            <option value="desktop">Desktop Software</option>
                            <option value="cli">Command Line</option>
                            <option value="jupyter-notebook">Notebook</option>
                          </select>
                        </div>
                      </li>
                      <li>
                        <div className="advanced-form-div"><label>Author:</label>
                          <input
                            type="text"
                            className="advanced-float-right"
                            placeholder="Author name"
                            onChange={handleRecordAuthorChange}
                          />

                        </div>
                      </li>
                      <li>
                        <div className="advanced-form-div"><label>Runtime Platform:</label>
                          <select className="form-select advanced-float-right" aria-label="record-type" id="record-type" name="record-type" onChange={handleRuntimePlatformChange}>
                            <option value="">All</option>
                            <option value="Python">Python</option>
                            <option value="R">R</option>
                            <option value="Java">Java</option>
                          </select>
                        </div>
                      </li>

                    </ul>

                    <br /><br />

                    <Button onClick={onClickAdvancedSearch} className="search-button">Search</Button>
                    <br /><br />
                  </Form>
                </div>

                : null}

            </div>



            <ul className="workflow-ul">
              {workflow_results_sliced.map(item => (
                <li className="workflow-li" key={item.name}>
                  <label className="container workflow-checkbox">
                    <input type="radio" name="workflow" onChange={setWorkflow} value={item.url} />  <span className="checkmark"></span>
                  </label>
                  <h5>{item.name}</h5><br />
                  <span><b>Description: </b> <span dangerouslySetInnerHTML={{ __html: item.description }}></span></span><br />
                  <span><b>Link: </b> <a href={item.url}>{item.url}</a></span><br />
                  <span><b>Author: </b>{item.author}</span><br />
                  <span><b>Runtime Platform: </b>{item.runtimePlatform}</span><br />
                  <span><b>Keywords: </b>{item.keywords}</span>

                </li>
              ))}
            </ul>


            {showMoreButton ?
              <Button className="more-button" onClick={showMore}>More</Button>
              : null}
          </Form>
        </div>
        : null}


      {/* DLAAS Service */}

      {showFacilities ?

        <div className="facility-div">
          <h2>Compute Facilities</h2>

          <Form className="mt-5">

            <div className="search-buttons">

              <input
                className="search-large"
                type="text"
                placeholder="Search for Facilities"
                value={searchTerm}
                onChange={handleChange}
              />
              <div className="deploy-buttons">

                {showBack ?
                  <Button className="back-button" onClick={onClickBack}>&#171;</Button>
                  : null}

                <Button
                  disabled={!showDeploy}
                  className="deploy-button"
                  href={api_host + "ida/deploy?facility=" + encodeURIComponent(idaSystemURL) + "&workflow=" + encodeURIComponent(workflowURL)}
                  target="_blank"
                  rel="noopener noreferrer">
                  Deploy
                </Button>


              </div>

            </div>

            <ul className="facility-ul">
              {facility_results.map(item => (
                <li className="facility-li">
                  <label className="container facility-checkbox">
                    <input className="radio" onChange={setFacility} name="facility" type="radio" value={item.url} />
                    <span className="checkmark"></span>
                  </label>
                  <h5>{item.name}</h5><br />
                  <span><b>Description:</b><br /> {item.description}</span> <br />
                  <span><b>Link:</b> <a href={item.url}>{item.url}</a></span>

                </li>
              ))}
            </ul>

          </Form>
        </div>
        : null}

    </Container>
  );
}