diff --git a/src/components/MyShoppingBasket.js b/src/components/MyShoppingBasket.js deleted file mode 100644 index 30f1161b47a1dee35f84f1762c66a20d395d6763..0000000000000000000000000000000000000000 --- a/src/components/MyShoppingBasket.js +++ /dev/null @@ -1,16 +0,0 @@ -import React, { useContext } from "react"; -import { Button } from 'react-bootstrap'; -import { GlobalContext } from "../contexts/GlobalContext"; -import { BasketContext } from "../contexts/BasketContext"; -import { getShoppingIcon } from "../utils/styling"; - -export default function MyShoppingBasket(props) { - const { api_host, isAuthenticated } = useContext(GlobalContext); - const basketContext = useContext(BasketContext); - - if (isAuthenticated) { - return <Button> {getShoppingIcon("cart")} </Button> - } else { - return null - } -} \ No newline at end of file diff --git a/src/components/NavBar.js b/src/components/NavBar.js index c636e4a96d1664c46d6c553b69f353e9046cfdd4..f450038ed78c47106e0836e504cd34d31a4d4c6a 100644 --- a/src/components/NavBar.js +++ b/src/components/NavBar.js @@ -2,7 +2,7 @@ import React, { useContext } from "react"; import { Navbar, Nav } from "react-bootstrap"; import { NavLink } from "react-router-dom"; import AuthControl from "./auth/authControl"; -import MyShoppingBasket from "./MyShoppingBasket" +import MyBasketButton from "./basket/MyBasketButton" import { QueryContext } from "../contexts/QueryContext"; import { GlobalContext } from "../contexts/GlobalContext"; @@ -31,10 +31,11 @@ export default function NavBar() { </Nav.Link> ))} </Nav> - <Nav> - <MyShoppingBasket /> - </Nav> + <Nav.Link key="my basket" as={NavLink} to="/basket"> + <MyBasketButton /> + </Nav.Link> <Nav> + <AuthControl /> </Nav> </Navbar> diff --git a/src/components/basket/addtobasket.js b/src/components/basket/AddToBasketCheckBox.js similarity index 100% rename from src/components/basket/addtobasket.js rename to src/components/basket/AddToBasketCheckBox.js diff --git a/src/components/basket/LoadBasket.js b/src/components/basket/LoadBasket.js new file mode 100644 index 0000000000000000000000000000000000000000..4c1213bc0ba0cec44fb11f25c2a17a15c7c545f6 --- /dev/null +++ b/src/components/basket/LoadBasket.js @@ -0,0 +1,73 @@ +import React, { useContext } from "react"; +import { Button } from "react-bootstrap"; +import { GlobalContext } from "../../contexts/GlobalContext"; +import { BasketContext } from "../../contexts/BasketContext"; +import axios from "axios"; +import { getShoppingIcon } from "../../utils/styling"; + +export function loadBasket(basketContext, api_host, isAuthenticated){ + //alert('loadBasket: authenticated = '+isAuthenticated) + if (!isAuthenticated) { + return + } + + const profileUrl = api_host + "accounts/user-profiles/"; + axios + .get(profileUrl, {withCredentials: true}) + .then((response) => { + console.log(response.data) + const userProfileUrl = profileUrl + response.data.results[0].user_name + "/"; + + axios + .get(userProfileUrl, {withCredentials: true}) + .then((response) => { + console.log("get", response); + // load the shopping_cart into the basketContext + //alert('loaded basket: '+response.data.shopping_cart.length) + + // only update the datasets when there are changes, + // because the shoppingbasket button responds to these changes + let current_datasets = basketContext.datasets + if (current_datasets.length !== response.data.shopping_cart.length) { + //alert('loadBasket changes') + basketContext.setDatasets(response.data.shopping_cart) + } + + }) + .catch((error) => { + console.log(error); + }); + }) + .catch((error) => { + console.log(error); + }); +} + +export function LoadBasketButton(props) { + const { api_host, isAuthenticated } = useContext(GlobalContext); + const basketContext = useContext(BasketContext); + + // fake authentication when in 'development' mode. + //let authenticated = isAuthenticated || (process.env.NODE_ENV === "development") + let authenticated = isAuthenticated + + if(authenticated) { + + return ( + <Button + type="button" + variant="primary" + onClick={() => loadBasket(basketContext, api_host, authenticated)} + {...props}> + {getShoppingIcon("cart")} Load Basket</Button> + ); + } + else{ + return (<> + <Button variant="warning" disabled {...props}> + Log In to Enable Data Selection + </Button> + </> + ); + } +} diff --git a/src/components/basket/MyBasketButton.js b/src/components/basket/MyBasketButton.js new file mode 100644 index 0000000000000000000000000000000000000000..b86720aecea66598cd5f75cd2c619509e0dd717f --- /dev/null +++ b/src/components/basket/MyBasketButton.js @@ -0,0 +1,38 @@ +import React, { useContext, useEffect } from "react"; +import { Button, Badge } from 'react-bootstrap'; +import { GlobalContext } from "../../contexts/GlobalContext"; +import { BasketContext } from "../../contexts/BasketContext"; +import { getShoppingIcon } from "../../utils/styling"; +import { loadBasket } from "./LoadBasket"; + + +export default function MyBasketButton(props) { + const { api_host, isAuthenticated } = useContext(GlobalContext); + const basketContext = useContext(BasketContext); + const { datasets } = useContext(BasketContext); + useEffect(() => { + loadBasket(basketContext,api_host, isAuthenticated) + },[isAuthenticated, datasets]) + + if (isAuthenticated) { + try { + let nr_of_items = basketContext.datasets.length + if (nr_of_items > 0) { + return <Button>{getShoppingIcon("cart")} + <Badge variant="light">{nr_of_items}</Badge> + </Button> + } else { + // do not show shopping basket when the basket is empty + return null + } + + } catch (e) { + // do not show shopping basket when there is no basket at all + return null + } + + } else { + // do not show shopping basket when not authenticated + return null + } +} \ No newline at end of file diff --git a/src/components/basket/MyBasketPage.js b/src/components/basket/MyBasketPage.js new file mode 100644 index 0000000000000000000000000000000000000000..bf10c0a404aa27556ee1e31b3d75f8f9e827d176 --- /dev/null +++ b/src/components/basket/MyBasketPage.js @@ -0,0 +1,71 @@ +import React, { useEffect, useContext } from "react"; +import { Button, Table, Container, Alert } from "react-bootstrap"; +import { IDAContext } from "../../contexts/IDAContext"; +import { GlobalContext } from "../../contexts/GlobalContext"; +import { BasketContext } from "../../contexts/BasketContext"; +import SaveBasketButton from "./SaveBasketButton"; +import { LoadBasketButton, loadBasket } from "./LoadBasket"; +import AddToBasket from "./AddToBasketCheckBox"; + +export default function MyBasketPage() { + const { api_host, isAuthenticated } = useContext(GlobalContext); + const basketContext = useContext(BasketContext); + + useEffect(() => { + loadBasket(basketContext,api_host, isAuthenticated) + },[]) + + + let items = basketContext.datasets + if (!items) { + return (<LoadBasketButton />) + } + + // parse the items and build a line to display + let my_list = items.map((item, index) => { + let id = `${index}` + let item_data = item.item_data + + // currently item data is not stored as proper json, but as a stringified dict. + // this converts all ' to "", so that it can be used by the JSON parser. + let j = item_data.replaceAll("'",'"') + let o = JSON.parse(j) + let archive = o.archive + + return <tr> + <td> + <AddToBasket id={id} item={item_data} /> + </td> + <td>{archive}</td> + <td>{item_data}</td> + </tr> + }) + + + return ( + <> + <Container fluid> + <h2>Data Checkout</h2> + <SaveBasketButton /> + + <Table className="mt-3" responsive> + <thead> + + <tr className="bg-light"> + <th>Basket</th> + <th>Source</th> + <th>Item</th> + + </tr> + + </thead> + <tbody> + {my_list} + </tbody> + + </Table> + + </Container> + </> + ); +} diff --git a/src/components/basket/savebasket.js b/src/components/basket/SaveBasketButton.js similarity index 100% rename from src/components/basket/savebasket.js rename to src/components/basket/SaveBasketButton.js diff --git a/src/components/basket/databasket.js b/src/components/basket/databasket_obsolete.js similarity index 100% rename from src/components/basket/databasket.js rename to src/components/basket/databasket_obsolete.js diff --git a/src/components/basket/dataset.js b/src/components/basket/dataset_obsolete.js similarity index 100% rename from src/components/basket/dataset.js rename to src/components/basket/dataset_obsolete.js diff --git a/src/components/query/ASTRONVOResults.js b/src/components/query/ASTRONVOResults.js index 1cc01a5d81e1fc4fd1d9440ad8d9cadca4d1cb93..50a30be1b479fd645c245e60f458b0cc307175ea 100644 --- a/src/components/query/ASTRONVOResults.js +++ b/src/components/query/ASTRONVOResults.js @@ -7,8 +7,8 @@ import LoadingSpinner from "../LoadingSpinner"; import Paginate from "../Paginate"; import HandlePreview from "./HandlePreview"; import Preview from "./Preview"; -import SaveBasket from "../basket/savebasket"; -import AddToBasket from "../basket/addtobasket"; +import SaveBasket from "../basket/SaveBasketButton"; +import AddToBasket from "../basket/AddToBasketCheckBox"; function SAMPBasketItem(record){ return { diff --git a/src/components/query/ApertifResults.js b/src/components/query/ApertifResults.js index 1cef4f23243c4320054c5da5aec12c259ceee931..b251ba8ee8ae2ba098b0b5a51856a552647dd87e 100644 --- a/src/components/query/ApertifResults.js +++ b/src/components/query/ApertifResults.js @@ -8,8 +8,8 @@ import LoadingSpinner from "../LoadingSpinner"; import Paginate from "../Paginate"; import HandlePreview from "./HandlePreview"; import Preview from "./Preview"; -import SaveBasket from "../basket/savebasket"; -import AddToBasket from "../basket/addtobasket"; +import SaveBasket from "../basket/SaveBasketButton"; +import AddToBasket from "../basket/AddToBasketCheckBox"; function SAMPBasketItem(record){ return { diff --git a/src/components/query/ZooniverseResults.js b/src/components/query/ZooniverseResults.js index 4b80c522cb975d50d61e34ad9cdf29ea822f81b3..56c51a5ebcd2feb963d09b40d64042fee61d2a88 100644 --- a/src/components/query/ZooniverseResults.js +++ b/src/components/query/ZooniverseResults.js @@ -6,8 +6,8 @@ import { QueryContext } from "../../contexts/QueryContext"; import { BasketContext } from "../../contexts/BasketContext"; import LoadingSpinner from "../LoadingSpinner"; import Paginate, { pagination_fields } from "../Paginate"; -import SaveBasket from "../basket/savebasket"; -import AddToBasket from "../basket/addtobasket"; +import SaveBasket from "../basket/SaveBasketButton"; +import AddToBasket from "../basket/AddToBasketCheckBox"; const DATETIME_OPTIONS = { year: "numeric", diff --git a/src/components/query/samp/SampGrid.js b/src/components/query/samp/SampGrid.js index e1104f41171db1a6d2742d91bf94bf8230e65cdd..527ae610e9c2d33d4cec0cd71fd21475d52b9195 100644 --- a/src/components/query/samp/SampGrid.js +++ b/src/components/query/samp/SampGrid.js @@ -1,7 +1,7 @@ import React, {useState, useContext } from 'react'; import { Table } from "react-bootstrap"; import { BasketContext } from "../../../contexts/BasketContext"; -import AddToBasket from "../../basket/addtobasket"; +import AddToBasket from "../../basket/AddToBasketCheckBox"; function SAMPBasketItem(record){ return { diff --git a/src/components/query/samp/SampPage.js b/src/components/query/samp/SampPage.js index 73ca9ffd489f05396108b2d3575990940d79a963..a2f26b06db4fb7aa0ba9ec8c0b42800870bd25d6 100644 --- a/src/components/query/samp/SampPage.js +++ b/src/components/query/samp/SampPage.js @@ -5,7 +5,7 @@ import SampGrid from './SampGrid' import { GlobalContext } from "../../../contexts/GlobalContext"; import { QueryContext } from "../../../contexts/QueryContext"; import { BasketContext } from "../../../contexts/BasketContext"; -import SaveBasket from "../../basket/savebasket"; +import SaveBasket from "../../basket/SaveBasketButton"; export default function SampPage(props) { diff --git a/src/contexts/BasketContext.js b/src/contexts/BasketContext.js index 35880d0d8d8dcc13a4c7771095486a6e2c17af87..67079bab4fac480b982bdff34358700e6462c741 100644 --- a/src/contexts/BasketContext.js +++ b/src/contexts/BasketContext.js @@ -18,7 +18,7 @@ export function BasketContextProvider({ children }) { return ( <BasketContext.Provider - value={{ datasets, add: handleAddDataset, remove: handleRemoveDataset }} + value={{ datasets, setDatasets, add: handleAddDataset, remove: handleRemoveDataset }} > {children} </BasketContext.Provider> diff --git a/src/routes/Routes.js b/src/routes/Routes.js index 2de334972a991c8ecff4f2129b1e80992a55bb13..86eb6468ee046ef6c131ab4b9a5b99891e471eff 100644 --- a/src/routes/Routes.js +++ b/src/routes/Routes.js @@ -9,6 +9,7 @@ import { BrowserRouter as Router } from "react-router-dom"; import NavBar from "../components/NavBar"; import Rucio from "../components/Rucio"; import Interactive from "../components/Interactive"; +import MyBasketPage from "../components/basket/MyBasketPage"; import { BasketContextProvider } from "../contexts/BasketContext"; import { IVOAContextProvider } from "../contexts/IVOAContext"; @@ -22,8 +23,12 @@ export default function Routes() { if (!jhubURL) return null; return ( + <Router basename={navbar.frontend_basename}> - <NavBar /> + <BasketContextProvider> + <NavBar /> + </BasketContextProvider> + <Switch> <Route exact path={["/", "/archives"]}> <Archives /> @@ -50,13 +55,21 @@ export default function Routes() { <Route exact path={["/adex-query", "/archives/:uri/query"]}> <QueryCatalogs /> </Route> + <Route exact path="/samp" > <BasketContextProvider> <SampPage/> </BasketContextProvider> </Route> + + <Route exact path="/basket" > + <BasketContextProvider> + <MyBasketPage/> + </BasketContextProvider> + </Route> + </Switch> - <footer><small>esap-gui version 4 jun 2021 - 10:00</small></footer> + <footer><small>esap-gui version 8 jun 2021 - 16:55</small></footer> </Router> ); }