mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
refactor: Clean up routes (#5702)
* refactor: Clean up routes * Fix tests
This commit is contained in:
+35
-147
@@ -153,22 +153,14 @@ export const AppRouter: FC = () => {
|
||||
<Route index element={<TemplatesPage />} />
|
||||
<Route path="new" element={<CreateTemplatePage />} />
|
||||
<Route path=":template">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<TemplateLayout>
|
||||
<TemplateSummaryPage />
|
||||
</TemplateLayout>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="permissions"
|
||||
element={
|
||||
<TemplateLayout>
|
||||
<TemplatePermissionsPage />
|
||||
</TemplateLayout>
|
||||
}
|
||||
/>
|
||||
<Route element={<TemplateLayout />}>
|
||||
<Route index element={<TemplateSummaryPage />} />
|
||||
<Route
|
||||
path="permissions"
|
||||
element={<TemplatePermissionsPage />}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="workspace" element={<CreateWorkspacePage />} />
|
||||
<Route path="settings" element={<TemplateSettingsPage />} />
|
||||
<Route path="versions">
|
||||
@@ -178,26 +170,18 @@ export const AppRouter: FC = () => {
|
||||
</Route>
|
||||
|
||||
<Route path="users">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<UsersLayout>
|
||||
<UsersPage />
|
||||
</UsersLayout>
|
||||
}
|
||||
/>
|
||||
<Route element={<UsersLayout />}>
|
||||
<Route index element={<UsersPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path="create" element={<CreateUserPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path="/groups">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<UsersLayout>
|
||||
<GroupsPage />
|
||||
</UsersLayout>
|
||||
}
|
||||
/>
|
||||
<Route element={<UsersLayout />}>
|
||||
<Route index element={<GroupsPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path="create" element={<CreateGroupPage />} />
|
||||
<Route path=":groupId" element={<GroupPage />} />
|
||||
<Route path=":groupId/settings" element={<SettingsGroupPage />} />
|
||||
@@ -219,118 +203,22 @@ export const AppRouter: FC = () => {
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/settings/deployment">
|
||||
<Route
|
||||
path="general"
|
||||
element={
|
||||
<RequirePermission
|
||||
isFeatureVisible={Boolean(
|
||||
permissions?.viewDeploymentConfig,
|
||||
)}
|
||||
>
|
||||
<DeploySettingsLayout>
|
||||
<GeneralSettingsPage />
|
||||
</DeploySettingsLayout>
|
||||
</RequirePermission>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="security"
|
||||
element={
|
||||
<RequirePermission
|
||||
isFeatureVisible={Boolean(
|
||||
permissions?.viewDeploymentConfig,
|
||||
)}
|
||||
>
|
||||
<DeploySettingsLayout>
|
||||
<SecuritySettingsPage />
|
||||
</DeploySettingsLayout>
|
||||
</RequirePermission>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="appearance"
|
||||
element={
|
||||
<RequirePermission
|
||||
isFeatureVisible={Boolean(
|
||||
permissions?.viewDeploymentConfig,
|
||||
)}
|
||||
>
|
||||
<DeploySettingsLayout>
|
||||
<AppearanceSettingsPage />
|
||||
</DeploySettingsLayout>
|
||||
</RequirePermission>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="network"
|
||||
element={
|
||||
<RequirePermission
|
||||
isFeatureVisible={Boolean(
|
||||
permissions?.viewDeploymentConfig,
|
||||
)}
|
||||
>
|
||||
<DeploySettingsLayout>
|
||||
<NetworkSettingsPage />
|
||||
</DeploySettingsLayout>
|
||||
</RequirePermission>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="userauth"
|
||||
element={
|
||||
<RequirePermission
|
||||
isFeatureVisible={Boolean(
|
||||
permissions?.viewDeploymentConfig,
|
||||
)}
|
||||
>
|
||||
<DeploySettingsLayout>
|
||||
<UserAuthSettingsPage />
|
||||
</DeploySettingsLayout>
|
||||
</RequirePermission>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="gitauth"
|
||||
element={
|
||||
<RequirePermission
|
||||
isFeatureVisible={Boolean(
|
||||
permissions?.viewDeploymentConfig,
|
||||
)}
|
||||
>
|
||||
<DeploySettingsLayout>
|
||||
<GitAuthSettingsPage />
|
||||
</DeploySettingsLayout>
|
||||
</RequirePermission>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/settings/deployment"
|
||||
element={<DeploySettingsLayout />}
|
||||
>
|
||||
<Route path="general" element={<GeneralSettingsPage />} />
|
||||
<Route path="security" element={<SecuritySettingsPage />} />
|
||||
<Route path="appearance" element={<AppearanceSettingsPage />} />
|
||||
<Route path="network" element={<NetworkSettingsPage />} />
|
||||
<Route path="userauth" element={<UserAuthSettingsPage />} />
|
||||
<Route path="gitauth" element={<GitAuthSettingsPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path="settings">
|
||||
<Route
|
||||
path="account"
|
||||
element={
|
||||
<SettingsLayout>
|
||||
<AccountPage />
|
||||
</SettingsLayout>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="security"
|
||||
element={
|
||||
<SettingsLayout>
|
||||
<SecurityPage />
|
||||
</SettingsLayout>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="ssh-keys"
|
||||
element={
|
||||
<SettingsLayout>
|
||||
<SSHKeysPage />
|
||||
</SettingsLayout>
|
||||
}
|
||||
/>
|
||||
<Route path="settings" element={<SettingsLayout />}>
|
||||
<Route path="account" element={<AccountPage />} />
|
||||
<Route path="security" element={<SecurityPage />} />
|
||||
<Route path="ssh-keys" element={<SSHKeysPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path="/@:username">
|
||||
@@ -349,11 +237,11 @@ export const AppRouter: FC = () => {
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
<Route path="/@:username">
|
||||
<Route path=":workspace">
|
||||
<Route path="terminal" element={<TerminalPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
{/* Terminal page don't have the dashboard layout */}
|
||||
<Route
|
||||
path="/@:username/:workspace/terminal"
|
||||
element={<TerminalPage />}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
{/* Using path="*"" means "match anything", so this route
|
||||
|
||||
@@ -2,17 +2,14 @@ import { makeStyles } from "@material-ui/core/styles"
|
||||
import { Margins } from "components/Margins/Margins"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
import { Sidebar } from "./Sidebar"
|
||||
import {
|
||||
createContext,
|
||||
PropsWithChildren,
|
||||
Suspense,
|
||||
useContext,
|
||||
FC,
|
||||
} from "react"
|
||||
import { createContext, Suspense, useContext, FC } from "react"
|
||||
import { useMachine } from "@xstate/react"
|
||||
import { Loader } from "components/Loader/Loader"
|
||||
import { DeploymentConfig } from "api/typesGenerated"
|
||||
import { deploymentConfigMachine } from "xServices/deploymentConfig/deploymentConfigMachine"
|
||||
import { RequirePermission } from "components/RequirePermission/RequirePermission"
|
||||
import { usePermissions } from "hooks/usePermissions"
|
||||
import { Outlet } from "react-router-dom"
|
||||
|
||||
type DeploySettingsContextValue = { deploymentConfig: DeploymentConfig }
|
||||
|
||||
@@ -30,28 +27,33 @@ export const useDeploySettings = (): DeploySettingsContextValue => {
|
||||
return context
|
||||
}
|
||||
|
||||
export const DeploySettingsLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
export const DeploySettingsLayout: FC = () => {
|
||||
const [state] = useMachine(deploymentConfigMachine)
|
||||
const styles = useStyles()
|
||||
const { deploymentConfig } = state.context
|
||||
const permissions = usePermissions()
|
||||
|
||||
return (
|
||||
<Margins>
|
||||
<Stack className={styles.wrapper} direction="row" spacing={6}>
|
||||
<Sidebar />
|
||||
<main className={styles.content}>
|
||||
{deploymentConfig ? (
|
||||
<DeploySettingsContext.Provider
|
||||
value={{ deploymentConfig: deploymentConfig }}
|
||||
>
|
||||
<Suspense fallback={<Loader />}>{children}</Suspense>
|
||||
</DeploySettingsContext.Provider>
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
</main>
|
||||
</Stack>
|
||||
</Margins>
|
||||
<RequirePermission isFeatureVisible={permissions.viewDeploymentConfig}>
|
||||
<Margins>
|
||||
<Stack className={styles.wrapper} direction="row" spacing={6}>
|
||||
<Sidebar />
|
||||
<main className={styles.content}>
|
||||
{deploymentConfig ? (
|
||||
<DeploySettingsContext.Provider
|
||||
value={{ deploymentConfig: deploymentConfig }}
|
||||
>
|
||||
<Suspense fallback={<Loader />}>
|
||||
<Outlet />
|
||||
</Suspense>
|
||||
</DeploySettingsContext.Provider>
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
</main>
|
||||
</Stack>
|
||||
</Margins>
|
||||
</RequirePermission>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,37 +43,34 @@ export const Sidebar: React.FC = () => {
|
||||
return (
|
||||
<nav className={styles.sidebar}>
|
||||
<SidebarNavItem
|
||||
href="../general"
|
||||
href="general"
|
||||
icon={<SidebarNavItemIcon icon={LaunchOutlined} />}
|
||||
>
|
||||
General
|
||||
</SidebarNavItem>
|
||||
<SidebarNavItem
|
||||
href="../appearance"
|
||||
href="appearance"
|
||||
icon={<SidebarNavItemIcon icon={Brush} />}
|
||||
>
|
||||
Appearance
|
||||
</SidebarNavItem>
|
||||
<SidebarNavItem
|
||||
href="../userauth"
|
||||
href="userauth"
|
||||
icon={<SidebarNavItemIcon icon={VpnKeyOutlined} />}
|
||||
>
|
||||
User Authentication
|
||||
</SidebarNavItem>
|
||||
<SidebarNavItem
|
||||
href="../gitauth"
|
||||
href="gitauth"
|
||||
icon={<SidebarNavItemIcon icon={GitIcon} />}
|
||||
>
|
||||
Git Authentication
|
||||
</SidebarNavItem>
|
||||
<SidebarNavItem
|
||||
href="../network"
|
||||
icon={<SidebarNavItemIcon icon={Globe} />}
|
||||
>
|
||||
<SidebarNavItem href="network" icon={<SidebarNavItemIcon icon={Globe} />}>
|
||||
Network
|
||||
</SidebarNavItem>
|
||||
<SidebarNavItem
|
||||
href="../security"
|
||||
href="security"
|
||||
icon={<SidebarNavItemIcon icon={LockRounded} />}
|
||||
>
|
||||
Security
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { Sidebar } from "./Sidebar"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
import { FC, PropsWithChildren, Suspense } from "react"
|
||||
import { FC, Suspense } from "react"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import { pageTitle } from "../../util/page"
|
||||
import { Margins } from "../Margins/Margins"
|
||||
import { useMe } from "hooks/useMe"
|
||||
import { Loader } from "components/Loader/Loader"
|
||||
import { Outlet } from "react-router-dom"
|
||||
|
||||
export const SettingsLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
export const SettingsLayout: FC = () => {
|
||||
const styles = useStyles()
|
||||
const me = useMe()
|
||||
|
||||
@@ -22,7 +23,9 @@ export const SettingsLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
<Stack className={styles.wrapper} direction="row" spacing={6}>
|
||||
<Sidebar user={me} />
|
||||
<Suspense fallback={<Loader />}>
|
||||
<main className={styles.content}>{children}</main>
|
||||
<main className={styles.content}>
|
||||
<Outlet />
|
||||
</main>
|
||||
</Suspense>
|
||||
</Stack>
|
||||
</Margins>
|
||||
|
||||
@@ -52,19 +52,19 @@ export const Sidebar: React.FC<{ user: User }> = ({ user }) => {
|
||||
</Stack>
|
||||
|
||||
<SidebarNavItem
|
||||
href="../account"
|
||||
href="account"
|
||||
icon={<SidebarNavItemIcon icon={AccountIcon} />}
|
||||
>
|
||||
Account
|
||||
</SidebarNavItem>
|
||||
<SidebarNavItem
|
||||
href="../security"
|
||||
href="security"
|
||||
icon={<SidebarNavItemIcon icon={SecurityIcon} />}
|
||||
>
|
||||
Security
|
||||
</SidebarNavItem>
|
||||
<SidebarNavItem
|
||||
href="../ssh-keys"
|
||||
href="ssh-keys"
|
||||
icon={<SidebarNavItemIcon icon={VpnKeyOutlined} />}
|
||||
>
|
||||
SSH Keys
|
||||
|
||||
@@ -11,14 +11,13 @@ import {
|
||||
PageHeaderTitle,
|
||||
} from "components/PageHeader/PageHeader"
|
||||
import { useOrganizationId } from "hooks/useOrganizationId"
|
||||
import { createContext, FC, Suspense, useContext } from "react"
|
||||
import {
|
||||
createContext,
|
||||
FC,
|
||||
PropsWithChildren,
|
||||
Suspense,
|
||||
useContext,
|
||||
} from "react"
|
||||
import { Link as RouterLink, NavLink, useParams } from "react-router-dom"
|
||||
Link as RouterLink,
|
||||
NavLink,
|
||||
Outlet,
|
||||
useParams,
|
||||
} from "react-router-dom"
|
||||
import { combineClasses } from "util/combineClasses"
|
||||
import { firstLetter } from "util/firstLetter"
|
||||
import { selectPermissions } from "xServices/auth/authSelectors"
|
||||
@@ -96,7 +95,9 @@ const CreateWorkspaceButton: FC<{
|
||||
</Link>
|
||||
)
|
||||
|
||||
export const TemplateLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
export const TemplateLayout: FC<{ children?: JSX.Element }> = ({
|
||||
children = <Outlet />,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const organizationId = useOrganizationId()
|
||||
const templateName = useTemplateName()
|
||||
|
||||
@@ -6,13 +6,18 @@ import PersonAdd from "@material-ui/icons/PersonAddOutlined"
|
||||
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"
|
||||
import { useFeatureVisibility } from "hooks/useFeatureVisibility"
|
||||
import { usePermissions } from "hooks/usePermissions"
|
||||
import { FC, PropsWithChildren } from "react"
|
||||
import { Link as RouterLink, NavLink, useNavigate } from "react-router-dom"
|
||||
import { FC } from "react"
|
||||
import {
|
||||
Link as RouterLink,
|
||||
NavLink,
|
||||
Outlet,
|
||||
useNavigate,
|
||||
} from "react-router-dom"
|
||||
import { combineClasses } from "util/combineClasses"
|
||||
import { Margins } from "../../components/Margins/Margins"
|
||||
import { Stack } from "../../components/Stack/Stack"
|
||||
|
||||
export const UsersLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
export const UsersLayout: FC = () => {
|
||||
const styles = useStyles()
|
||||
const { createUser: canCreateUser, createGroup: canCreateGroup } =
|
||||
usePermissions()
|
||||
@@ -81,7 +86,9 @@ export const UsersLayout: FC<PropsWithChildren> = ({ children }) => {
|
||||
</Margins>
|
||||
</div>
|
||||
|
||||
<Margins>{children}</Margins>
|
||||
<Margins>
|
||||
<Outlet />
|
||||
</Margins>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user