From 340ef69e2a23270d9fe31c51e7004865e102c061 Mon Sep 17 00:00:00 2001 From: Edward Louth Date: Fri, 29 Sep 2023 11:41:43 +0100 Subject: [PATCH] Settings page redesign (#669) * Start on settings page redesign * add icons and fix tests * Final fixes * Fix code style issues with ESLint * lint fix --------- Co-authored-by: Lint Action --- grai-frontend/src/components/icons/Alerts.tsx | 28 +++ .../src/components/icons/ApiKeys.tsx | 21 ++ .../src/components/icons/Installations.tsx | 28 +++ .../src/components/icons/PersonalInfo.tsx | 28 +++ .../src/components/icons/TwoFactor.tsx | 28 +++ grai-frontend/src/components/icons/Users.tsx | 42 ++++ .../src/components/icons/Workspace.tsx | 35 +++ .../components/settings/SettingsAppBar.tsx | 59 +++-- .../components/settings/SettingsContent.tsx | 13 ++ .../components/settings/SettingsDrawer.tsx | 210 +++++++----------- .../settings/SettingsDrawerSection.tsx | 70 ++++++ .../components/settings/SettingsLayout.tsx | 22 +- .../settings/alerts/AlertsHeader.tsx | 35 +-- .../settings/apiKeys/ApiKeysHeader.tsx | 49 ++-- .../memberships/MembershipsHeader.tsx | 35 +-- .../settings/profile/ProfileForm.tsx | 134 +++++------ .../settings/twoFactor/TwoFactorHeader.tsx | 32 ++- .../settings/workspace/WorkspaceForm.tsx | 51 ++--- grai-frontend/src/index.css | 1 + .../src/pages/settings/Alert.test.tsx | 8 +- .../src/pages/settings/Alerts.test.tsx | 6 +- grai-frontend/src/pages/settings/Alerts.tsx | 10 +- .../src/pages/settings/ApiKeys.test.tsx | 8 +- grai-frontend/src/pages/settings/ApiKeys.tsx | 10 +- .../src/pages/settings/Installations.test.tsx | 8 +- .../src/pages/settings/Installations.tsx | 9 +- .../src/pages/settings/Memberships.tsx | 8 +- .../pages/settings/ProfileSettings.test.tsx | 2 +- .../src/pages/settings/ProfileSettings.tsx | 2 + .../src/pages/settings/TwoFactor.test.tsx | 4 +- .../src/pages/settings/TwoFactor.tsx | 8 +- .../pages/settings/WorkspaceSettings.test.tsx | 28 ++- .../src/pages/settings/WorkspaceSettings.tsx | 2 + 33 files changed, 650 insertions(+), 384 deletions(-) create mode 100644 grai-frontend/src/components/icons/Alerts.tsx create mode 100644 grai-frontend/src/components/icons/ApiKeys.tsx create mode 100644 grai-frontend/src/components/icons/Installations.tsx create mode 100644 grai-frontend/src/components/icons/PersonalInfo.tsx create mode 100644 grai-frontend/src/components/icons/TwoFactor.tsx create mode 100644 grai-frontend/src/components/icons/Users.tsx create mode 100644 grai-frontend/src/components/icons/Workspace.tsx create mode 100644 grai-frontend/src/components/settings/SettingsContent.tsx create mode 100644 grai-frontend/src/components/settings/SettingsDrawerSection.tsx 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 - - - - - - + + + + + + + } + /> ) } 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 - - - - - + + + + + + + } + /> + + + + 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 - - - - - - + + + + + + + } + /> ) } 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 - - - -
- {error && } - - - setValues({ ...values, first_name: event.target.value }) - } - margin="normal" - fullWidth - required - /> - - setValues({ ...values, last_name: event.target.value }) - } - margin="normal" - fullWidth - required - /> - - - - ), - }} - /> - - Save - - -
-
+ +
+ {error && } + + + setValues({ ...values, first_name: event.target.value }) + } + margin="normal" + fullWidth + required + /> + + setValues({ ...values, last_name: event.target.value }) + } + margin="normal" + fullWidth + required + /> + + + + ), + }} + /> + + Save + +
) } 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 - - - - - - + + + + + + + } + /> ) } 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 - - - -
- {error && } - - setValues({ ...values, name: event.target.value }) - } - margin="normal" - fullWidth - required - /> - - Save - - -
-
+ +
+ {error && } + setValues({ ...values, name: event.target.value })} + margin="normal" + fullWidth + required + /> + + Save + +
) } 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 ( +