mirror of
https://github.com/logto-io/logto.git
synced 2025-03-17 22:31:28 -05:00
refactor(console): update app structure (#3066)
This commit is contained in:
parent
8bf28df796
commit
d3e786ec80
38 changed files with 124 additions and 83 deletions
|
@ -14,10 +14,10 @@ import './scss/overlayscrollbars.scss';
|
|||
|
||||
// eslint-disable-next-line import/no-unassigned-import
|
||||
import '@fontsource/roboto-mono';
|
||||
import AppBoundary from '@/components/AppBoundary';
|
||||
import AppContent from '@/components/AppContent';
|
||||
import ErrorBoundary from '@/components/ErrorBoundary';
|
||||
import Toast from '@/components/Toast';
|
||||
import AppBoundary from '@/containers/AppBoundary';
|
||||
import AppLayout from '@/containers/AppLayout';
|
||||
import ErrorBoundary from '@/containers/ErrorBoundary';
|
||||
import useSwrOptions from '@/hooks/use-swr-options';
|
||||
import initI18n from '@/i18n/init';
|
||||
import ApiResourceDetails from '@/pages/ApiResourceDetails';
|
||||
|
@ -47,8 +47,10 @@ import {
|
|||
SignInExperiencePage,
|
||||
UserDetailsTabs,
|
||||
} from './consts/page-tabs';
|
||||
import AppContent from './containers/AppContent';
|
||||
import ApiResourcePermissions from './pages/ApiResourceDetails/ApiResourcePermissions';
|
||||
import ApiResourceSettings from './pages/ApiResourceDetails/ApiResourceSettings';
|
||||
import CloudPreview from './pages/CloudPreview';
|
||||
import RolePermissions from './pages/RoleDetails/RolePermissions';
|
||||
import RoleSettings from './pages/RoleDetails/RoleSettings';
|
||||
import RoleUsers from './pages/RoleDetails/RoleUsers';
|
||||
|
@ -70,66 +72,78 @@ const Main = () => {
|
|||
<Routes>
|
||||
<Route path="callback" element={<Callback />} />
|
||||
<Route path="welcome" element={<Welcome />} />
|
||||
<Route element={<AppContent />}>
|
||||
<Route path="*" element={<NotFound />} />
|
||||
<Route path="get-started" element={<GetStarted />} />
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Route path="applications">
|
||||
<Route index element={<Applications />} />
|
||||
<Route path="create" element={<Applications />} />
|
||||
<Route path=":id" element={<ApplicationDetails />} />
|
||||
</Route>
|
||||
<Route path="api-resources">
|
||||
<Route index element={<ApiResources />} />
|
||||
<Route path="create" element={<ApiResources />} />
|
||||
<Route path=":id" element={<ApiResourceDetails />}>
|
||||
<Route element={<AppLayout />}>
|
||||
<Route path="/cloud-preview" element={<CloudPreview />} />
|
||||
<Route element={<AppContent />}>
|
||||
<Route path="*" element={<NotFound />} />
|
||||
<Route path="get-started" element={<GetStarted />} />
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Route path="applications">
|
||||
<Route index element={<Applications />} />
|
||||
<Route path="create" element={<Applications />} />
|
||||
<Route path=":id" element={<ApplicationDetails />} />
|
||||
</Route>
|
||||
<Route path="api-resources">
|
||||
<Route index element={<ApiResources />} />
|
||||
<Route path="create" element={<ApiResources />} />
|
||||
<Route path=":id" element={<ApiResourceDetails />}>
|
||||
<Route
|
||||
index
|
||||
element={<Navigate replace to={ApiResourceDetailsTabs.Settings} />}
|
||||
/>
|
||||
<Route
|
||||
path={ApiResourceDetailsTabs.Settings}
|
||||
element={<ApiResourceSettings />}
|
||||
/>
|
||||
<Route
|
||||
path={ApiResourceDetailsTabs.Permissions}
|
||||
element={<ApiResourcePermissions />}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="sign-in-experience">
|
||||
<Route
|
||||
index
|
||||
element={<Navigate replace to={ApiResourceDetailsTabs.Settings} />}
|
||||
element={<Navigate replace to={SignInExperiencePage.BrandingTab} />}
|
||||
/>
|
||||
<Route path={ApiResourceDetailsTabs.Settings} element={<ApiResourceSettings />} />
|
||||
<Route path=":tab" element={<SignInExperience />} />
|
||||
</Route>
|
||||
<Route path="connectors">
|
||||
<Route index element={<Navigate replace to={ConnectorsTabs.Passwordless} />} />
|
||||
<Route path=":tab" element={<Connectors />} />
|
||||
<Route path=":tab/create/:createType" element={<Connectors />} />
|
||||
<Route path=":tab/:connectorId" element={<ConnectorDetails />} />
|
||||
</Route>
|
||||
<Route path="users">
|
||||
<Route index element={<Users />} />
|
||||
<Route path="create" element={<Users />} />
|
||||
<Route path=":id" element={<UserDetails />}>
|
||||
<Route index element={<Navigate replace to={UserDetailsTabs.Settings} />} />
|
||||
<Route path={UserDetailsTabs.Settings} element={<UserSettings />} />
|
||||
<Route path={UserDetailsTabs.Roles} element={<UserRoles />} />
|
||||
<Route path={UserDetailsTabs.Logs} element={<UserLogs />} />
|
||||
</Route>
|
||||
<Route
|
||||
path={ApiResourceDetailsTabs.Permissions}
|
||||
element={<ApiResourcePermissions />}
|
||||
path={`:id/${UserDetailsTabs.Logs}/:logId`}
|
||||
element={<AuditLogDetails />}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="sign-in-experience">
|
||||
<Route index element={<Navigate replace to={SignInExperiencePage.BrandingTab} />} />
|
||||
<Route path=":tab" element={<SignInExperience />} />
|
||||
</Route>
|
||||
<Route path="connectors">
|
||||
<Route index element={<Navigate replace to={ConnectorsTabs.Passwordless} />} />
|
||||
<Route path=":tab" element={<Connectors />} />
|
||||
<Route path=":tab/create/:createType" element={<Connectors />} />
|
||||
<Route path=":tab/:connectorId" element={<ConnectorDetails />} />
|
||||
</Route>
|
||||
<Route path="users">
|
||||
<Route index element={<Users />} />
|
||||
<Route path="create" element={<Users />} />
|
||||
<Route path=":id" element={<UserDetails />}>
|
||||
<Route index element={<Navigate replace to={UserDetailsTabs.Settings} />} />
|
||||
<Route path={UserDetailsTabs.Settings} element={<UserSettings />} />
|
||||
<Route path={UserDetailsTabs.Roles} element={<UserRoles />} />
|
||||
<Route path={UserDetailsTabs.Logs} element={<UserLogs />} />
|
||||
<Route path="audit-logs">
|
||||
<Route index element={<AuditLogs />} />
|
||||
<Route path=":logId" element={<AuditLogDetails />} />
|
||||
</Route>
|
||||
<Route path={`:id/${UserDetailsTabs.Logs}/:logId`} element={<AuditLogDetails />} />
|
||||
</Route>
|
||||
<Route path="audit-logs">
|
||||
<Route index element={<AuditLogs />} />
|
||||
<Route path=":logId" element={<AuditLogDetails />} />
|
||||
</Route>
|
||||
<Route path="roles">
|
||||
<Route index element={<Roles />} />
|
||||
<Route path="create" element={<Roles />} />
|
||||
<Route path=":id" element={<RoleDetails />}>
|
||||
<Route index element={<Navigate replace to={RoleDetailsTabs.Settings} />} />
|
||||
<Route path={RoleDetailsTabs.Settings} element={<RoleSettings />} />
|
||||
<Route path={RoleDetailsTabs.Permissions} element={<RolePermissions />} />
|
||||
<Route path={RoleDetailsTabs.Users} element={<RoleUsers />} />
|
||||
<Route path="roles">
|
||||
<Route index element={<Roles />} />
|
||||
<Route path="create" element={<Roles />} />
|
||||
<Route path=":id" element={<RoleDetails />}>
|
||||
<Route index element={<Navigate replace to={RoleDetailsTabs.Settings} />} />
|
||||
<Route path={RoleDetailsTabs.Settings} element={<RoleSettings />} />
|
||||
<Route path={RoleDetailsTabs.Permissions} element={<RolePermissions />} />
|
||||
<Route path={RoleDetailsTabs.Users} element={<RoleUsers />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="settings" element={<Settings />} />
|
||||
</Route>
|
||||
<Route path="settings" element={<Settings />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</AppBoundary>
|
||||
|
|
17
packages/console/src/containers/AppContent/index.module.scss
Normal file
17
packages/console/src/containers/AppContent/index.module.scss
Normal file
|
@ -0,0 +1,17 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex-grow: 1;
|
||||
padding: 0 _.unit(2);
|
||||
overflow-y: scroll;
|
||||
|
||||
> * {
|
||||
@include _.main-content-width;
|
||||
}
|
||||
}
|
20
packages/console/src/containers/AppContent/index.tsx
Normal file
20
packages/console/src/containers/AppContent/index.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { Outlet, useOutletContext } from 'react-router-dom';
|
||||
|
||||
import type { AppLayoutOutletContext } from '../AppLayout/types';
|
||||
import Sidebar from './Sidebar';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
const AppContent = () => {
|
||||
const { scrollableContent } = useOutletContext<AppLayoutOutletContext>();
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
<Sidebar />
|
||||
<div ref={scrollableContent} className={styles.main}>
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppContent;
|
|
@ -11,19 +11,3 @@
|
|||
.topbarShadow {
|
||||
box-shadow: var(--shadow-2);
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex-grow: 1;
|
||||
padding: 0 _.unit(2);
|
||||
overflow-y: scroll;
|
||||
|
||||
> * {
|
||||
@include _.main-content-width;
|
||||
}
|
||||
}
|
|
@ -11,12 +11,13 @@ import useConfigs from '@/hooks/use-configs';
|
|||
import useScroll from '@/hooks/use-scroll';
|
||||
import useUserPreferences from '@/hooks/use-user-preferences';
|
||||
|
||||
import Sidebar, { getPath } from './components/Sidebar';
|
||||
import { useSidebarMenuItems } from './components/Sidebar/hook';
|
||||
import { getPath } from '../AppContent/Sidebar';
|
||||
import { useSidebarMenuItems } from '../AppContent/Sidebar/hook';
|
||||
import Topbar from './components/Topbar';
|
||||
import * as styles from './index.module.scss';
|
||||
import { AppLayoutOutletContext } from './types';
|
||||
|
||||
const AppContent = () => {
|
||||
const AppLayout = () => {
|
||||
const { isAuthenticated, isLoading: isLogtoLoading, error, signIn } = useLogto();
|
||||
const href = useHref('/callback');
|
||||
const { isLoading: isPreferencesLoading } = useUserPreferences();
|
||||
|
@ -26,8 +27,8 @@ const AppContent = () => {
|
|||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { firstItem } = useSidebarMenuItems();
|
||||
const mainRef = useRef<HTMLDivElement>(null);
|
||||
const { scrollTop } = useScroll(mainRef.current);
|
||||
const scrollableContent = useRef<HTMLDivElement>(null);
|
||||
const { scrollTop } = useScroll(scrollableContent.current);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -62,14 +63,9 @@ const AppContent = () => {
|
|||
return (
|
||||
<div className={styles.app}>
|
||||
<Topbar className={conditional(scrollTop && styles.topbarShadow)} />
|
||||
<div className={styles.content}>
|
||||
<Sidebar />
|
||||
<div ref={mainRef} className={styles.main}>
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
<Outlet context={{ scrollableContent } satisfies AppLayoutOutletContext} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppContent;
|
||||
export default AppLayout;
|
5
packages/console/src/containers/AppLayout/types.ts
Normal file
5
packages/console/src/containers/AppLayout/types.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import type { RefObject } from 'react';
|
||||
|
||||
export type AppLayoutOutletContext = {
|
||||
scrollableContent: RefObject<HTMLDivElement>;
|
||||
};
|
|
@ -2,7 +2,7 @@ import { conditional } from '@silverhand/essentials';
|
|||
import type { ReactNode } from 'react';
|
||||
import { Component } from 'react';
|
||||
|
||||
import AppError from '../AppError';
|
||||
import AppError from '../../components/AppError';
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
5
packages/console/src/pages/CloudPreview/index.tsx
Normal file
5
packages/console/src/pages/CloudPreview/index.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
const CloudPreview = () => {
|
||||
return <div>CloudPreview(WIP)</div>;
|
||||
};
|
||||
|
||||
export default CloudPreview;
|
Loading…
Add table
Reference in a new issue