From 471a9708e72d1c9a86a35124fdcf76a3a652fca2 Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 27 May 2022 16:10:03 +0000 Subject: [PATCH 1/4] refactor: Update users page to looks like others --- .../AvatarData/AvatarData.stories.tsx | 23 ++++ site/src/components/AvatarData/AvatarData.tsx | 67 ++++++++++ site/src/components/Header/Header.test.tsx | 28 ----- site/src/components/Header/Header.tsx | 118 ------------------ .../components/HeaderButton/HeaderButton.tsx | 35 ------ site/src/components/RoleSelect/RoleSelect.tsx | 5 + site/src/components/UsersTable/UsersTable.tsx | 4 +- .../pages/TemplatesPage/TemplatesPageView.tsx | 18 +-- site/src/pages/UsersPage/UsersPageView.tsx | 32 ++++- .../WorkspacesPage/WorkspacesPageView.tsx | 41 +----- 10 files changed, 137 insertions(+), 234 deletions(-) create mode 100644 site/src/components/AvatarData/AvatarData.stories.tsx create mode 100644 site/src/components/AvatarData/AvatarData.tsx delete mode 100644 site/src/components/Header/Header.test.tsx delete mode 100644 site/src/components/Header/Header.tsx delete mode 100644 site/src/components/HeaderButton/HeaderButton.tsx diff --git a/site/src/components/AvatarData/AvatarData.stories.tsx b/site/src/components/AvatarData/AvatarData.stories.tsx new file mode 100644 index 0000000000000..da03672a13ef6 --- /dev/null +++ b/site/src/components/AvatarData/AvatarData.stories.tsx @@ -0,0 +1,23 @@ +import { Story } from "@storybook/react" +import React from "react" +import { AvatarData, AvatarDataProps } from "./AvatarData" + +export default { + title: "components/AvatarData", + component: AvatarData, +} + +const Template: Story = (args: AvatarDataProps) => + +export const Example = Template.bind({}) +Example.args = { + title: "coder", + subtitle: "coder@coder.com", +} + +export const WithLink = Template.bind({}) +WithLink.args = { + title: "coder", + subtitle: "coder@coder.com", + link: "/users/coder", +} diff --git a/site/src/components/AvatarData/AvatarData.tsx b/site/src/components/AvatarData/AvatarData.tsx new file mode 100644 index 0000000000000..730d6f1f742b5 --- /dev/null +++ b/site/src/components/AvatarData/AvatarData.tsx @@ -0,0 +1,67 @@ +import Avatar from "@material-ui/core/Avatar" +import Link from "@material-ui/core/Link" +import { makeStyles } from "@material-ui/core/styles" +import React from "react" +import { Link as RouterLink } from "react-router-dom" +import { combineClasses } from "../../util/combineClasses" +import { firstLetter } from "../../util/firstLetter" + +export interface AvatarDataProps { + title: string + subtitle: string + link?: string +} + +export const AvatarData: React.FC = ({ title, subtitle, link }) => { + const styles = useStyles() + + return ( +
+ + {firstLetter(title)} + + + {link ? ( + + {title} + {subtitle} + + ) : ( +
+ {title} + {subtitle} +
+ )} +
+ ) +} + +const useStyles = makeStyles((theme) => ({ + root: { + display: "flex", + alignItems: "center", + }, + avatar: { + borderRadius: 2, + marginRight: theme.spacing(1), + width: 24, + height: 24, + fontSize: 16, + }, + info: { + display: "flex", + flexDirection: "column", + color: theme.palette.text.primary, + + "& span": { + fontSize: 12, + color: theme.palette.text.secondary, + }, + }, + link: { + textDecoration: "none", + "&:hover": { + textDecoration: "underline", + }, + }, +})) diff --git a/site/src/components/Header/Header.test.tsx b/site/src/components/Header/Header.test.tsx deleted file mode 100644 index 35d38de89c7c3..0000000000000 --- a/site/src/components/Header/Header.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { screen } from "@testing-library/react" -import React from "react" -import { render } from "../../testHelpers/renderHelpers" -import { Header } from "./Header" - -describe("Header", () => { - it("renders title and subtitle", async () => { - // When - render(
) - - // Then - const titleElement = await screen.findByText("Title Test") - expect(titleElement).toBeDefined() - - const subTitleElement = await screen.findByText("Subtitle Test") - expect(subTitleElement).toBeDefined() - }) - - it("renders button if specified", async () => { - // When - render(
) - - // Then - const buttonElement = await screen.findByRole("button") - expect(buttonElement).toBeDefined() - expect(buttonElement.textContent).toEqual("Button Test") - }) -}) diff --git a/site/src/components/Header/Header.tsx b/site/src/components/Header/Header.tsx deleted file mode 100644 index 3fdf1141ece6b..0000000000000 --- a/site/src/components/Header/Header.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import Box from "@material-ui/core/Box" -import { makeStyles } from "@material-ui/core/styles" -import Typography from "@material-ui/core/Typography" -import React from "react" -import { maxWidth, sidePadding } from "../../theme/constants" -import { HeaderButton } from "../HeaderButton/HeaderButton" - -export interface HeaderAction { - readonly text: string - readonly onClick?: (event: MouseEvent) => void -} - -export interface HeaderProps { - description?: string - title: string - subTitle?: string - action?: HeaderAction -} - -export const Header: React.FC = ({ description, title, subTitle, action }) => { - const styles = useStyles() - - return ( -
-
-
- -
- - - - {title} - - - - {subTitle && ( -
- {subTitle} -
- )} -
- {description && ( - - {description} - - )} -
-
- - {action && ( - <> -
- -
- - )} -
-
-
- ) -} - -const secondaryText = "#B5BFD2" -const useStyles = makeStyles((theme) => ({ - root: {}, - top: { - position: "relative", - display: "flex", - alignItems: "center", - height: 126, - background: theme.palette.background.default, - boxShadow: theme.shadows[3], - }, - topInner: { - display: "flex", - alignItems: "center", - maxWidth, - margin: "0 auto", - flex: 1, - height: 68, - minWidth: 0, - padding: `0 ${sidePadding}`, - }, - title: { - display: "flex", - alignItems: "center", - fontWeight: "bold", - whiteSpace: "nowrap", - minWidth: 0, - color: theme.palette.primary.contrastText, - }, - description: { - display: "block", - marginTop: theme.spacing(1) / 2, - marginBottom: -26, - color: secondaryText, - }, - subtitle: { - position: "relative", - top: 2, - display: "flex", - alignItems: "center", - borderLeft: `1px solid ${theme.palette.divider}`, - height: 28, - marginLeft: 16, - paddingLeft: 16, - color: secondaryText, - }, - actions: { - paddingLeft: "50px", - paddingRight: 0, - flex: 1, - display: "flex", - flexDirection: "row", - justifyContent: "flex-end", - alignItems: "center", - }, -})) diff --git a/site/src/components/HeaderButton/HeaderButton.tsx b/site/src/components/HeaderButton/HeaderButton.tsx deleted file mode 100644 index ecc4559050e5c..0000000000000 --- a/site/src/components/HeaderButton/HeaderButton.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import Button from "@material-ui/core/Button" -import { makeStyles } from "@material-ui/core/styles" -import React from "react" - -export interface HeaderButtonProps { - readonly text: string - readonly disabled?: boolean - readonly onClick?: (event: MouseEvent) => void -} - -export const HeaderButton: React.FC = (props) => { - const styles = useStyles() - - return ( - - ) -} - -const useStyles = makeStyles(() => ({ - pageButton: { - whiteSpace: "nowrap", - }, -})) diff --git a/site/src/components/RoleSelect/RoleSelect.tsx b/site/src/components/RoleSelect/RoleSelect.tsx index 2527521e4d794..b644d353d15b4 100644 --- a/site/src/components/RoleSelect/RoleSelect.tsx +++ b/site/src/components/RoleSelect/RoleSelect.tsx @@ -55,5 +55,10 @@ const useStyles = makeStyles((theme: Theme) => ({ // Set a fixed width for the select. It avoids selects having different sizes // depending on how many roles they have selected. width: theme.spacing(25), + "& .MuiSelect-root": { + // Adjusting padding because it does not have label + paddingTop: theme.spacing(1.5), + paddingBottom: theme.spacing(1.5), + }, }, })) diff --git a/site/src/components/UsersTable/UsersTable.tsx b/site/src/components/UsersTable/UsersTable.tsx index 62075d66d51ef..1ed0552caa976 100644 --- a/site/src/components/UsersTable/UsersTable.tsx +++ b/site/src/components/UsersTable/UsersTable.tsx @@ -6,11 +6,11 @@ import TableHead from "@material-ui/core/TableHead" import TableRow from "@material-ui/core/TableRow" import React from "react" import * as TypesGen from "../../api/typesGenerated" +import { AvatarData } from "../AvatarData/AvatarData" import { EmptyState } from "../EmptyState/EmptyState" import { RoleSelect } from "../RoleSelect/RoleSelect" import { TableLoader } from "../TableLoader/TableLoader" import { TableRowMenu } from "../TableRowMenu/TableRowMenu" -import { UserCell } from "../UserCell/UserCell" export const Language = { pageTitle: "Users", @@ -60,7 +60,7 @@ export const UsersTable: React.FC = ({ users.map((u) => ( - {" "} + {canEditUsers ? ( diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index 92426747e8e54..6e73e0c397808 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -1,5 +1,3 @@ -import Avatar from "@material-ui/core/Avatar" -import Box from "@material-ui/core/Box" import Link from "@material-ui/core/Link" import { makeStyles } from "@material-ui/core/styles" import Table from "@material-ui/core/Table" @@ -12,10 +10,10 @@ import relativeTime from "dayjs/plugin/relativeTime" import React from "react" import { Link as RouterLink } from "react-router-dom" import * as TypesGen from "../../api/typesGenerated" +import { AvatarData } from "../../components/AvatarData/AvatarData" import { Margins } from "../../components/Margins/Margins" import { Stack } from "../../components/Stack/Stack" import { TableLoader } from "../../components/TableLoader/TableLoader" -import { firstLetter } from "../../util/firstLetter" dayjs.extend(relativeTime) @@ -73,15 +71,11 @@ export const TemplatesPageView: React.FC = (props) => { {props.templates?.map((template) => ( - - - {firstLetter(template.name)} - - - {template.name} - {template.description} - - + {Language.developerCount(template.workspace_owner_count)} diff --git a/site/src/pages/UsersPage/UsersPageView.tsx b/site/src/pages/UsersPage/UsersPageView.tsx index be5367d748ab5..9bf6a4d93ac65 100644 --- a/site/src/pages/UsersPage/UsersPageView.tsx +++ b/site/src/pages/UsersPage/UsersPageView.tsx @@ -1,14 +1,16 @@ +import Button from "@material-ui/core/Button" +import { makeStyles } from "@material-ui/core/styles" +import AddCircleOutline from "@material-ui/icons/AddCircleOutline" import React from "react" import * as TypesGen from "../../api/typesGenerated" import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary" -import { Header } from "../../components/Header/Header" import { Margins } from "../../components/Margins/Margins" import { Stack } from "../../components/Stack/Stack" import { UsersTable } from "../../components/UsersTable/UsersTable" export const Language = { pageTitle: "Users", - newUserButton: "New user", + createButton: "New user", } export interface UsersPageViewProps { @@ -38,11 +40,20 @@ export const UsersPageView: React.FC = ({ canCreateUser, isLoading, }) => { - const newUserAction = canCreateUser ? { text: Language.newUserButton, onClick: openUserCreationDialog } : undefined + const styles = useStyles() + return ( -
+
+
+ {canCreateUser && ( + + )} +
+
{error ? ( ) : ( @@ -61,3 +72,16 @@ export const UsersPageView: React.FC = ({ ) } + +const useStyles = makeStyles((theme) => ({ + actions: { + marginTop: theme.spacing(3), + marginBottom: theme.spacing(3), + display: "flex", + height: theme.spacing(6), + + "& > *": { + marginLeft: "auto", + }, + }, +})) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx index f0a4b44ac94b1..bdf72223b998a 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx @@ -1,4 +1,3 @@ -import Avatar from "@material-ui/core/Avatar" import Button from "@material-ui/core/Button" import Link from "@material-ui/core/Link" import { makeStyles, Theme } from "@material-ui/core/styles" @@ -14,9 +13,9 @@ import relativeTime from "dayjs/plugin/relativeTime" import React from "react" import { Link as RouterLink } from "react-router-dom" import * as TypesGen from "../../api/typesGenerated" +import { AvatarData } from "../../components/AvatarData/AvatarData" import { Margins } from "../../components/Margins/Margins" import { Stack } from "../../components/Stack/Stack" -import { firstLetter } from "../../util/firstLetter" import { getDisplayStatus } from "../../util/workspace" dayjs.extend(relativeTime) @@ -73,15 +72,11 @@ export const WorkspacesPageView: React.FC = (props) => return ( -
- - {firstLetter(workspace.name)} - - - {workspace.name} - {workspace.owner_name} - -
+
{workspace.template_name} @@ -134,28 +129,4 @@ const useStyles = makeStyles((theme) => ({ lineHeight: `${theme.spacing(3)}px`, }, }, - workspaceAvatar: { - borderRadius: 2, - marginRight: theme.spacing(1), - width: 24, - height: 24, - fontSize: 16, - }, - workspaceName: { - display: "flex", - alignItems: "center", - }, - workspaceLink: { - display: "flex", - flexDirection: "column", - color: theme.palette.text.primary, - textDecoration: "none", - "&:hover": { - textDecoration: "underline", - }, - "& span": { - fontSize: 12, - color: theme.palette.text.secondary, - }, - }, })) From b052f84f8fbce8d57ba1bd1790d25aae055f07a5 Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 27 May 2022 16:12:28 +0000 Subject: [PATCH 2/4] Remove unused styles --- .../pages/TemplatesPage/TemplatesPageView.tsx | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index 6e73e0c397808..f23841e20d27e 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -108,24 +108,4 @@ const useStyles = makeStyles((theme) => ({ lineHeight: `${theme.spacing(3)}px`, }, }, - templateAvatar: { - borderRadius: 2, - marginRight: theme.spacing(1), - width: 24, - height: 24, - fontSize: 16, - }, - templateLink: { - display: "flex", - flexDirection: "column", - color: theme.palette.text.primary, - textDecoration: "none", - "&:hover": { - textDecoration: "underline", - }, - "& span": { - fontSize: 12, - color: theme.palette.text.secondary, - }, - }, })) From 339c16e1828a00a46a80a5cc683c1abdd97b97bd Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 27 May 2022 16:17:21 +0000 Subject: [PATCH 3/4] Update new to create --- site/src/pages/UsersPage/UsersPage.test.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/src/pages/UsersPage/UsersPage.test.tsx b/site/src/pages/UsersPage/UsersPage.test.tsx index ea57bbb978970..d0671b068e3c2 100644 --- a/site/src/pages/UsersPage/UsersPage.test.tsx +++ b/site/src/pages/UsersPage/UsersPage.test.tsx @@ -103,13 +103,13 @@ describe("Users Page", () => { expect(users.length).toEqual(2) }) - it("shows 'New user' button to an authorized user", () => { + it("shows 'Create user' button to an authorized user", () => { render() - const newUserButton = screen.queryByText(UsersViewLanguage.newUserButton) - expect(newUserButton).toBeDefined() + const createUserButton = screen.queryByText(UsersViewLanguage.createButton) + expect(createUserButton).toBeDefined() }) - it("does not show 'New user' button to unauthorized user", () => { + it("does not show 'Create user' button to unauthorized user", () => { server.use( rest.post("/api/v2/users/:userId/authorization", async (req, res, ctx) => { const permissions = Object.keys(permissionsToCheck) @@ -125,8 +125,8 @@ describe("Users Page", () => { }), ) render() - const newUserButton = screen.queryByText(UsersViewLanguage.newUserButton) - expect(newUserButton).toBeNull() + const createUserButton = screen.queryByText(UsersViewLanguage.createButton) + expect(createUserButton).toBeNull() }) describe("suspend user", () => { From 65323e8300b0363d0374fbd609d79c89cac3d06b Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 27 May 2022 16:33:16 +0000 Subject: [PATCH 4/4] Fixworkspace page test --- site/src/pages/WorkspacePage/WorkspacePage.test.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index 5340005dc1e07..502bd76b2c0c7 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -139,8 +139,12 @@ describe("Workspace Page", () => { it("shows the timeline build", async () => { await renderWorkspacePage() const table = await screen.findByTestId("builds-table") - const rows = table.querySelectorAll("tbody > tr") - expect(rows).toHaveLength(MockBuilds.length) + + // Wait for the results to be loaded + await waitFor(async () => { + const rows = table.querySelectorAll("tbody > tr") + expect(rows).toHaveLength(MockBuilds.length) + }) }) }) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy