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..f23841e20d27e 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)} @@ -114,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, - }, - }, })) 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", () => { 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/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) + }) }) }) 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, - }, - }, })) 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