From fbf892447ced88a840b7fd84995121a763847f9d Mon Sep 17 00:00:00 2001 From: Nico Vermaas <vermaas@astron.nl> Date: Tue, 29 Jun 2021 16:33:17 +0200 Subject: [PATCH] add token to clipboard button --- src/components/NavBar.js | 5 ++- src/components/ShowTokenButton.js | 66 ++++++++++++++++++++++++++++++ src/components/auth/authControl.js | 2 +- src/components/basket/APIButton.js | 2 +- src/contexts/GlobalContext.js | 10 +++-- src/routes/Routes.js | 2 +- src/utils/styling.js | 19 ++++++++- 7 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 src/components/ShowTokenButton.js diff --git a/src/components/NavBar.js b/src/components/NavBar.js index 9ee6243..da34ccd 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 0000000..a6cda00 --- /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 ebf8aae..3cb663c 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 78128ef..5561eb6 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 deea45d..ba39d3e 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 30ba160..10a5add 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 595d649..c11c1c6 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 -- GitLab