diff --git a/src/src/App.css b/src/src/App.css index e8497952..c74bdf08 100644 --- a/src/src/App.css +++ b/src/src/App.css @@ -70,6 +70,10 @@ margin-right: 2px; } +.logout button div.MuiLoadingButton-loadingIndicator span{ + color: white; +} + .inline-icon { margin-right: 1em; } diff --git a/src/src/App.js b/src/src/App.js index 9e32a480..53dc4477 100644 --- a/src/src/App.js +++ b/src/src/App.js @@ -31,6 +31,7 @@ import IconButton from '@mui/material/IconButton'; import AnnouncementTwoToneIcon from '@mui/icons-material/AnnouncementTwoTone'; import {ingest_api_all_groups,ingest_api_users_groups} from './service/ingest_api'; +import {api_validate_token} from './service/search_api'; import {ubkg_api_get_dataset_type_set,ubkg_api_get_organ_type_set} from "./service/ubkg_api"; import {sortGroupsByDisplay} from "./service/user_service"; import {BuildError} from "./utils/error_helper"; @@ -60,13 +61,15 @@ import Forms from "./components/uuid/forms"; export function App (props){ let navigate = useNavigate(); + var [expiredKey,setExpiredKey ] = useState(false); + var [loginError,setLoginError ] = useState(""); var [loginDialogRender, setLoginDialogRender] = useState(false); var [successDialogRender, setSuccessDialogRender] = useState(false); var [snackMessage, setSnackMessage] = useState(""); var [showSnack, setShowSnack] = useState(false); var [newEntity, setNewEntity] = useState(null); var [authStatus, setAuthStatus] = useState(false); - var [unregStatus, setUnegStatus] = useState(false); + var [unregStatus, setUnregStatus] = useState(false); var [groupsToken, setGroupsToken] = useState(null); var [allGroups, setAllGroups] = useState(null); var [timerStatus, setTimerStatus] = useState(true); @@ -75,8 +78,10 @@ export function App (props){ var [organList, setOrganList] = useState(); var [userGroups, setUserGroups] = useState({}); var [userDataGroups, setUserDataGroups] = useState({}); + var [userDev, setUserDev] = useState(false); - var [regStatus, setRegStatus] = useState(false); + // var [regStatus, setRegStatus] = useState(false); + var [isLoggingOut, setIsLoggingOut] = useState(false); var [isLoading, setIsLoading] = useState(true); var [dtloading, setDTLoading] = useState(true); var [bannerTitle,setBannerTitle] = useState(); @@ -87,11 +92,49 @@ export function App (props){ Datasets:["Registering individual datasets is currently disabled.","/new/upload"], }); + useEffect(() => { + // API Key Validity Check + console.debug('%c◉ API Key Validity ', 'color:#00ff7b',localStorage.getItem("info") ); + if(localStorage.getItem("info") ){ + console.debug('%c◉ localStorage.getItem("info") ', 'color:#00ff7b', localStorage.getItem("info")); + // try { + api_validate_token(JSON.parse(localStorage.getItem("info")).groups_token) + .then((results) => { + console.debug('%c◉ results ', 'color:#00ff7b', results); + if(results.error && results.error.response && results.error.response.status){ + console.debug('%c◉ results.error.response.data ', 'color:#ff005d', results.error.response.data); + console.debug('%c◉ results.error.response.data.error ', 'color:#ff005d', results.error.response.data.error?results.error.response.data.error:"NOMESSAGE"); + setLoginError(results.error.response.data.error ? results.error.response.data.error : "API Key Error"); + console.debug('%c◉ results.error.response.status', 'color:#00ff7b',results.error.response.status ); + if(results.error.response.status === 401){ + console.debug('%c◉ EXPIRED ', 'color:#ff005d' ); + setExpiredKey(true); + // setTimerStatus(false); + // setIsLoading(false); + // setAuthStatus(false); + // // reportError("error", "API Key Expired"); + // localStorage.removeItem('info'); + } + }else if(!results.error){ + console.debug('%c◉ API Key OK ', 'color:#00ff7b', results); + } + }) + .catch((err) => { + console.debug('%c⭗', 'color:#ff005d', "API Key Validity ERR", err ); + }) + + }else{ + console.debug('%c◉ No Local Storage Key to check validity against ', 'color:#00ff7b', ); + } + + + },[]) useEffect(() => { console.debug("useEffect URL/Info"); let url = new URL(window.location.href); let info = url.searchParams.get("info"); + if (info !== null) { localStorage.setItem("info", info); localStorage.setItem("isAuthenticated", true); @@ -99,59 +142,34 @@ export function App (props){ window.location.replace(`${process.env.REACT_APP_URL}`); } - if(localStorage.getItem("info") ){ - console.debug('%c◉ localStorage.getItem("info") ', 'color:#00ff7b', localStorage.getItem("info")); - try { - ingest_api_users_groups(JSON.parse(localStorage.getItem("info")).groups_token).then((results) => { - // console.debug("LocalStorageAuth", results); - - if (results && results.status === 200) { - // console.debug("LocalStorageAuth", results); - setUserGroups(results.results); - setUserDataGroups(results.results); - if (results.results.length > 0) { - setRegStatus(true); - for (let group in results.results) { - if(results.results[group].displayname.includes("IEC")){ - setUserDev(true) - } + try { + ingest_api_users_groups(JSON.parse(localStorage.getItem("info")).groups_token).then((results) => { + console.debug('%c◉ RESULTS ', 'color:#00ff7b', results); + if (results && results.status === 200) { + setUserGroups(results.results); + setUserDataGroups(results.results); + if (results.results.length > 0) { + for (let group in results.results) { + if(results.results[group].displayname.includes("IEC")){ + setUserDev(true) } } - setGroupsToken(JSON.parse(localStorage.getItem("info")).groups_token); - setTimerStatus(false); - setIsLoading(false); - setAuthStatus(true); - } else if (results && results.status === 401) { - console.debug('%c◉ FAIL WITH 410 ', 'color:#00ff7b', ); - setGroupsToken(null); - setAuthStatus(false); - setRegStatus(false); - setTimerStatus(false); - setIsLoading(false); - if (localStorage.getItem("isHubmapUser")) { - // If we were logged out and we have an old token, - // We should promopt to sign back in - CallLoginDialog(); - } - } else if (results && results.status === 403 && results.results === "User is not a member of group HuBMAP-read") { - // console.debug("HERE results", results, results.results); - setAuthStatus(true); - setRegStatus(false); - setUnegStatus(true); - setIsLoading(false); + } + setGroupsToken(JSON.parse(localStorage.getItem("info")).groups_token); + setTimerStatus(false); + setIsLoading(false); + setAuthStatus(true); } }); - }catch(error){ - console.debug('%c◉ FAIL WITH ERROR 410 ', 'color:#ff0000', ); - setTimerStatus(false); - setIsLoading(false) - throw new Error(error); - } - }else{ + }catch(error){ + console.debug('%c◉ error, no results', 'color:#ff0000',error ); setTimerStatus(false); setIsLoading(false) - setAuthStatus(false); + // localStorage.clear(); + // throw new Error(error); + } + }, [ ]); useEffect(() => { @@ -172,16 +190,10 @@ export function App (props){ }) }) .catch(error => { - if (unregStatus) { - setGroupsToken(JSON.parse(localStorage.getItem("info")).groups_token); - setTimerStatus(false); - CallLoginDialog(); - } else { console.debug('%c⭗', 'color:#ff005d', "APP ubkg_api_get_assay_type_set ERROR", error); - reportError(error) - } + reportError(error) }); - }, [unregStatus ]); + }, [ ]); useEffect(() => { if(localStorage.getItem("info")){ @@ -227,27 +239,19 @@ export function App (props){ console.debug('%c◉ stripUrl ', 'color:#00ff7b', stripUrl); } },[]) + - function clearAuths() { - console.debug('%c◉ CLEAR AUTHS ', 'color:#00ff7b' ); - if(process.env.REACT_APP_URL == "http://localhost:8585"){ - console.debug('%c◉ clearAuths start ', 'color:#00ff7b' ); - return new Promise((resolve) => { - setTimeout(() => { // Give it a chance to cleaer the local storage - localStorage.removeItem("info"); - localStorage.removeItem("isAuthenticated"); - resolve(); - }, 2000); - }); - } - } - function Logout(){ - clearAuths().then((response) => { - console.debug('%c◉ response', 'color:#00ff7b',response ); - window.location.replace(`${process.env.REACT_APP_DATAINGEST_API_URL}/logout`) - }) + function Logout(e){ + setIsLoggingOut(true); + localStorage.removeItem('info'); + window.location.replace(`${process.env.REACT_APP_DATAINGEST_API_URL}/logout`) + }; + + function closeExpiredSnack(){ + // setExpiredKey(false) + // window.location.reload(); }; function handleCancel(){ @@ -296,6 +300,7 @@ export function App (props){ const app_info_storage = localStorage.getItem("info") ? JSON.parse(localStorage.getItem("info")) : ""; const { search } = useLocation(); + // @TODO: is search itself already handling this / is this an old prop drill? const queryParams = new URLSearchParams(search); const queryEntity = queryParams.has("entity_type")?queryParams.get("entity_type"):null const queryKeyword = queryParams.has("keywords")?queryParams.get("keywords"):null @@ -324,257 +329,237 @@ export function App (props){ } return ( -
- + +
+ closeExpiredSnack()}> + {loginError} + - { process.env.REACT_APP_URL!=="http://localhost:8585" && ()} + { !userDev && ()}
- - - - - Sorry! Something's gone wrong... - setErrorShow(false)} - edge="start"> - - - - - - - - - There's been an error handling the current task. Please try again later.
- If the problem persists, please contact the HuBMAP Help Desk at help@hubmapconsortium.org -
-
+ { + console.log("Error caught!"); + console.error(error); + console.error(errorInfo); + }}> + + + + + Sorry! Something's gone wrong... + setErrorShow(false)} + edge="start"> + + + + + + + + + There's been an error handling the current task. Please try again later.
+ If the problem persists, please contact the HuBMAP Help Desk at help@hubmapconsortium.org +
+
- - - Error Details: setErrorInfoShow(!errorInfoShow)}> - - { errorDetail && errorDetail.length>0 && ( - ERR{errorDetail} - )} - - - {errorInfo} + + + Error Details: setErrorInfoShow(!errorInfoShow)}> - + { errorDetail && errorDetail.length>0 && ( + {errorDetail} + )} + + + {errorInfo} + + +
-
-
+ -
- { !isLoading && bannerShow && ( -
-

{bannerTitle}

-
-
- )} - {isLoading || dtloading || (groupsToken && (!allGroups || allGroups.length<=0)) && ( - - )} + + { !isLoading && bannerShow && ( +
+

{bannerTitle}

+
+
+ )} + {isLoading || dtloading || (groupsToken && (!allGroups || allGroups.length<=0)) && ( + + )} - { !authStatus && ( - - - } /> - } /> - } /> - } /> - - - + { !authStatus && ( - Session Has Ended + + } /> + } /> + } /> + } /> + - - - -
- It looks like your login session has ended. Please log in again to continue -
-
- - - -
-
- - )} - - {unregStatus && ( - - - You do not have access to the HuBMAP Ingest Registration System. You can request access by checking the "HuBMAP Data Via Globus" system in your profile. If you continue to have issues and have selected the "HuBMAP Data Via Globus" option make sure you have accepted the invitation to the Globus Group "HuBMAP-Read" or contact the help desk at help@hubmapconsortium.org - - }/> - - )} - - {authStatus && !timerStatus && !isLoading && !dtloading && !unregStatus &&( - { - console.log("Error caught!"); - console.error(error); - console.error(errorInfo); - }}> - - - - - - } /> - } /> - } /> - - {authStatus && (!userDataGroups || userDataGroups.length === 0) && !isLoading && ( - {window.history.back()}}> - Cancel - - }> - You do not have privileges to create registrations in this system. Please contact the help desk at help@hubmapconsortium.org and ask to be added to your HuBMAP Component's access group - - }/> - - - )} - - {authStatus && (userDataGroups && userDataGroups.length > 0) && !isLoading && (allGroups && allGroups.length > 0) && ( - - } /> - }/> - }/> - } /> - creationSuccess(response)} onReturn={() => onClose()} handleCancel={() => handleCancel()} /> }/> - creationSuccess(response)} onReturn={() => onClose()} handleCancel={() => handleCancel()} /> }/> - } > - }/> - }/> {/*Will make sure the search load under the modal */} - - {/* {userDev && ( - }/> - )} - {!userDev && ( + + )} + + {unregStatus && ( + + + You do not have access to the HuBMAP Ingest Registration System. You can request access by checking the "HuBMAP Data Via Globus" system in your profile. If you continue to have issues and have selected the "HuBMAP Data Via Globus" option make sure you have accepted the invitation to the Globus Group "HuBMAP-Read" or contact the help desk at help@hubmapconsortium.org + + }/> + + )} + + {authStatus && !timerStatus && !isLoading && !dtloading && !unregStatus &&( + + + + + + } /> + } /> + } /> + + {authStatus && (!userDataGroups || userDataGroups.length === 0) && !isLoading && ( + {window.history.back()}}> + Cancel + + }> + You do not have privileges to create registrations in this system. Please contact the help desk at help@hubmapconsortium.org and ask to be added to your HuBMAP Component's access group + + }/> + + + )} + + {authStatus && (userDataGroups && userDataGroups.length > 0) && !isLoading && (allGroups && allGroups.length > 0) && ( + + } /> + }/> + }/> + } /> + creationSuccess(response)} onReturn={() => onClose()} handleCancel={() => handleCancel()} /> }/> + creationSuccess(response)} onReturn={() => onClose()} handleCancel={() => handleCancel()} /> }/> } > - )} */} - - )} - } > - } > - } > - } > - } > - - } /> - } /> - } /> - } /> - } /> - updateSuccess(response)} reportError={reportError} handleCancel={handleCancel} status="view" />} /> - updateSuccess(response)} reportError={reportError} handleCancel={handleCancel} status="view" />} /> - - } /> - } /> - - } /> - }/> - }/> - }/> - - - - - - {newEntity && ( - + }/> + }/> {/*Will make sure the search load under the modal */} + + {/* {userDev && ( + }/> + )} + {!userDev && ( + } > + )} */} + )} - - - setShowSnack(false)} - anchorOrigin={{vertical: 'bottom', - horizontal:'right',}} - autoHideDuration={6000} - action={ - setShowSnack(false)}> - - - }> - {snackMessage} - - - - + } > + } > + } > + } > + } > + + } /> + } /> + } /> + } /> + } /> + updateSuccess(response)} reportError={reportError} handleCancel={handleCancel} status="view" />} /> + updateSuccess(response)} reportError={reportError} handleCancel={handleCancel} status="view" />} /> + + } /> + } /> + + } /> + }/> + }/> + }/> + + + + + + {newEntity && ( + + )} + + + setShowSnack(false)} + anchorOrigin={{vertical: 'bottom', + horizontal:'right',}} + autoHideDuration={6000} + action={ + setShowSnack(false)}> + + + }> + {snackMessage} + + + + + )} + - )} +
-
); } diff --git a/src/src/Nav.js b/src/src/Nav.js index 2da8dc46..046331cc 100644 --- a/src/src/Nav.js +++ b/src/src/Nav.js @@ -17,6 +17,7 @@ import MenuItem from '@mui/material/MenuItem'; import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; +import LoadingButton from '@mui/lab/LoadingButton'; import UploadsForm from "./components/uploads/createUploads"; @@ -91,7 +92,7 @@ export const Navigation = (props) => { { { }}> - + src="https://hubmapconsortium.org/wp-content/uploads/2020/09/hubmap-type-white250.png" + height="40" + className="d-inline-block align-top" + id="MenuLogo" + alt="HuBMAP logo" + /> + {props.login && userDataGroups[0] && userDataGroups[0].length >0 &&( @@ -443,12 +444,10 @@ export const Navigation = (props) => { Edit Profile - - + {}
diff --git a/src/src/assets/App.css b/src/src/assets/App.css index e2109b8e..69f594a7 100644 --- a/src/src/assets/App.css +++ b/src/src/assets/App.css @@ -70,6 +70,10 @@ margin-right: 2px; } +.logout button div.MuiLoadingButton-loadingIndicator span{ + color: white; +} + .inline-icon { margin-right: 1em; } diff --git a/src/src/components/search/searchTable.jsx b/src/src/components/search/searchTable.jsx index 2725fc92..1daa1c13 100644 --- a/src/src/components/search/searchTable.jsx +++ b/src/src/components/search/searchTable.jsx @@ -161,6 +161,10 @@ export const RenderSearchTable = (props) => { "newTable" ) .then((response) => { + if(response.error){ + console.debug('%c◉ Error on Search ', 'color:#ff005d', response.error); + errorReporting(response.error) + } console.debug('%c◉ searchFilterParams ', 'color:#00d184', searchFilterParams); setTableLoading(false); console.debug('%c⊙useEffect Search', 'color:rgb(0 140 255)', response.total, response.results );