diff --git a/grai-frontend/src/components/icons/Alerts.tsx b/grai-frontend/src/components/icons/Alerts.tsx
new file mode 100644
index 000000000..f520b06b1
--- /dev/null
+++ b/grai-frontend/src/components/icons/Alerts.tsx
@@ -0,0 +1,28 @@
+import React from "react"
+
+const Alerts: React.FC = () => (
+
+)
+
+export default Alerts
diff --git a/grai-frontend/src/components/icons/ApiKeys.tsx b/grai-frontend/src/components/icons/ApiKeys.tsx
new file mode 100644
index 000000000..7c6207129
--- /dev/null
+++ b/grai-frontend/src/components/icons/ApiKeys.tsx
@@ -0,0 +1,21 @@
+import React from "react"
+
+const ApiKeys: React.FC = () => (
+
+)
+
+export default ApiKeys
diff --git a/grai-frontend/src/components/icons/Installations.tsx b/grai-frontend/src/components/icons/Installations.tsx
new file mode 100644
index 000000000..dc1b46f78
--- /dev/null
+++ b/grai-frontend/src/components/icons/Installations.tsx
@@ -0,0 +1,28 @@
+import React from "react"
+
+const Installations: React.FC = () => (
+
+)
+
+export default Installations
diff --git a/grai-frontend/src/components/icons/PersonalInfo.tsx b/grai-frontend/src/components/icons/PersonalInfo.tsx
new file mode 100644
index 000000000..0f3e53c27
--- /dev/null
+++ b/grai-frontend/src/components/icons/PersonalInfo.tsx
@@ -0,0 +1,28 @@
+import React from "react"
+
+const PersonalInfo: React.FC = () => (
+
+)
+
+export default PersonalInfo
diff --git a/grai-frontend/src/components/icons/TwoFactor.tsx b/grai-frontend/src/components/icons/TwoFactor.tsx
new file mode 100644
index 000000000..75e092cd7
--- /dev/null
+++ b/grai-frontend/src/components/icons/TwoFactor.tsx
@@ -0,0 +1,28 @@
+import React from "react"
+
+const TwoFactor: React.FC = () => (
+
+)
+
+export default TwoFactor
diff --git a/grai-frontend/src/components/icons/Users.tsx b/grai-frontend/src/components/icons/Users.tsx
new file mode 100644
index 000000000..71e00e783
--- /dev/null
+++ b/grai-frontend/src/components/icons/Users.tsx
@@ -0,0 +1,42 @@
+import React from "react"
+
+const Users: React.FC = () => (
+
+)
+
+export default Users
diff --git a/grai-frontend/src/components/icons/Workspace.tsx b/grai-frontend/src/components/icons/Workspace.tsx
new file mode 100644
index 000000000..8cc4b77a1
--- /dev/null
+++ b/grai-frontend/src/components/icons/Workspace.tsx
@@ -0,0 +1,35 @@
+import React from "react"
+
+const Workspace: React.FC = () => (
+
+)
+
+export default Workspace
diff --git a/grai-frontend/src/components/settings/SettingsAppBar.tsx b/grai-frontend/src/components/settings/SettingsAppBar.tsx
index c610a0ddc..13808c822 100644
--- a/grai-frontend/src/components/settings/SettingsAppBar.tsx
+++ b/grai-frontend/src/components/settings/SettingsAppBar.tsx
@@ -1,38 +1,37 @@
import React from "react"
-import { Close } from "@mui/icons-material"
-import { AppBar, IconButton, Toolbar, Typography } from "@mui/material"
-import { useNavigate } from "react-router-dom"
-import useWorkspace from "helpers/useWorkspace"
+import { Box, Typography } from "@mui/material"
-const SettingsAppBar: React.FC = () => {
- const { routePrefix } = useWorkspace()
- const navigate = useNavigate()
-
- const handleClose = () => navigate(routePrefix)
+type SettingsAppBarProps = {
+ title: string
+ buttons?: React.ReactNode
+}
- return (
- = ({ title, buttons }) => (
+
+ theme.zIndex.drawer + 1,
- backgroundColor: "white",
+ color: "rgba(0, 0, 0, 0.80)",
+ fontSize: "24px",
+ fontWeight: 400,
+ lineHeight: "32px",
+ my: "8px",
}}
>
-
-
- Settings
-
-
-
-
-
-
- )
-}
+ {title}
+
+
+ {buttons}
+
+)
export default SettingsAppBar
diff --git a/grai-frontend/src/components/settings/SettingsContent.tsx b/grai-frontend/src/components/settings/SettingsContent.tsx
new file mode 100644
index 000000000..acd1956c5
--- /dev/null
+++ b/grai-frontend/src/components/settings/SettingsContent.tsx
@@ -0,0 +1,13 @@
+import React from "react"
+import { Box, SxProps } from "@mui/material"
+
+type SettingsContentProps = {
+ children: React.ReactNode
+ sx?: SxProps
+}
+
+const SettingsContent: React.FC = ({ children, sx }) => (
+ {children}
+)
+
+export default SettingsContent
diff --git a/grai-frontend/src/components/settings/SettingsDrawer.tsx b/grai-frontend/src/components/settings/SettingsDrawer.tsx
index df2f4d97a..befad6e44 100644
--- a/grai-frontend/src/components/settings/SettingsDrawer.tsx
+++ b/grai-frontend/src/components/settings/SettingsDrawer.tsx
@@ -1,140 +1,88 @@
-import React, { useState } from "react"
-import {
- AccountCircle,
- Business,
- CloudQueue,
- KeyboardArrowLeft,
- Lock,
- Notifications,
- People,
- VpnKey,
-} from "@mui/icons-material"
-import {
- Box,
- Drawer,
- List,
- ListItem,
- ListItemButton,
- ListItemIcon,
- ListItemText,
- Toolbar,
-} from "@mui/material"
-import { Link } from "react-router-dom"
-import useWorkspace from "helpers/useWorkspace"
+import React from "react"
+import { Box, Typography } from "@mui/material"
+import Alerts from "components/icons/Alerts"
+import ApiKeys from "components/icons/ApiKeys"
+import Installations from "components/icons/Installations"
+import PersonalInfo from "components/icons/PersonalInfo"
+import TwoFactor from "components/icons/TwoFactor"
+import Users from "components/icons/Users"
+import Workspace from "components/icons/Workspace"
+import SettingsDrawerSection, { Page } from "./SettingsDrawerSection"
-const drawerWidth = 300
+const drawerWidth = 230
-const SettingsDrawer: React.FC = () => {
- const { routePrefix } = useWorkspace()
- const [open, setOpen] = useState(true)
+const profilePages: Page[] = [
+ {
+ name: "Personal info",
+ icon: ,
+ path: "/settings/profile",
+ },
+ {
+ name: "2 Factor",
+ icon: ,
+ path: "/settings/2fa",
+ },
+ {
+ name: "API Keys",
+ icon: ,
+ path: "/settings/api-keys",
+ },
+]
- const handleClose = () => setOpen(false)
+const workspacePages: Page[] = [
+ {
+ name: "Settings",
+ icon: ,
+ path: "/settings/workspace",
+ },
+ {
+ name: "Users",
+ icon: ,
+ path: "/settings/memberships",
+ },
+ {
+ name: "Alerts",
+ icon: ,
+ path: "/settings/alerts",
+ },
+ {
+ name: "Installations",
+ icon: ,
+ path: "/settings/installations",
+ },
+]
- return (
- (
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
+ Settings
+
+
+
+
+)
export default SettingsDrawer
diff --git a/grai-frontend/src/components/settings/SettingsDrawerSection.tsx b/grai-frontend/src/components/settings/SettingsDrawerSection.tsx
new file mode 100644
index 000000000..f08835492
--- /dev/null
+++ b/grai-frontend/src/components/settings/SettingsDrawerSection.tsx
@@ -0,0 +1,70 @@
+import React from "react"
+import {
+ List,
+ ListItem,
+ ListItemButton,
+ ListItemIcon,
+ ListItemText,
+ ListSubheader,
+ SxProps,
+} from "@mui/material"
+import { Link, useLocation } from "react-router-dom"
+import useWorkspace from "helpers/useWorkspace"
+
+const Subheader = ({ children }: { children: React.ReactNode }) => (
+
+ {children}
+
+)
+
+export interface Page {
+ name: string
+ icon: React.ReactNode
+ path: string
+}
+
+type SettingsDrawerSectionProps = {
+ title: string
+ pages: Page[]
+ sx?: SxProps
+}
+
+const SettingsDrawerSection: React.FC = ({
+ title,
+ pages,
+ sx,
+}) => {
+ const { routePrefix } = useWorkspace()
+ const location = useLocation()
+
+ return (
+
+ {title}
+ {pages.map(({ name, icon, path }) => (
+
+
+ {icon}
+
+
+
+ ))}
+
+ )
+}
+
+export default SettingsDrawerSection
diff --git a/grai-frontend/src/components/settings/SettingsLayout.tsx b/grai-frontend/src/components/settings/SettingsLayout.tsx
index 5cd9f6e01..37becfc39 100644
--- a/grai-frontend/src/components/settings/SettingsLayout.tsx
+++ b/grai-frontend/src/components/settings/SettingsLayout.tsx
@@ -1,7 +1,7 @@
import React, { ReactNode } from "react"
-import { Box, Toolbar } from "@mui/material"
+import { Box } from "@mui/material"
import Loading from "components/layout/Loading"
-import SettingsAppBar from "./SettingsAppBar"
+import PageLayout from "components/layout/PageLayout"
import SettingsDrawer from "./SettingsDrawer"
type SettingsLayoutProps = {
@@ -14,15 +14,17 @@ const SettingsLayout: React.FC = ({
loading,
}) => {
return (
-
-
-
-
-
- {loading && }
- {children}
+
+
+
+
+ {loading && }
+ {children}
+
-
+
)
}
diff --git a/grai-frontend/src/components/settings/alerts/AlertsHeader.tsx b/grai-frontend/src/components/settings/alerts/AlertsHeader.tsx
index 80b1dcd8a..cfabc1afc 100644
--- a/grai-frontend/src/components/settings/alerts/AlertsHeader.tsx
+++ b/grai-frontend/src/components/settings/alerts/AlertsHeader.tsx
@@ -1,7 +1,8 @@
import React, { useState } from "react"
import { Add } from "@mui/icons-material"
-import { Box, Button, Typography } from "@mui/material"
+import { Box, Button } from "@mui/material"
import CreateAlertDialog from "./CreateAlertDialog"
+import SettingsAppBar from "../SettingsAppBar"
type AlertsHeaderProps = {
workspaceId: string
@@ -14,21 +15,23 @@ const AlertsHeader: React.FC = ({ workspaceId }) => {
const handleClose = () => setOpen(false)
return (
-
-
- Alerts
-
-
- } onClick={handleOpen}>
- Add alert
-
-
-
-
+
+
+ } onClick={handleOpen}>
+ Add alert
+
+
+
+ >
+ }
+ />
)
}
export default AlertsHeader
diff --git a/grai-frontend/src/components/settings/apiKeys/ApiKeysHeader.tsx b/grai-frontend/src/components/settings/apiKeys/ApiKeysHeader.tsx
index 548fdf4fc..0dc22178f 100644
--- a/grai-frontend/src/components/settings/apiKeys/ApiKeysHeader.tsx
+++ b/grai-frontend/src/components/settings/apiKeys/ApiKeysHeader.tsx
@@ -2,6 +2,7 @@ import React, { useState } from "react"
import { Add } from "@mui/icons-material"
import { Box, Button, Card, Typography } from "@mui/material"
import CreateKeyDialog from "./CreateKeyDialog"
+import SettingsAppBar from "../SettingsAppBar"
type ApiKeysHeaderProps = {
workspaceId: string
@@ -15,27 +16,35 @@ const ApiKeysHeader: React.FC = ({ workspaceId }) => {
return (
<>
-
-
- API Keys
-
-
- } onClick={handleOpen}>
- Add API Key
-
-
-
+
+
+ }
+ onClick={handleOpen}
+ >
+ Add API Key
+
+
+
+ >
+ }
+ />
+
+
+
+ WorkspaceId
+
+ {workspaceId}
+
-
-
- WorkspaceId
-
- {workspaceId}
-
>
)
}
diff --git a/grai-frontend/src/components/settings/memberships/MembershipsHeader.tsx b/grai-frontend/src/components/settings/memberships/MembershipsHeader.tsx
index 1e3bc6c14..a71779cff 100644
--- a/grai-frontend/src/components/settings/memberships/MembershipsHeader.tsx
+++ b/grai-frontend/src/components/settings/memberships/MembershipsHeader.tsx
@@ -1,7 +1,8 @@
import React, { useState } from "react"
import { Add } from "@mui/icons-material"
-import { Box, Button, Typography } from "@mui/material"
+import { Box, Button } from "@mui/material"
import CreateMembershipDialog from "./CreateMembershipDialog"
+import SettingsAppBar from "../SettingsAppBar"
type MembershipsHeaderProps = {
workspaceId: string
@@ -16,21 +17,23 @@ const MembershipsHeader: React.FC = ({
const handleClose = () => setOpen(false)
return (
-
-
- Memberships
-
-
- } onClick={handleOpen}>
- Invite users
-
-
-
-
+
+
+ } onClick={handleOpen}>
+ Invite users
+
+
+
+ >
+ }
+ />
)
}
export default MembershipsHeader
diff --git a/grai-frontend/src/components/settings/profile/ProfileForm.tsx b/grai-frontend/src/components/settings/profile/ProfileForm.tsx
index c34ec88d3..e4fc85a8f 100644
--- a/grai-frontend/src/components/settings/profile/ProfileForm.tsx
+++ b/grai-frontend/src/components/settings/profile/ProfileForm.tsx
@@ -1,14 +1,7 @@
import React, { useState } from "react"
import { gql, useMutation } from "@apollo/client"
import { LoadingButton } from "@mui/lab"
-import {
- Box,
- Button,
- Grid,
- InputAdornment,
- TextField,
- Typography,
-} from "@mui/material"
+import { Box, Button, InputAdornment, TextField } from "@mui/material"
import { useSnackbar } from "notistack"
import { Link } from "react-router-dom"
import useWorkspace from "helpers/useWorkspace"
@@ -65,72 +58,65 @@ const ProfileForm: React.FC = ({ profile }) => {
.catch(err => {})
return (
-
-
- Profile Settings
-
-
-
-
-
-
+
+
)
}
diff --git a/grai-frontend/src/components/settings/twoFactor/TwoFactorHeader.tsx b/grai-frontend/src/components/settings/twoFactor/TwoFactorHeader.tsx
index ed7a9762c..76dcdd9e3 100644
--- a/grai-frontend/src/components/settings/twoFactor/TwoFactorHeader.tsx
+++ b/grai-frontend/src/components/settings/twoFactor/TwoFactorHeader.tsx
@@ -1,7 +1,8 @@
import React, { useState } from "react"
import { Add } from "@mui/icons-material"
-import { Box, Button, Typography } from "@mui/material"
+import { Box, Button } from "@mui/material"
import CreateDeviceDialog from "./CreateDeviceDialog"
+import SettingsAppBar from "../SettingsAppBar"
const TwoFactorHeader: React.FC = () => {
const [open, setOpen] = useState(false)
@@ -10,17 +11,24 @@ const TwoFactorHeader: React.FC = () => {
const handleClose = () => setOpen(false)
return (
-
-
- 2FA Keys
-
-
- } onClick={handleOpen}>
- Add 2FA Key
-
-
-
-
+
+
+ }
+ onClick={handleOpen}
+ sx={{ height: "48px" }}
+ >
+ Add 2FA Key
+
+
+
+ >
+ }
+ />
)
}
export default TwoFactorHeader
diff --git a/grai-frontend/src/components/settings/workspace/WorkspaceForm.tsx b/grai-frontend/src/components/settings/workspace/WorkspaceForm.tsx
index 50880f410..e973954b0 100644
--- a/grai-frontend/src/components/settings/workspace/WorkspaceForm.tsx
+++ b/grai-frontend/src/components/settings/workspace/WorkspaceForm.tsx
@@ -1,7 +1,7 @@
import React, { useState } from "react"
import { gql, useMutation } from "@apollo/client"
import { LoadingButton } from "@mui/lab"
-import { Box, Grid, TextField, Typography } from "@mui/material"
+import { Box, TextField } from "@mui/material"
import { useSnackbar } from "notistack"
import Form from "components/form/Form"
import GraphError from "components/utils/GraphError"
@@ -52,35 +52,26 @@ const WorkspaceForm: React.FC = ({ workspace }) => {
.catch(err => {})
return (
-
-
- Workspace Settings
-
-
-
-
-
-
+
+
)
}
diff --git a/grai-frontend/src/index.css b/grai-frontend/src/index.css
index 9f8dbfe70..2c78b87ca 100644
--- a/grai-frontend/src/index.css
+++ b/grai-frontend/src/index.css
@@ -1,4 +1,5 @@
@import url("https://fonts.googleapis.com/css?family=Sora:regular,semibold,bold,extrabold,italic&subset=latin,latin-ext");
+@import url("https://fonts.googleapis.com/css?family=Inter:regular,semibold,bold,extrabold,italic&subset=latin,latin-ext");
@import url("shepherd.js/dist/css/shepherd.css");
body {
diff --git a/grai-frontend/src/pages/settings/Alert.test.tsx b/grai-frontend/src/pages/settings/Alert.test.tsx
index 150d6bacd..5ec5a53e3 100644
--- a/grai-frontend/src/pages/settings/Alert.test.tsx
+++ b/grai-frontend/src/pages/settings/Alert.test.tsx
@@ -9,12 +9,14 @@ test("renders", async () => {
})
await waitFor(() => {
- expect(screen.getByText("Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
expect(
- screen.getByRole("heading", { name: /Hello World/i })
+ screen.getByRole("heading", { name: /Hello World/i }),
).toBeInTheDocument()
})
})
@@ -69,7 +71,7 @@ test("no workspace", async () => {
await waitFor(() => {
expect(
- screen.getByText("Sorry something has gone wrong")
+ screen.getByText("Sorry something has gone wrong"),
).toBeInTheDocument()
})
})
diff --git a/grai-frontend/src/pages/settings/Alerts.test.tsx b/grai-frontend/src/pages/settings/Alerts.test.tsx
index 64e28d759..eb56b251b 100644
--- a/grai-frontend/src/pages/settings/Alerts.test.tsx
+++ b/grai-frontend/src/pages/settings/Alerts.test.tsx
@@ -9,7 +9,9 @@ test("renders", async () => {
})
await waitFor(() => {
- expect(screen.getByText("Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
@@ -62,7 +64,7 @@ test("no workspace", async () => {
await waitFor(() => {
expect(
- screen.getByText("Sorry something has gone wrong")
+ screen.getByText("Sorry something has gone wrong"),
).toBeInTheDocument()
})
})
diff --git a/grai-frontend/src/pages/settings/Alerts.tsx b/grai-frontend/src/pages/settings/Alerts.tsx
index 21c82c37a..59c75bd50 100644
--- a/grai-frontend/src/pages/settings/Alerts.tsx
+++ b/grai-frontend/src/pages/settings/Alerts.tsx
@@ -1,10 +1,10 @@
import React from "react"
import { gql, useQuery } from "@apollo/client"
-import { Box } from "@mui/material"
import NotFound from "pages/NotFound"
import useWorkspace from "helpers/useWorkspace"
import AlertsHeader from "components/settings/alerts/AlertsHeader"
import AlertsTable from "components/settings/alerts/AlertsTable"
+import SettingsContent from "components/settings/SettingsContent"
import SettingsLayout from "components/settings/SettingsLayout"
import GraphError from "components/utils/GraphError"
import { GetAlerts, GetAlertsVariables } from "./__generated__/GetAlerts"
@@ -38,7 +38,7 @@ const Alerts: React.FC = () => {
organisationName,
workspaceName,
},
- }
+ },
)
if (error) return
@@ -49,14 +49,14 @@ const Alerts: React.FC = () => {
return (
-
-
+
+
-
+
)
}
diff --git a/grai-frontend/src/pages/settings/ApiKeys.test.tsx b/grai-frontend/src/pages/settings/ApiKeys.test.tsx
index 739108946..0412bc348 100644
--- a/grai-frontend/src/pages/settings/ApiKeys.test.tsx
+++ b/grai-frontend/src/pages/settings/ApiKeys.test.tsx
@@ -9,12 +9,14 @@ test("renders", async () => {
})
await waitFor(() => {
- expect(screen.getByText("Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
expect(
- screen.getByRole("heading", { name: /Api Keys/i })
+ screen.getByRole("heading", { name: /Api Keys/i }),
).toBeInTheDocument()
})
})
@@ -64,7 +66,7 @@ test("no workspace", async () => {
await waitFor(() => {
expect(
- screen.getByText("Sorry something has gone wrong")
+ screen.getByText("Sorry something has gone wrong"),
).toBeInTheDocument()
})
})
diff --git a/grai-frontend/src/pages/settings/ApiKeys.tsx b/grai-frontend/src/pages/settings/ApiKeys.tsx
index f63745bf4..d4cd658fe 100644
--- a/grai-frontend/src/pages/settings/ApiKeys.tsx
+++ b/grai-frontend/src/pages/settings/ApiKeys.tsx
@@ -1,10 +1,10 @@
import React from "react"
import { gql, useQuery } from "@apollo/client"
-import { Box } from "@mui/material"
import NotFound from "pages/NotFound"
import useWorkspace from "helpers/useWorkspace"
import ApiKeysHeader from "components/settings/apiKeys/ApiKeysHeader"
import ApiKeysTable from "components/settings/apiKeys/ApiKeysTable"
+import SettingsContent from "components/settings/SettingsContent"
import SettingsLayout from "components/settings/SettingsLayout"
import GraphError from "components/utils/GraphError"
import { GetApiKeys, GetApiKeysVariables } from "./__generated__/GetApiKeys"
@@ -43,7 +43,7 @@ const ApiKeys: React.FC = () => {
organisationName,
workspaceName,
},
- }
+ },
)
if (error) return
@@ -54,14 +54,14 @@ const ApiKeys: React.FC = () => {
return (
-
-
+
+
-
+
)
}
diff --git a/grai-frontend/src/pages/settings/Installations.test.tsx b/grai-frontend/src/pages/settings/Installations.test.tsx
index 503b6cca3..86a26bc8b 100644
--- a/grai-frontend/src/pages/settings/Installations.test.tsx
+++ b/grai-frontend/src/pages/settings/Installations.test.tsx
@@ -10,12 +10,14 @@ test("renders", async () => {
})
await waitFor(() => {
- expect(screen.getByText("Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
expect(
- screen.getByRole("heading", { name: /Installations/i })
+ screen.getByRole("heading", { name: /Installations/i }),
).toBeInTheDocument()
})
@@ -69,7 +71,7 @@ test("no workspace", async () => {
await waitFor(() => {
expect(
- screen.getByText("Sorry something has gone wrong")
+ screen.getByText("Sorry something has gone wrong"),
).toBeInTheDocument()
})
})
diff --git a/grai-frontend/src/pages/settings/Installations.tsx b/grai-frontend/src/pages/settings/Installations.tsx
index 3bbe38d40..ed20f0a8d 100644
--- a/grai-frontend/src/pages/settings/Installations.tsx
+++ b/grai-frontend/src/pages/settings/Installations.tsx
@@ -1,14 +1,13 @@
import React from "react"
-import { Box, Typography } from "@mui/material"
+import { Box } from "@mui/material"
import GitHubInstallation from "components/settings/installations/GitHubInstallation"
+import SettingsAppBar from "components/settings/SettingsAppBar"
import SettingsLayout from "components/settings/SettingsLayout"
const Installations: React.FC = () => (
-
-
- Installations
-
+
+
diff --git a/grai-frontend/src/pages/settings/Memberships.tsx b/grai-frontend/src/pages/settings/Memberships.tsx
index 462f0a734..c10e93540 100644
--- a/grai-frontend/src/pages/settings/Memberships.tsx
+++ b/grai-frontend/src/pages/settings/Memberships.tsx
@@ -1,10 +1,10 @@
import React from "react"
import { gql, useQuery } from "@apollo/client"
-import { Box } from "@mui/material"
import NotFound from "pages/NotFound"
import useWorkspace from "helpers/useWorkspace"
import MembershipsHeader from "components/settings/memberships/MembershipsHeader"
import MembershipsTable from "components/settings/memberships/MembershipsTable"
+import SettingsContent from "components/settings/SettingsContent"
import SettingsLayout from "components/settings/SettingsLayout"
import GraphError from "components/utils/GraphError"
import {
@@ -58,15 +58,15 @@ const Memberships: React.FC = () => {
return (
-
-
+
+
-
+
)
}
diff --git a/grai-frontend/src/pages/settings/ProfileSettings.test.tsx b/grai-frontend/src/pages/settings/ProfileSettings.test.tsx
index 2431f6fbf..3c8f39258 100644
--- a/grai-frontend/src/pages/settings/ProfileSettings.test.tsx
+++ b/grai-frontend/src/pages/settings/ProfileSettings.test.tsx
@@ -9,7 +9,7 @@ test("renders", async () => {
})
await waitFor(() => {
- expect(screen.getByText("Profile Settings")).toBeInTheDocument()
+ expect(screen.getByText("Personal info")).toBeInTheDocument()
})
})
diff --git a/grai-frontend/src/pages/settings/ProfileSettings.tsx b/grai-frontend/src/pages/settings/ProfileSettings.tsx
index 74c9dbec6..4f1f5da6a 100644
--- a/grai-frontend/src/pages/settings/ProfileSettings.tsx
+++ b/grai-frontend/src/pages/settings/ProfileSettings.tsx
@@ -2,6 +2,7 @@ import React from "react"
import { gql, useQuery } from "@apollo/client"
import NotFound from "pages/NotFound"
import ProfileForm from "components/settings/profile/ProfileForm"
+import SettingsAppBar from "components/settings/SettingsAppBar"
import SettingsLayout from "components/settings/SettingsLayout"
import GraphError from "components/utils/GraphError"
import { GetProfile } from "./__generated__/GetProfile"
@@ -29,6 +30,7 @@ const ProfileSettings: React.FC = () => {
return (
+
)
diff --git a/grai-frontend/src/pages/settings/TwoFactor.test.tsx b/grai-frontend/src/pages/settings/TwoFactor.test.tsx
index 5e3516634..b93b49ed8 100644
--- a/grai-frontend/src/pages/settings/TwoFactor.test.tsx
+++ b/grai-frontend/src/pages/settings/TwoFactor.test.tsx
@@ -9,7 +9,9 @@ test("renders", async () => {
})
await waitFor(() => {
- expect(screen.getByText("Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
diff --git a/grai-frontend/src/pages/settings/TwoFactor.tsx b/grai-frontend/src/pages/settings/TwoFactor.tsx
index 269c64df7..21e862309 100644
--- a/grai-frontend/src/pages/settings/TwoFactor.tsx
+++ b/grai-frontend/src/pages/settings/TwoFactor.tsx
@@ -1,7 +1,7 @@
import React from "react"
import { gql, useQuery } from "@apollo/client"
-import { Box } from "@mui/material"
import NotFound from "pages/NotFound"
+import SettingsContent from "components/settings/SettingsContent"
import SettingsLayout from "components/settings/SettingsLayout"
import TwoFactorHeader from "components/settings/twoFactor/TwoFactorHeader"
import TwoFactorTable from "components/settings/twoFactor/TwoFactorTable"
@@ -37,10 +37,10 @@ const ProfileSettings: React.FC = () => {
return (
-
-
+
+
-
+
)
}
diff --git a/grai-frontend/src/pages/settings/WorkspaceSettings.test.tsx b/grai-frontend/src/pages/settings/WorkspaceSettings.test.tsx
index d30ebeb23..95848120f 100644
--- a/grai-frontend/src/pages/settings/WorkspaceSettings.test.tsx
+++ b/grai-frontend/src/pages/settings/WorkspaceSettings.test.tsx
@@ -11,7 +11,9 @@ test("renders", async () => {
})
await waitFor(() => {
- expect(screen.getByText("Workspace Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
@@ -38,7 +40,9 @@ test("error", async () => {
render(, { mocks, withRouter: true })
await waitFor(() => {
- expect(screen.getByText("Workspace Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
@@ -67,7 +71,9 @@ test("not found", async () => {
render(, { mocks, withRouter: true })
await waitFor(() => {
- expect(screen.getByText("Workspace Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
@@ -83,7 +89,9 @@ test("submit", async () => {
})
await waitFor(() => {
- expect(screen.getAllByText("Workspace Settings")).toBeTruthy()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
@@ -94,12 +102,12 @@ test("submit", async () => {
async () =>
await user.type(
screen.getByRole("textbox", { name: /name/i }),
- "Workspace 1"
- )
+ "Workspace 1",
+ ),
)
await act(
- async () => await user.click(screen.getByRole("button", { name: /save/i }))
+ async () => await user.click(screen.getByRole("button", { name: /save/i })),
)
// eslint-disable-next-line testing-library/no-wait-for-empty-callback
@@ -144,7 +152,9 @@ test("submit error", async () => {
render(, { mocks, withRouter: true })
await waitFor(() => {
- expect(screen.getByText("Workspace Settings")).toBeInTheDocument()
+ expect(
+ screen.getByRole("heading", { name: "Settings" }),
+ ).toBeInTheDocument()
})
await waitFor(() => {
@@ -152,7 +162,7 @@ test("submit error", async () => {
})
await act(
- async () => await user.click(screen.getByRole("button", { name: /save/i }))
+ async () => await user.click(screen.getByRole("button", { name: /save/i })),
)
await waitFor(() => {
diff --git a/grai-frontend/src/pages/settings/WorkspaceSettings.tsx b/grai-frontend/src/pages/settings/WorkspaceSettings.tsx
index 76bb0e81a..7eeffa735 100644
--- a/grai-frontend/src/pages/settings/WorkspaceSettings.tsx
+++ b/grai-frontend/src/pages/settings/WorkspaceSettings.tsx
@@ -2,6 +2,7 @@ import React from "react"
import { gql, useQuery } from "@apollo/client"
import NotFound from "pages/NotFound"
import useWorkspace from "helpers/useWorkspace"
+import SettingsAppBar from "components/settings/SettingsAppBar"
import SettingsLayout from "components/settings/SettingsLayout"
import WorkspaceDanger from "components/settings/workspace/WorkspaceDanger"
import WorkspaceForm from "components/settings/workspace/WorkspaceForm"
@@ -45,6 +46,7 @@ const WorkspaceSettings: React.FC = () => {
return (
+