Skip to content

Commit 75ef1f4

Browse files
feat: Add preferences pages (#893)
1 parent 17848b3 commit 75ef1f4

File tree

13 files changed

+155
-95
lines changed

13 files changed

+155
-95
lines changed

site/src/AppRouter.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import React from "react"
2-
import { Route, Routes } from "react-router-dom"
2+
import { Navigate, Route, Routes } from "react-router-dom"
33
import { AuthAndNav, RequireAuth } from "./components"
4+
import { PreferencesLayout } from "./components/Preferences/Layout"
45
import { IndexPage } from "./pages"
56
import { NotFoundPage } from "./pages/404"
67
import { CliAuthenticationPage } from "./pages/cli-auth"
78
import { HealthzPage } from "./pages/healthz"
89
import { SignInPage } from "./pages/login"
9-
import { PreferencesPage } from "./pages/preferences"
10+
import { PreferencesAccountPage } from "./pages/preferences/account"
11+
import { PreferencesLinkedAccountsPage } from "./pages/preferences/linked-accounts"
12+
import { PreferencesSecurityPage } from "./pages/preferences/security"
13+
import { PreferencesSSHKeysPage } from "./pages/preferences/ssh-keys"
1014
import { TemplatesPage } from "./pages/templates"
1115
import { TemplatePage } from "./pages/templates/[organization]/[template]"
1216
import { CreateWorkspacePage } from "./pages/templates/[organization]/[template]/create"
@@ -68,15 +72,12 @@ export const AppRouter: React.FC = () => (
6872
/>
6973
</Route>
7074

71-
<Route path="preferences">
72-
<Route
73-
index
74-
element={
75-
<AuthAndNav>
76-
<PreferencesPage />
77-
</AuthAndNav>
78-
}
79-
/>
75+
<Route path="preferences" element={<PreferencesLayout />}>
76+
<Route index element={<Navigate to="account" />} />
77+
<Route path="account" element={<PreferencesAccountPage />} />
78+
<Route path="security" element={<PreferencesSecurityPage />} />
79+
<Route path="ssh-keys" element={<PreferencesSSHKeysPage />} />
80+
<Route path="linked-accounts" element={<PreferencesLinkedAccountsPage />} />
8081
</Route>
8182

8283
{/* Using path="*"" means "match anything", so this route

site/src/components/Panel/Panel.stories.tsx

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Box from "@material-ui/core/Box"
2+
import React from "react"
3+
import { Outlet } from "react-router-dom"
4+
import { AuthAndNav } from "../Page"
5+
import { TabPanel } from "../TabPanel"
6+
7+
export const Language = {
8+
accountLabel: "Account",
9+
securityLabel: "Security",
10+
sshKeysLabel: "SSH Keys",
11+
linkedAccountsLabel: "Linked Accounts",
12+
preferencesLabel: "Preferences",
13+
}
14+
15+
const menuItems = [
16+
{ label: Language.accountLabel, path: "/preferences/account" },
17+
{ label: Language.securityLabel, path: "/preferences/security" },
18+
{ label: Language.sshKeysLabel, path: "/preferences/ssh-keys" },
19+
{ label: Language.linkedAccountsLabel, path: "/preferences/linked-accounts" },
20+
]
21+
22+
export const PreferencesLayout: React.FC = () => {
23+
return (
24+
<AuthAndNav>
25+
<Box display="flex" flexDirection="column">
26+
<Box style={{ maxWidth: "1380px", margin: "1em auto" }}>
27+
<TabPanel title={Language.preferencesLabel} menuItems={menuItems}>
28+
<Outlet />
29+
</TabPanel>
30+
</Box>
31+
</Box>
32+
</AuthAndNav>
33+
)
34+
}

site/src/components/Sidebar/Sidebar.stories.tsx

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Story } from "@storybook/react"
2+
import React from "react"
3+
import { TabPanel, TabPanelProps } from "."
4+
5+
export default {
6+
title: "TabPanel/TabPanel",
7+
component: TabPanel,
8+
}
9+
10+
const Template: Story<TabPanelProps> = (args: TabPanelProps) => <TabPanel {...args} />
11+
12+
export const Example = Template.bind({})
13+
Example.args = {
14+
title: "Title",
15+
menuItems: [
16+
{ label: "OAuth Settings", path: "oauthSettings" },
17+
{ label: "Security", path: "oauthSettings", hasChanges: true },
18+
{ label: "Hardware", path: "oauthSettings" },
19+
],
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Story } from "@storybook/react"
2+
import React from "react"
3+
import { TabSidebar, TabSidebarProps } from "./TabSidebar"
4+
5+
export default {
6+
title: "TabPanel/TabSidebar",
7+
component: TabSidebar,
8+
}
9+
10+
const Template: Story<TabSidebarProps> = (args: TabSidebarProps) => <TabSidebar {...args} />
11+
12+
export const Example = Template.bind({})
13+
Example.args = {
14+
menuItems: [
15+
{ label: "OAuth Settings", path: "oauthSettings" },
16+
{ label: "Security", path: "security", hasChanges: true },
17+
{ label: "Hardware", path: "hardware" },
18+
],
19+
}

site/src/components/Sidebar/index.tsx renamed to site/src/components/TabPanel/TabSidebar.tsx

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,35 @@ import List from "@material-ui/core/List"
22
import ListItem from "@material-ui/core/ListItem"
33
import { makeStyles } from "@material-ui/core/styles"
44
import React from "react"
5+
import { NavLink } from "react-router-dom"
56
import { combineClasses } from "../../util/combine-classes"
67

7-
export interface SidebarItem {
8-
value: string
8+
export interface TabSidebarItem {
9+
path: string
910
label: string
1011
hasChanges?: boolean
1112
}
1213

13-
export interface SidebarProps {
14-
menuItems: SidebarItem[]
15-
activeItem?: string
16-
onSelect?: (value: string) => void
14+
export interface TabSidebarProps {
15+
menuItems: TabSidebarItem[]
1716
}
1817

19-
export const Sidebar: React.FC<SidebarProps> = ({ menuItems, activeItem, onSelect }) => {
18+
export const TabSidebar: React.FC<TabSidebarProps> = ({ menuItems }) => {
2019
const styles = useStyles()
2120

2221
return (
2322
<List className={styles.menu}>
2423
{menuItems.map(({ hasChanges, ...tab }) => {
25-
const isActive = activeItem === tab.value
2624
return (
27-
<ListItem
28-
key={tab.value}
29-
button
30-
onClick={onSelect ? () => onSelect(tab.value) : undefined}
31-
className={styles.menuItem}
32-
disableRipple
33-
focusRipple={false}
34-
component="li"
35-
>
36-
<span className={combineClasses({ [styles.menuItemSpan]: true, active: isActive })}>
37-
{hasChanges ? `${tab.label}*` : tab.label}
38-
</span>
39-
</ListItem>
25+
<NavLink to={tab.path} key={tab.path} className={styles.link}>
26+
{({ isActive }) => (
27+
<ListItem button className={styles.menuItem} disableRipple focusRipple={false} component="li">
28+
<span className={combineClasses({ [styles.menuItemSpan]: true, active: isActive })}>
29+
{hasChanges ? `${tab.label}*` : tab.label}
30+
</span>
31+
</ListItem>
32+
)}
33+
</NavLink>
4034
)
4135
})}
4236
</List>
@@ -49,6 +43,10 @@ const useStyles = makeStyles((theme) => ({
4943
marginTop: theme.spacing(5),
5044
},
5145

46+
link: {
47+
textDecoration: "none",
48+
},
49+
5250
menuItem: {
5351
letterSpacing: -theme.spacing(0.0375),
5452
padding: 0,

site/src/components/Panel/index.tsx renamed to site/src/components/TabPanel/index.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
import { makeStyles } from "@material-ui/core/styles"
22
import { fade } from "@material-ui/core/styles/colorManipulator"
33
import React from "react"
4-
import { Sidebar, SidebarItem } from "../Sidebar"
4+
import { TabSidebar, TabSidebarItem } from "./TabSidebar"
55

66
export type AdminMenuItemCallback = (menuItem: string) => void
77

8-
export interface PanelProps {
8+
export interface TabPanelProps {
99
title: string
10-
menuItems: SidebarItem[]
11-
activeTab: string
12-
onSelect: AdminMenuItemCallback
10+
menuItems: TabSidebarItem[]
1311
}
1412

15-
export const Panel: React.FC<PanelProps> = ({ children, title, menuItems, activeTab, onSelect }) => {
13+
export const TabPanel: React.FC<TabPanelProps> = ({ children, title, menuItems }) => {
1614
const styles = useStyles()
1715

1816
return (
1917
<div className={styles.root}>
2018
<div className={styles.inner}>
2119
<div className={styles.menuPanel}>
2220
<div className={styles.title}>{title}</div>
23-
<Sidebar menuItems={menuItems} activeItem={activeTab} onSelect={onSelect} />
21+
<TabSidebar menuItems={menuItems} />
2422
</div>
2523

2624
<div className={styles.contentPanel}>{children}</div>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from "react"
2+
import { Section } from "../../components/Section"
3+
4+
const Language = {
5+
title: "Account",
6+
description: "Update your display name, email, profile picture, and dotfiles preferences.",
7+
}
8+
9+
export const PreferencesAccountPage: React.FC = () => {
10+
return <Section title={Language.title} description={Language.description} />
11+
}

site/src/pages/preferences/index.tsx

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)