From af30c58c678005fa4993d03bd050ffc0b809a0b9 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 10 Jan 2023 19:18:20 +0000 Subject: [PATCH 1/3] Refactor user settings page --- site/src/AppRouter.tsx | 35 ++++- .../DeploySettingsLayout.tsx | 2 +- .../DeploySettingsLayout/Sidebar.tsx | 11 +- site/src/components/Section/Section.tsx | 19 +-- .../SettingsLayout/SettingsLayout.tsx | 64 +++++---- .../src/components/SettingsLayout/Sidebar.tsx | 133 ++++++++++++++++++ .../SettingsSecurityForm.tsx | 9 ++ .../AccountPage/AccountPage.tsx | 2 +- .../SSHKeysPage/SSHKeysPage.tsx | 11 +- .../SSHKeysPage/SSHKeysPageView.tsx | 25 +++- .../SecurityPage/SecurityPage.tsx | 2 +- 11 files changed, 244 insertions(+), 69 deletions(-) create mode 100644 site/src/components/SettingsLayout/Sidebar.tsx diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index f53fb1ccde8ae..1158305678745 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -420,10 +420,37 @@ export const AppRouter: FC = () => { /> - }> - } /> - } /> - } /> + + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> diff --git a/site/src/components/DeploySettingsLayout/DeploySettingsLayout.tsx b/site/src/components/DeploySettingsLayout/DeploySettingsLayout.tsx index 33d8db4d57d2d..995b0108a8634 100644 --- a/site/src/components/DeploySettingsLayout/DeploySettingsLayout.tsx +++ b/site/src/components/DeploySettingsLayout/DeploySettingsLayout.tsx @@ -46,7 +46,7 @@ export const DeploySettingsLayout: React.FC = ({ return ( - +
{deploymentConfig ? ( diff --git a/site/src/components/DeploySettingsLayout/Sidebar.tsx b/site/src/components/DeploySettingsLayout/Sidebar.tsx index 9e0b32f8c481c..d6dfc506438f5 100644 --- a/site/src/components/DeploySettingsLayout/Sidebar.tsx +++ b/site/src/components/DeploySettingsLayout/Sidebar.tsx @@ -1,8 +1,8 @@ import { makeStyles } from "@material-ui/core/styles" import Brush from "@material-ui/icons/Brush" import LaunchOutlined from "@material-ui/icons/LaunchOutlined" -import LockRounded from "@material-ui/icons/LockRounded" -import Globe from "@material-ui/icons/Public" +import LockRounded from "@material-ui/icons/LockOutlined" +import Globe from "@material-ui/icons/PublicOutlined" import VpnKeyOutlined from "@material-ui/icons/VpnKeyOutlined" import { GitIcon } from "components/Icons/GitIcon" import { Stack } from "components/Stack/Stack" @@ -92,9 +92,9 @@ const useStyles = makeStyles((theme) => ({ sidebarNavItem: { color: "inherit", display: "block", - fontSize: 16, + fontSize: 14, textDecoration: "none", - padding: theme.spacing(1.5, 1.5, 1.5, 3), + padding: theme.spacing(1.5, 1.5, 1.5, 2), borderRadius: theme.shape.borderRadius / 2, transition: "background-color 0.15s ease-in-out", marginBottom: 1, @@ -117,7 +117,8 @@ const useStyles = makeStyles((theme) => ({ left: 0, top: 0, backgroundColor: theme.palette.secondary.dark, - borderRadius: theme.shape.borderRadius, + borderTopLeftRadius: theme.shape.borderRadius, + borderBottomLeftRadius: theme.shape.borderRadius, }, }, diff --git a/site/src/components/Section/Section.tsx b/site/src/components/Section/Section.tsx index db7eb42e74884..e701dd4d7dc6d 100644 --- a/site/src/components/Section/Section.tsx +++ b/site/src/components/Section/Section.tsx @@ -1,7 +1,6 @@ import { makeStyles } from "@material-ui/core/styles" import Typography from "@material-ui/core/Typography" import { FC } from "react" -import { combineClasses } from "../../util/combineClasses" import { SectionAction } from "../SectionAction/SectionAction" type SectionLayout = "fixed" | "fluid" @@ -31,7 +30,7 @@ export const Section: SectionFC = ({ }) => { const styles = useStyles({ layout }) return ( -
+
{(title || description) && (
@@ -60,18 +59,6 @@ export const Section: SectionFC = ({ Section.Action = SectionAction const useStyles = makeStyles((theme) => ({ - root: { - backgroundColor: theme.palette.background.paper, - boxShadow: theme.shadows[6], - marginBottom: theme.spacing(1), - padding: theme.spacing(6), - borderRadius: theme.shape.borderRadius, - border: `1px solid ${theme.palette.divider}`, - - [theme.breakpoints.down("sm")]: { - padding: theme.spacing(4, 3, 4, 3), - }, - }, inner: ({ layout }: { layout: SectionLayout }) => ({ maxWidth: layout === "fluid" ? "100%" : 500, }), @@ -79,7 +66,7 @@ const useStyles = makeStyles((theme) => ({ marginBottom: theme.spacing(1), }, header: { - marginBottom: theme.spacing(4), + marginBottom: theme.spacing(3), display: "flex", flexDirection: "row", justifyContent: "space-between", @@ -87,6 +74,6 @@ const useStyles = makeStyles((theme) => ({ description: { color: theme.palette.text.secondary, fontSize: 16, - marginTop: theme.spacing(2), + marginTop: theme.spacing(0.5), }, })) diff --git a/site/src/components/SettingsLayout/SettingsLayout.tsx b/site/src/components/SettingsLayout/SettingsLayout.tsx index 77fb87cc803c6..b22be4ecebcf2 100644 --- a/site/src/components/SettingsLayout/SettingsLayout.tsx +++ b/site/src/components/SettingsLayout/SettingsLayout.tsx @@ -1,38 +1,42 @@ -import Box from "@material-ui/core/Box" -import { FC } from "react" +import { makeStyles } from "@material-ui/core/styles" +import { Sidebar } from "./Sidebar" +import { Stack } from "components/Stack/Stack" +import { FC, PropsWithChildren, Suspense } from "react" import { Helmet } from "react-helmet-async" -import { Outlet } from "react-router-dom" import { pageTitle } from "../../util/page" -import { AuthAndFrame } from "../AuthAndFrame/AuthAndFrame" import { Margins } from "../Margins/Margins" -import { TabPanel } from "../TabPanel/TabPanel" +import { useMe } from "hooks/useMe" +import { Loader } from "components/Loader/Loader" -export const Language = { - accountLabel: "Account", - securityLabel: "Security", - sshKeysLabel: "SSH keys", - settingsLabel: "Settings", -} - -const menuItems = [ - { label: Language.accountLabel, path: "/settings/account" }, - { label: Language.securityLabel, path: "/settings/security" }, - { label: Language.sshKeysLabel, path: "/settings/ssh-keys" }, -] +export const SettingsLayout: FC = ({ children }) => { + const styles = useStyles() + const me = useMe() -export const SettingsLayout: FC = () => { return ( - - - - Codestin Search App - - - - - - - - + <> + + Codestin Search App + + + + + + }> +
{children}
+
+
+
+ ) } + +const useStyles = makeStyles((theme) => ({ + wrapper: { + padding: theme.spacing(6, 0), + }, + + content: { + maxWidth: 800, + width: "100%", + }, +})) diff --git a/site/src/components/SettingsLayout/Sidebar.tsx b/site/src/components/SettingsLayout/Sidebar.tsx new file mode 100644 index 0000000000000..b20f24206976a --- /dev/null +++ b/site/src/components/SettingsLayout/Sidebar.tsx @@ -0,0 +1,133 @@ +import { makeStyles } from "@material-ui/core/styles" +import VpnKeyOutlined from "@material-ui/icons/VpnKeyOutlined" +import { User } from "api/typesGenerated" +import { Stack } from "components/Stack/Stack" +import { UserAvatar } from "components/UserAvatar/UserAvatar" +import React, { ElementType, PropsWithChildren, ReactNode } from "react" +import { NavLink } from "react-router-dom" +import { combineClasses } from "util/combineClasses" +import AccountIcon from "@material-ui/icons/Person" +import SecurityIcon from "@material-ui/icons/LockOutlined" + +const SidebarNavItem: React.FC< + PropsWithChildren<{ href: string; icon: ReactNode }> +> = ({ children, href, icon }) => { + const styles = useStyles() + return ( + + combineClasses([ + styles.sidebarNavItem, + isActive ? styles.sidebarNavItemActive : undefined, + ]) + } + > + + {icon} + {children} + + + ) +} + +const SidebarNavItemIcon: React.FC<{ icon: ElementType }> = ({ + icon: Icon, +}) => { + const styles = useStyles() + return +} + +export const Sidebar: React.FC<{ user: User }> = ({ user }) => { + const styles = useStyles() + + return ( + + ) +} + +const useStyles = makeStyles((theme) => ({ + sidebar: { + width: 245, + flexShrink: 0, + }, + sidebarNavItem: { + color: "inherit", + display: "block", + fontSize: 14, + textDecoration: "none", + padding: theme.spacing(1.5, 1.5, 1.5, 2), + borderRadius: theme.shape.borderRadius / 2, + transition: "background-color 0.15s ease-in-out", + marginBottom: 1, + position: "relative", + + "&:hover": { + backgroundColor: theme.palette.action.hover, + }, + }, + sidebarNavItemActive: { + backgroundColor: theme.palette.action.hover, + + "&:before": { + content: '""', + display: "block", + width: 3, + height: "100%", + position: "absolute", + left: 0, + top: 0, + backgroundColor: theme.palette.secondary.dark, + borderTopLeftRadius: theme.shape.borderRadius, + borderBottomLeftRadius: theme.shape.borderRadius, + }, + }, + sidebarNavItemIcon: { + width: theme.spacing(2), + height: theme.spacing(2), + }, + userInfo: { + marginBottom: theme.spacing(2), + }, + userData: { + overflow: "hidden", + }, + username: { + fontWeight: 600, + overflow: "hidden", + textOverflow: "ellipsis", + }, + email: { + color: theme.palette.text.secondary, + fontSize: 12, + overflow: "hidden", + textOverflow: "ellipsis", + }, +})) diff --git a/site/src/components/SettingsSecurityForm/SettingsSecurityForm.tsx b/site/src/components/SettingsSecurityForm/SettingsSecurityForm.tsx index 57121867026c3..29f16c3a84c8a 100644 --- a/site/src/components/SettingsSecurityForm/SettingsSecurityForm.tsx +++ b/site/src/components/SettingsSecurityForm/SettingsSecurityForm.tsx @@ -77,6 +77,9 @@ export const SecurityForm: React.FC = ({ )} = ({ /> = ({ /> { } return ( -
+
- The following public key is used to authenticate Git in workspaces. You - may add it to Git services (such as GitHub) that you need to access from - your workspace.
-
- Coder configures authentication via $GIT_SSH_COMMAND. -

- ), regenerateDialogTitle: "Regenerate SSH key?", regenerateDialogMessage: "You will need to replace the public SSH key on services you use it with, and you'll need to rebuild existing workspaces.", @@ -41,7 +32,7 @@ export const SSHKeysPage: React.FC> = () => { return ( <> -
+
{ + const styles = useStyles() + if (isLoading) { return ( @@ -43,7 +46,6 @@ export const SSHKeysPageView: FC< {/* Regenerating the key is not an option if getSSHKey fails. Only one of the error messages will exist at a single time */} - {Boolean(getSSHKeyError) && ( )} @@ -57,6 +59,12 @@ export const SSHKeysPageView: FC< )} {hasLoaded && sshKey && ( <> +

+ The following public key is used to authenticate Git in workspaces. + You may add it to Git services (such as GitHub) that you need to + access from your workspace. Coder configures authentication via{" "} + $GIT_SSH_COMMAND. +