This repository has been archived by the owner on Sep 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* start of login page * env and google auth button * merge with main, remove params reference * start of okta auth * initial commit for handling auth token (#67) * start of login with keycloak * handle google sign in with token * more google auth * profile dropdown * merge with main * merge with main * convert to axios * start of readme instructions * get current user endpoint (#70) clean up some other endpoints * commenting out UI until repositories are merged * clean up current user (#74) * yarn lock file * remove keycloak for now, node version error in jwt-decode dependency * commit yarn lock * remove state as useEffect dependency, comment out currentUser call for now --------- Co-authored-by: Xiang Xu <[email protected]>
- Loading branch information
1 parent
24badda
commit 4f9403d
Showing
25 changed files
with
1,772 additions
and
859 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Google config | ||
REACT_APP_GOOGLE_AUTH_ENABLED=false | ||
REACT_APP_GOOGLE_CLIENT_ID= | ||
|
||
# Okta config | ||
REACT_APP_OKTA_AUTH_ENABLED=false | ||
REACT_APP_OKTA_DOMAIN= | ||
REACT_APP_OKTA_CLIENT_ID= | ||
|
||
# Keycloak config | ||
REACT_APP_KEYCLOAK_AUTH_ENABLED=false | ||
REACT_APP_KEYCLOAK_URL= | ||
REACT_APP_KEYCLOAK_REALM_ID= | ||
REACT_APP_KEYCLOAK_CLIENT_ID= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,13 @@ | ||
import React from 'react'; | ||
import { ConfigProvider, Layout, Menu } from 'antd'; | ||
import React, { useMemo } from 'react'; | ||
import { | ||
Avatar, | ||
ConfigProvider, | ||
Dropdown, | ||
Layout, | ||
Menu, | ||
MenuProps, | ||
Typography, | ||
} from 'antd'; | ||
import { | ||
createBrowserRouter, | ||
Outlet, | ||
|
@@ -16,6 +24,9 @@ import CatalogsList from './pages/CatalogsList'; | |
import CatalogDetails from './pages/CatalogDetails'; | ||
import SchemaDetails from './pages/SchemaDetails'; | ||
import { NotificationProvider } from './utils/NotificationContext'; | ||
import Login from './pages/Login'; | ||
import { AuthProvider, useAuth } from './context/auth-context'; | ||
import { UserOutlined } from '@ant-design/icons'; | ||
|
||
const router = createBrowserRouter([ | ||
{ | ||
|
@@ -50,8 +61,43 @@ const router = createBrowserRouter([ | |
]); | ||
|
||
function AppProvider() { | ||
const { accessToken, logout } = useAuth(); | ||
const navigate = useNavigate(); | ||
const loggedIn = accessToken !== ''; | ||
|
||
const profileMenuItems = useMemo( | ||
(): MenuProps['items'] => [ | ||
{ | ||
key: 'userInfo', | ||
label: ( | ||
<div | ||
style={{ | ||
display: 'flex', | ||
flexDirection: 'column', | ||
cursor: 'default', | ||
}} | ||
> | ||
<Typography.Text>User name here</Typography.Text> | ||
<Typography.Text>[email protected]</Typography.Text> | ||
</div> | ||
), | ||
}, | ||
{ | ||
type: 'divider', | ||
}, | ||
{ | ||
key: 'logout', | ||
label: 'Log out', | ||
onClick: () => logout().then(() => navigate('/')), | ||
}, | ||
], | ||
[], | ||
); | ||
|
||
// commenting login UI for now until repositories are merged | ||
// return !loggedIn ? ( | ||
// <Login /> | ||
// ) : ( | ||
return ( | ||
<ConfigProvider | ||
theme={{ | ||
|
@@ -65,23 +111,54 @@ function AppProvider() { | |
> | ||
<Layout> | ||
{/* Header */} | ||
<Layout.Header style={{ display: 'flex', alignItems: 'center' }}> | ||
<div style={{ marginRight: 24 }} onClick={() => navigate('/')}> | ||
<img src="/uc-logo-reverse.png" height={32} alt="uc-logo-reverse" /> | ||
<Layout.Header | ||
style={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
width: '100%', | ||
justifyContent: 'space-between', | ||
}} | ||
> | ||
<div | ||
style={{ display: 'flex', alignItems: 'center', flex: '1 0 auto' }} | ||
> | ||
<div style={{ marginRight: 24 }} onClick={() => navigate('/')}> | ||
<img | ||
src="/uc-logo-reverse.png" | ||
height={32} | ||
alt="uc-logo-reverse" | ||
/> | ||
</div> | ||
<Menu | ||
theme="dark" | ||
mode="horizontal" | ||
defaultSelectedKeys={['catalogs']} | ||
items={[ | ||
{ | ||
key: 'catalogs', | ||
label: 'Catalogs', | ||
onClick: () => navigate('/'), | ||
}, | ||
]} | ||
style={{ flex: 1, minWidth: 0 }} | ||
/> | ||
</div> | ||
<Menu | ||
theme="dark" | ||
mode="horizontal" | ||
defaultSelectedKeys={['catalogs']} | ||
items={[ | ||
{ | ||
key: 'catalogs', | ||
label: 'Catalogs', | ||
onClick: () => navigate('/'), | ||
}, | ||
]} | ||
style={{ flex: 1, minWidth: 0 }} | ||
/> | ||
{/*<div>*/} | ||
{/* <Dropdown*/} | ||
{/* menu={{ items: profileMenuItems }}*/} | ||
{/* trigger={['click']}*/} | ||
{/* placement={'bottomRight'}*/} | ||
{/* >*/} | ||
{/* <Avatar*/} | ||
{/* icon={<UserOutlined />}*/} | ||
{/* style={{*/} | ||
{/* backgroundColor: 'white',*/} | ||
{/* color: 'black',*/} | ||
{/* cursor: 'pointer',*/} | ||
{/* }}*/} | ||
{/* />*/} | ||
{/* </Dropdown>*/} | ||
{/*</div>*/} | ||
</Layout.Header> | ||
{/* Content */} | ||
<Layout.Content | ||
|
@@ -118,6 +195,7 @@ function AppProvider() { | |
</Layout> | ||
</ConfigProvider> | ||
); | ||
// ); | ||
} | ||
|
||
function App() { | ||
|
@@ -128,7 +206,9 @@ function App() { | |
return ( | ||
<NotificationProvider> | ||
<QueryClientProvider client={queryClient}> | ||
<RouterProvider router={router} fallbackElement={<p>Loading...</p>} /> | ||
<AuthProvider> | ||
<RouterProvider router={router} fallbackElement={<p>Loading...</p>} /> | ||
</AuthProvider> | ||
</QueryClientProvider> | ||
</NotificationProvider> | ||
); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { useCallback, useEffect, useMemo } from 'react'; | ||
import { Button } from 'antd'; | ||
|
||
export default function GoogleAuthButton({ | ||
onGoogleSignIn, | ||
}: { | ||
onGoogleSignIn: (credential: string) => void; | ||
}) { | ||
const clientId = useMemo(() => process.env.REACT_APP_GOOGLE_CLIENT_ID, []); | ||
|
||
const handleGoogleSignIn = useCallback( | ||
(res: any) => { | ||
if (!res.clientId || !res.credential) return; | ||
onGoogleSignIn(res.credential); | ||
}, | ||
[onGoogleSignIn], | ||
); | ||
|
||
useEffect(() => { | ||
const url = 'https://accounts.google.com/gsi/client'; | ||
const scripts = document.getElementsByTagName('script'); | ||
const isGsiScriptLoaded = Array.from(scripts).some( | ||
(script) => script.src === url, | ||
); | ||
|
||
if (isGsiScriptLoaded) return; | ||
|
||
const initializeGsi = () => { | ||
// Typescript will complain about window.google | ||
// Add types to your `react-app-env.d.ts` or //@ts-ignore it. | ||
if (!(window as any).google || isGsiScriptLoaded) return; | ||
|
||
(window as any).google.accounts.id.initialize({ | ||
client_id: process.env.REACT_APP_GOOGLE_CLIENT_ID, | ||
callback: handleGoogleSignIn, | ||
}); | ||
|
||
(window as any).google.accounts.id.renderButton( | ||
document.getElementById('google-client-button'), | ||
{ | ||
text: 'continue_with', // customization attributes | ||
width: 240, | ||
theme: 'outline', | ||
}, | ||
); | ||
}; | ||
|
||
const script = document.createElement('script'); | ||
script.src = 'https://accounts.google.com/gsi/client'; | ||
script.onload = initializeGsi; | ||
script.defer = true; | ||
script.async = true; | ||
script.id = 'google-client-script'; | ||
document.querySelector('body')?.appendChild(script); | ||
|
||
return () => { | ||
// Cleanup function that runs when component unmounts | ||
(window as any).google?.accounts.id.cancel(); | ||
document.getElementById('google-client-script')?.remove(); | ||
}; | ||
}, [handleGoogleSignIn]); | ||
|
||
return ( | ||
<> | ||
{clientId && <Button style={{ width: 240 }} id="google-client-button" />} | ||
</> | ||
); | ||
} |
Oops, something went wrong.