diff --git a/src/components/NavBar.js b/src/components/NavBar.js index 9ee62437f7d0340ceb2b297e247460d8817dd925..da34ccd826e7a8a1e26c5010757481ffbab3373f 100644 --- a/src/components/NavBar.js +++ b/src/components/NavBar.js @@ -4,7 +4,7 @@ import { NavLink } from "react-router-dom"; import AuthControl from "./auth/authControl"; import MyBasketButton from "./basket/MyBasketButton" import SaveBasketButton from "./basket/SaveBasketButton" -import EmptyBasketButton from "./basket/EmptyBasketButton" +import ShowTokenButton from "./ShowTokenButton" import { QueryContext } from "../contexts/QueryContext"; import { GlobalContext } from "../contexts/GlobalContext"; @@ -39,7 +39,8 @@ export default function NavBar() { <SaveBasketButton/>{' '} <Nav> - <AuthControl /> + <AuthControl /> + <ShowTokenButton/> </Nav> </Navbar> ); diff --git a/src/components/ShowTokenButton.js b/src/components/ShowTokenButton.js new file mode 100644 index 0000000000000000000000000000000000000000..a6cda0044d71bba4c0270d6f86730aeb7471879a --- /dev/null +++ b/src/components/ShowTokenButton.js @@ -0,0 +1,66 @@ +import React, { useContext, useState, useRef } from "react"; +import { Button, Modal, Form, FormControl } from "react-bootstrap"; +import { GlobalContext } from "../contexts/GlobalContext"; +import { getTokenIcon, getOKIcon, getCopyIcon } from "../utils/styling"; + +export default function ShowTokenButton(props) { + const { api_host, token, isAuthenticated } = useContext(GlobalContext); + const [show, setShow] = useState(false); + + const [copySuccess, setCopySuccess] = useState(''); + const textAreaRef = useRef(null); + + const handleClose = () => setShow(false); + const handleShow = () => setShow(true); + + function copyToClipboard(e) { + textAreaRef.current.select(); + document.execCommand('copy'); + // This is just personal preference. + // I prefer to not show the the whole text area selected. + e.target.focus(); + setCopySuccess('Copied!'); + + setShow(false) + }; + + function close(){ + setShow(false) + } + + if (isAuthenticated) { + + return ( + <> + <Button + type="button" + variant="outline-primary" + onClick={handleShow} + {...props}> + {getTokenIcon('white')} + </Button> + + <Modal size="lg" show={show} onHide={handleClose}> + <Modal.Header closeButton> + <Modal.Title>{getTokenIcon('black')}{' '}oidc_id_token</Modal.Title> + </Modal.Header> + <Modal.Body> + <Form.Control as="textarea" rows={12} ref={textAreaRef} value={token}> + {token} + </Form.Control> + </Modal.Body> + <Modal.Footer> + <Button variant="primary" onClick={copyToClipboard}> + {getCopyIcon()}{' '}Copy to Clipboard + </Button> + + </Modal.Footer> + </Modal> + </> + ) + + } + else{ + return null + } +} diff --git a/src/components/auth/authControl.js b/src/components/auth/authControl.js index ebf8aaecea2cb684d4ec910a62db98ccc9de1bc3..3cb663cd1e9c0d93bf9c2a457dc98ebc099167cd 100644 --- a/src/components/auth/authControl.js +++ b/src/components/auth/authControl.js @@ -4,7 +4,7 @@ import { Nav } from "react-bootstrap"; import { GlobalContext } from "../../contexts/GlobalContext"; export default function AuthControl() { - const { api_host, isAuthenticated, loggedInUserName } = useContext(GlobalContext); + const { api_host, isAuthenticated, loggedInUserName, token } = useContext(GlobalContext); console.log("loggedIn: ", isAuthenticated); diff --git a/src/components/basket/APIButton.js b/src/components/basket/APIButton.js index 78128efedd12f1586b60da692d1bd449f41722aa..5561eb67f1abe1bd65797d48c1849df4c24e29ea 100644 --- a/src/components/basket/APIButton.js +++ b/src/components/basket/APIButton.js @@ -11,7 +11,7 @@ export default function APIButton(props) { if (isAuthenticated) { return <a href={profileUrl} target="_blank"> - <Button variant="outline-primary">{getAPIIcon()} API + <Button variant="outline-primary">{getAPIIcon()} API (expert user) </Button> </a> diff --git a/src/contexts/GlobalContext.js b/src/contexts/GlobalContext.js index deea45d6cb5d69d990127c987902569f680aa1ac..ba39d3e8365bb84c3513496b318365494ff79747 100644 --- a/src/contexts/GlobalContext.js +++ b/src/contexts/GlobalContext.js @@ -5,12 +5,14 @@ import getCookie from "../utils/getCookie"; export const GlobalContext = createContext(); -function getUserName(api_host, setLoggedInUserName){ +function getUserName(api_host, setLoggedInUserName, setToken){ const profileUrl = api_host + "accounts/user-profiles/"; axios .get(profileUrl, {withCredentials: true}) .then((response) => { + setLoggedInUserName(response.data.results[0].full_name); + setToken(response.data.results[0].oidc_id_token) }) } @@ -26,6 +28,7 @@ export function GlobalContextProvider({ children }) { const [archives, setArchives] = useState(); const [navbar, setNavbar] = useState(); const [loggedInUserName, setLoggedInUserName] = useState(); + const [token, setToken] = useState([]); useEffect(() => { axios @@ -42,7 +45,7 @@ export function GlobalContextProvider({ children }) { }); }, [api_host]); - // !!!!! Still need to look at sessionid and stuff + // Zheng: "!!!!! Still need to look at sessionid and stuff" const [sessionid, setSessionid] = useState(getCookie("sessionid")); console.log("waah", sessionid, getCookie("sessionid"), document.cookie); const [isAuthenticated, setIsAuthenticated] = useState( @@ -53,7 +56,7 @@ export function GlobalContextProvider({ children }) { setIsAuthenticated(true); setSessionid(getCookie("sessionid")); history.replace("/"); - getUserName(api_host, setLoggedInUserName); + getUserName(api_host, setLoggedInUserName, setToken); return null; }; @@ -90,6 +93,7 @@ export function GlobalContextProvider({ children }) { handleLogout, handleError, loggedInUserName, + token, }} > {children} diff --git a/src/routes/Routes.js b/src/routes/Routes.js index 30ba160edd4934df8b4e57c1b0a534f368ba3af1..10a5add0b769bb7187f8c7c5d8b78c6b1cf70b42 100644 --- a/src/routes/Routes.js +++ b/src/routes/Routes.js @@ -64,7 +64,7 @@ export default function Routes() { </Switch> - <footer><small>esap-gui version 28 jun 2021 - 15:00</small></footer> + <footer><small>esap-gui version 29 jun 2021 - 16:00</small></footer> </Router> ); } diff --git a/src/utils/styling.js b/src/utils/styling.js index 595d6490f571f110960368e32a9c31a7e16f9d36..c11c1c6385b6406c7f4356065f1f4c8c8caf37a7 100644 --- a/src/utils/styling.js +++ b/src/utils/styling.js @@ -9,7 +9,9 @@ import { faTrashAlt, faCheck, faCog, - faSearchPlus } + faSearchPlus, + faKey, + faCopy} from '@fortawesome/free-solid-svg-icons' @@ -88,5 +90,20 @@ export const getOKIcon = () => { let color = "white" let size = 'md' + return <FontAwesomeIcon size={size} icon={icon} color={color}/> +} + +export const getTokenIcon = (color) => { + let icon = faKey + let size = 'md' + + return <FontAwesomeIcon size={size} icon={icon} color={color}/> +} + +export const getCopyIcon = () => { + let icon = faCopy + let color = "white" + let size = 'md' + return <FontAwesomeIcon size={size} icon={icon} color={color}/> } \ No newline at end of file