0
Fork 0
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:
Xiao Yijun 2023-02-07 17:59:22 +08:00 committed by GitHub
parent 8bf28df796
commit d3e786ec80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 124 additions and 83 deletions

View file

@ -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>

View 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;
}
}

View 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;

View file

@ -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;
}
}

View file

@ -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;

View file

@ -0,0 +1,5 @@
import type { RefObject } from 'react';
export type AppLayoutOutletContext = {
scrollableContent: RefObject<HTMLDivElement>;
};

View file

@ -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;

View file

@ -0,0 +1,5 @@
const CloudPreview = () => {
return <div>CloudPreview(WIP)</div>;
};
export default CloudPreview;