mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(console): integrate React SDK
This commit is contained in:
parent
56c8b6069a
commit
38d8196794
32 changed files with 168 additions and 51 deletions
1
.npmrc
1
.npmrc
|
@ -1,4 +1,5 @@
|
|||
# Hoist for Parcel
|
||||
public-hoist-pattern[]=@parcel/*
|
||||
public-hoist-pattern[]=postcss
|
||||
public-hoist-pattern[]=process
|
||||
public-hoist-pattern[]=*eslint*
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
},
|
||||
"alias": {
|
||||
"html-parse-stringify": "html-parse-stringify/dist/html-parse-stringify.module.js",
|
||||
"react-hook-form": "react-hook-form/dist/index.esm.mjs"
|
||||
"react-hook-form": "react-hook-form/dist/index.esm.mjs",
|
||||
"superstruct": "superstruct/lib/index.es.js"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@logto/phrases": "^0.1.0",
|
||||
"@logto/react": "^0.1.2",
|
||||
"@logto/schemas": "^0.1.0",
|
||||
"@monaco-editor/react": "^4.3.1",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
|
@ -55,6 +56,7 @@
|
|||
"postcss": "^8.4.6",
|
||||
"postcss-modules": "^4.3.0",
|
||||
"prettier": "^2.3.2",
|
||||
"process": "^0.11.10",
|
||||
"stylelint": "^13.13.1",
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
padding-right: _.unit(5);
|
||||
margin-bottom: _.unit(6);
|
||||
overflow: hidden;
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
import { LogtoProvider } from '@logto/react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { BrowserRouter, Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { SWRConfig } from 'swr';
|
||||
import './scss/normalized.scss';
|
||||
|
||||
import * as styles from './App.module.scss';
|
||||
import AppContent from './components/AppContent';
|
||||
import Content from './components/Content';
|
||||
import Sidebar, { getPath, sections } from './components/Sidebar';
|
||||
import { getPath, sections } from './components/AppContent/components/Sidebar';
|
||||
import Callback from './components/Callback';
|
||||
import Toast from './components/Toast';
|
||||
import Topbar from './components/Topbar';
|
||||
import initI18n from './i18n/init';
|
||||
import ApiResourceDetails from './pages/ApiResourceDetails';
|
||||
import ApiResources from './pages/ApiResources';
|
||||
|
@ -34,39 +33,36 @@ const Main = () => {
|
|||
}, [location.pathname, navigate]);
|
||||
|
||||
return (
|
||||
<SWRConfig value={{ fetcher }}>
|
||||
<Toast />
|
||||
<AppContent theme="light">
|
||||
<Topbar />
|
||||
<div className={styles.content}>
|
||||
<Sidebar />
|
||||
<Content>
|
||||
<Routes>
|
||||
<Route path="applications">
|
||||
<Route index element={<Applications />} />
|
||||
<Route path=":id">
|
||||
<Route index element={<Navigate to="settings" />} />
|
||||
<Route path="settings" element={<ApplicationDetails />} />
|
||||
<Route path="advanced-settings" element={<ApplicationDetails />} />
|
||||
</Route>
|
||||
<LogtoProvider logtoConfig={{ endpoint: 'https://logto.dev', clientId: 'foo' }}>
|
||||
<SWRConfig value={{ fetcher }}>
|
||||
<Toast />
|
||||
<Routes>
|
||||
<Route path="callback" element={<Callback />} />
|
||||
<Route element={<AppContent theme="light" />}>
|
||||
<Route path="applications">
|
||||
<Route index element={<Applications />} />
|
||||
<Route path=":id">
|
||||
<Route index element={<Navigate to="settings" />} />
|
||||
<Route path="settings" element={<ApplicationDetails />} />
|
||||
<Route path="advanced-settings" element={<ApplicationDetails />} />
|
||||
</Route>
|
||||
<Route path="api-resources">
|
||||
<Route index element={<ApiResources />} />
|
||||
<Route path=":id" element={<ApiResourceDetails />} />
|
||||
</Route>
|
||||
<Route path="connectors">
|
||||
<Route index element={<Connectors />} />
|
||||
<Route path="social" element={<Connectors />} />
|
||||
<Route path=":connectorId" element={<ConnectorDetails />} />
|
||||
</Route>
|
||||
<Route path="users">
|
||||
<Route index element={<Users />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Content>
|
||||
</div>
|
||||
</AppContent>
|
||||
</SWRConfig>
|
||||
</Route>
|
||||
<Route path="api-resources">
|
||||
<Route index element={<ApiResources />} />
|
||||
<Route path=":id" element={<ApiResourceDetails />} />
|
||||
</Route>
|
||||
<Route path="connectors">
|
||||
<Route index element={<Connectors />} />
|
||||
<Route path="social" element={<Connectors />} />
|
||||
<Route path=":connectorId" element={<ConnectorDetails />} />
|
||||
</Route>
|
||||
<Route path="users">
|
||||
<Route index element={<Users />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
</SWRConfig>
|
||||
</LogtoProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@use '@/scss/colors' as colors;
|
||||
@use '@/scss/underscore' as _;
|
||||
|
||||
.app {
|
||||
position: absolute;
|
||||
|
@ -7,6 +8,14 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
padding-right: _.unit(5);
|
||||
margin-bottom: _.unit(6);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.light {
|
||||
@include colors.light-theme;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import React, { ReactNode, useEffect } from 'react';
|
||||
import { useLogto } from '@logto/react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Outlet, useHref } from 'react-router-dom';
|
||||
|
||||
import Content from './components/Content';
|
||||
import Sidebar from './components/Sidebar';
|
||||
import Topbar from './components/Topbar';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Theme = 'light';
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
theme: Theme;
|
||||
};
|
||||
|
||||
const AppContent = ({ children, theme }: Props) => {
|
||||
const AppContent = ({ theme }: Props) => {
|
||||
const { isAuthenticated, signIn } = useLogto();
|
||||
const href = useHref('/callback');
|
||||
|
||||
useEffect(() => {
|
||||
const classes = [styles.web, styles[theme]].filter((value): value is string => Boolean(value));
|
||||
document.body.classList.add(...classes);
|
||||
|
@ -19,7 +26,27 @@ const AppContent = ({ children, theme }: Props) => {
|
|||
};
|
||||
}, [theme]);
|
||||
|
||||
return <div className={styles.app}>{children}</div>;
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) {
|
||||
void signIn(new URL(href, window.location.origin).toString());
|
||||
}
|
||||
}, [href, isAuthenticated, signIn]);
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return <>loading</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.app}>
|
||||
<Topbar />
|
||||
<div className={styles.content}>
|
||||
<Sidebar />
|
||||
<Content>
|
||||
<Outlet />
|
||||
</Content>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppContent;
|
||||
|
|
18
packages/console/src/components/Callback/index.tsx
Normal file
18
packages/console/src/components/Callback/index.tsx
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { useLogto } from '@logto/react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const Callback = () => {
|
||||
const { isAuthenticated, isLoading } = useLogto();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated && !isLoading) {
|
||||
navigate('/', { replace: true });
|
||||
}
|
||||
}, [isAuthenticated, isLoading, navigate]);
|
||||
|
||||
return <p>Redirecting...</p>;
|
||||
};
|
||||
|
||||
export default Callback;
|
|
@ -21,6 +21,7 @@ importers:
|
|||
packages/console:
|
||||
specifiers:
|
||||
'@logto/phrases': ^0.1.0
|
||||
'@logto/react': ^0.1.2
|
||||
'@logto/schemas': ^0.1.0
|
||||
'@monaco-editor/react': ^4.3.1
|
||||
'@parcel/core': ^2.3.2
|
||||
|
@ -47,6 +48,7 @@ importers:
|
|||
postcss: ^8.4.6
|
||||
postcss-modules: ^4.3.0
|
||||
prettier: ^2.3.2
|
||||
process: ^0.11.10
|
||||
react: ^17.0.2
|
||||
react-dom: ^17.0.2
|
||||
react-hook-form: ^7.27.1
|
||||
|
@ -61,6 +63,7 @@ importers:
|
|||
typescript: ^4.6.2
|
||||
dependencies:
|
||||
'@logto/phrases': link:../phrases
|
||||
'@logto/react': 0.1.2_react@17.0.2
|
||||
'@logto/schemas': link:../schemas
|
||||
'@monaco-editor/react': 4.3.1_e62f1489d5efe674a41c3f8d6971effe
|
||||
'@silverhand/essentials': 1.1.6
|
||||
|
@ -98,6 +101,7 @@ importers:
|
|||
postcss: 8.4.6
|
||||
postcss-modules: 4.3.0_postcss@8.4.6
|
||||
prettier: 2.5.1
|
||||
process: 0.11.10
|
||||
stylelint: 13.13.1
|
||||
typescript: 4.6.2
|
||||
|
||||
|
@ -2233,6 +2237,38 @@ packages:
|
|||
prop-types: 15.8.1
|
||||
react: 17.0.2
|
||||
react-dom: 17.0.2_react@17.0.2
|
||||
/@logto/browser/0.1.2:
|
||||
resolution: {integrity: sha512-sTJjnx00BXYEChCbbO/LPs0x0wE1bDSHniFi+u93cynyEHgoT5yjMnH4N39NhrpmRdkXxOxaIkXmyAT1nSmYzQ==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@logto/js': 0.1.2
|
||||
'@silverhand/essentials': 1.1.6
|
||||
jose: 4.6.0
|
||||
lodash.get: 4.4.2
|
||||
superstruct: 0.15.4
|
||||
dev: false
|
||||
|
||||
/@logto/js/0.1.2:
|
||||
resolution: {integrity: sha512-kz7l++gfpXa1OaUaB5WvnHNXQKEJDFnBzVYAofPADnPftHEF0zYRuQDCa8PJMd6/ECKfL1XPLMlJMNP/5U2fqQ==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@silverhand/essentials': 1.1.6
|
||||
camelcase-keys: 7.0.2
|
||||
jose: 4.6.0
|
||||
js-base64: 3.7.2
|
||||
lodash.get: 4.4.2
|
||||
superstruct: 0.15.4
|
||||
dev: false
|
||||
|
||||
/@logto/react/0.1.2_react@17.0.2:
|
||||
resolution: {integrity: sha512-kxLOvxOv3IB8BjpbcoRFsBFX249wAfbOL0tfJlSWmOXrkPouai1bRItEFBHFKDI1zLJATVQRoJNQfaczJy/c0A==}
|
||||
requiresBuild: true
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
'@logto/browser': 0.1.2
|
||||
'@silverhand/essentials': 1.1.6
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/@nodelib/fs.scandir/2.1.5:
|
||||
|
@ -4506,6 +4542,16 @@ packages:
|
|||
quick-lru: 4.0.1
|
||||
dev: true
|
||||
|
||||
/camelcase-keys/7.0.2:
|
||||
resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
camelcase: 6.3.0
|
||||
map-obj: 4.3.0
|
||||
quick-lru: 5.1.1
|
||||
type-fest: 1.4.0
|
||||
dev: false
|
||||
|
||||
/camelcase/5.3.1:
|
||||
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -4515,6 +4561,11 @@ packages:
|
|||
resolution: {integrity: sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
/camelcase/6.3.0:
|
||||
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/caniuse-api/3.0.0:
|
||||
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
|
||||
dependencies:
|
||||
|
@ -8568,6 +8619,14 @@ packages:
|
|||
resolution: {integrity: sha512-S7Xfsy8nN9Iw/AZxk+ZxEbd5ImIwJPM0TfAo8zI8FF+3lidQ2yiK4dqzsaPKSbZD0woNVSY0KCql6rlKc5V7ug==}
|
||||
dev: false
|
||||
|
||||
/jose/4.6.0:
|
||||
resolution: {integrity: sha512-0hNAkhMBNi4soKSAX4zYOFV+aqJlEz/4j4fregvasJzEVtjDChvWqRjPvHwLqr5hx28Ayr6bsOs1Kuj87V0O8w==}
|
||||
dev: false
|
||||
|
||||
/js-base64/3.7.2:
|
||||
resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==}
|
||||
dev: false
|
||||
|
||||
/js-tokens/4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
|
||||
|
@ -9073,7 +9132,6 @@ packages:
|
|||
|
||||
/lodash.get/4.4.2:
|
||||
resolution: {integrity: sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=}
|
||||
dev: true
|
||||
|
||||
/lodash.ismatch/4.4.0:
|
||||
resolution: {integrity: sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=}
|
||||
|
@ -11565,6 +11623,11 @@ packages:
|
|||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||
dev: true
|
||||
|
||||
/process/0.11.10:
|
||||
resolution: {integrity: sha1-czIwDoQBYb2j5podHZGn1LwW8YI=}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
dev: true
|
||||
|
||||
/promise-deferred/2.0.3:
|
||||
resolution: {integrity: sha512-n10XaoznCzLfyPFOlEE8iurezHpxrYzyjgq/1eW9Wk1gJwur/N7BdBmjJYJpqMeMcXK4wEbzo2EvZQcqjYcKUQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -13156,6 +13219,10 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/superstruct/0.15.4:
|
||||
resolution: {integrity: sha512-eOoMeSbP9ZJChNOm/9RYjE+F36rYR966AAqeG3xhQB02j2sfAUXDp4EQ/7bAOqnlJnuFDB8yvOu50SocvKpUEw==}
|
||||
dev: false
|
||||
|
||||
/supertest/6.2.2:
|
||||
resolution: {integrity: sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
@ -13666,6 +13733,11 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/type-fest/1.4.0:
|
||||
resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/type-fest/2.8.0:
|
||||
resolution: {integrity: sha512-O+V9pAshf9C6loGaH0idwsmugI2LxVNR7DtS40gVo2EXZVYFgz9OuNtOhgHLdHdapOEWNdvz9Ob/eeuaWwwlxA==}
|
||||
engines: {node: '>=12.20'}
|
||||
|
|
Loading…
Reference in a new issue