From 7ea5164ed253382f85c012d79d712a9b08ef3c65 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 27 May 2022 18:36:34 +0000 Subject: [PATCH 1/3] view user roles in menu resolves #1524 --- .../UserDropdown/UserDropdown.stories.tsx | 50 ++++++++++++++++- .../UserDropdown/UserDropdown.test.tsx | 55 +++++++++++-------- .../UserProfileCard/UserProfileCard.tsx | 21 ++++++- site/src/theme/overrides.ts | 5 ++ 4 files changed, 103 insertions(+), 28 deletions(-) diff --git a/site/src/components/UserDropdown/UserDropdown.stories.tsx b/site/src/components/UserDropdown/UserDropdown.stories.tsx index 48fb3650478dd..26381dc6afdc9 100644 --- a/site/src/components/UserDropdown/UserDropdown.stories.tsx +++ b/site/src/components/UserDropdown/UserDropdown.stories.tsx @@ -17,9 +17,53 @@ const Template: Story = (args: UserDropdownProps) => ( ) -export const Example = Template.bind({}) -Example.args = { - user: { id: "1", username: "CathyCoder", email: "cathy@coder.com", created_at: "dawn" }, +export const ExampleNoRoles = Template.bind({}) +ExampleNoRoles.args = { + user: { + id: "1", + username: "CathyCoder", + email: "cathy@coder.com", + created_at: "dawn", + status: "active", + organization_ids: [], + roles: [], + }, + onSignOut: () => { + return Promise.resolve() + }, +} + +export const ExampleOneRole = Template.bind({}) +ExampleNoRoles.args = { + user: { + id: "1", + username: "CathyCoder", + email: "cathy@coder.com", + created_at: "dawn", + status: "active", + organization_ids: [], + roles: [{ name: "member", display_name: "Member" }], + }, + onSignOut: () => { + return Promise.resolve() + }, +} + +export const ExampleThreeRoles = Template.bind({}) +ExampleNoRoles.args = { + user: { + id: "1", + username: "CathyCoder", + email: "cathy@coder.com", + created_at: "dawn", + status: "active", + organization_ids: [], + roles: [ + { name: "admin", display_name: "Admin" }, + { name: "member", display_name: "Member" }, + { name: "auditor", display_name: "Auditor" }, + ], + }, onSignOut: () => { return Promise.resolve() }, diff --git a/site/src/components/UserDropdown/UserDropdown.test.tsx b/site/src/components/UserDropdown/UserDropdown.test.tsx index 3a71246eaa9e4..6e9422eded0a7 100644 --- a/site/src/components/UserDropdown/UserDropdown.test.tsx +++ b/site/src/components/UserDropdown/UserDropdown.test.tsx @@ -1,6 +1,6 @@ import { screen } from "@testing-library/react" import React from "react" -import { MockUser } from "../../testHelpers/entities" +import { MockAdminRole, MockMemberRole, MockUser } from "../../testHelpers/entities" import { render } from "../../testHelpers/renderHelpers" import { Language, UserDropdown, UserDropdownProps } from "./UsersDropdown" @@ -33,6 +33,36 @@ describe("UserDropdown", () => { }) describe("when the menu is open", () => { + it("displays the user's roles", async () => { + await renderAndClick() + + expect(screen.getByText(MockAdminRole.display_name)).toBeDefined() + expect(screen.getByText(MockMemberRole.display_name)).toBeDefined() + }) + + it("has the correct link for the documentation item", async () => { + process.env.CODER_VERSION = "v0.5.4" + await renderAndClick() + + const link = screen.getByText(Language.docsLabel).closest("a") + if (!link) { + throw new Error("Anchor tag not found for the documentation menu item") + } + + expect(link.getAttribute("href")).toBe(`https://github.com/coder/coder/tree/${process.env.CODER_VERSION}/docs`) + }) + + it("has the correct link for the account item", async () => { + await renderAndClick() + + const link = screen.getByText(Language.accountLabel).closest("a") + if (!link) { + throw new Error("Anchor tag not found for the account menu item") + } + + expect(link.getAttribute("href")).toBe("/settings/account") + }) + describe("and sign out is clicked", () => { it("calls the onSignOut function", async () => { const onSignOut = jest.fn() @@ -42,27 +72,4 @@ describe("UserDropdown", () => { }) }) }) - - it("has the correct link for the documentation item", async () => { - process.env.CODER_VERSION = "v0.5.4" - await renderAndClick() - - const link = screen.getByText(Language.docsLabel).closest("a") - if (!link) { - throw new Error("Anchor tag not found for the documentation menu item") - } - - expect(link.getAttribute("href")).toBe(`https://github.com/coder/coder/tree/${process.env.CODER_VERSION}/docs`) - }) - - it("has the correct link for the account item", async () => { - await renderAndClick() - - const link = screen.getByText(Language.accountLabel).closest("a") - if (!link) { - throw new Error("Anchor tag not found for the account menu item") - } - - expect(link.getAttribute("href")).toBe("/settings/account") - }) }) diff --git a/site/src/components/UserProfileCard/UserProfileCard.tsx b/site/src/components/UserProfileCard/UserProfileCard.tsx index dc63b08ea2ef0..c7e52123d8876 100644 --- a/site/src/components/UserProfileCard/UserProfileCard.tsx +++ b/site/src/components/UserProfileCard/UserProfileCard.tsx @@ -1,7 +1,9 @@ +import Chip from "@material-ui/core/Chip" import { makeStyles } from "@material-ui/core/styles" import Typography from "@material-ui/core/Typography" import React from "react" import * as TypesGen from "../../api/typesGenerated" +import { Role } from "../../api/typesGenerated" import { UserAvatar } from "../UserAvatar/UserAvatar" interface UserProfileCardProps { @@ -18,6 +20,13 @@ export const UserProfileCard: React.FC = ({ user }) => { {user.username} {user.email} +
    + {user.roles.map((role: Role) => ( +
  • + +
  • + ))} +
) } @@ -52,6 +61,16 @@ const useStyles = makeStyles((theme) => ({ fontSize: 14, letterSpacing: 0.2, color: theme.palette.text.secondary, - marginBottom: theme.spacing(1.5), + }, + chipContainer: { + display: "flex", + justifyContent: "center", + flexWrap: "wrap", + listStyle: "none", + margin: "0", + padding: `${theme.spacing(1.5)}px ${theme.spacing(2.75)}px`, + }, + chipStyles: { + margin: theme.spacing(0.5), }, })) diff --git a/site/src/theme/overrides.ts b/site/src/theme/overrides.ts index 88f78f5d32353..63f6aac53ace9 100644 --- a/site/src/theme/overrides.ts +++ b/site/src/theme/overrides.ts @@ -33,6 +33,11 @@ export const getOverrides = (palette: PaletteOptions) => { }, }, }, + MuiChip: { + root: { + backgroundColor: "#7057FF", + }, + }, MuiTableHead: { root: { fontFamily: MONOSPACE_FONT_FAMILY, From 2eaa32dc57427fc3b810d19563c0453aca3f662a Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 27 May 2022 18:57:36 +0000 Subject: [PATCH 2/3] fix stories --- .../UserDropdown/UserDropdown.stories.tsx | 36 ------------ .../UserProfileCard.stories.tsx | 56 +++++++++++++++++++ .../UserProfileCard/UserProfileCard.tsx | 2 +- 3 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 site/src/components/UserProfileCard/UserProfileCard.stories.tsx diff --git a/site/src/components/UserDropdown/UserDropdown.stories.tsx b/site/src/components/UserDropdown/UserDropdown.stories.tsx index 26381dc6afdc9..928a42c5c5039 100644 --- a/site/src/components/UserDropdown/UserDropdown.stories.tsx +++ b/site/src/components/UserDropdown/UserDropdown.stories.tsx @@ -32,39 +32,3 @@ ExampleNoRoles.args = { return Promise.resolve() }, } - -export const ExampleOneRole = Template.bind({}) -ExampleNoRoles.args = { - user: { - id: "1", - username: "CathyCoder", - email: "cathy@coder.com", - created_at: "dawn", - status: "active", - organization_ids: [], - roles: [{ name: "member", display_name: "Member" }], - }, - onSignOut: () => { - return Promise.resolve() - }, -} - -export const ExampleThreeRoles = Template.bind({}) -ExampleNoRoles.args = { - user: { - id: "1", - username: "CathyCoder", - email: "cathy@coder.com", - created_at: "dawn", - status: "active", - organization_ids: [], - roles: [ - { name: "admin", display_name: "Admin" }, - { name: "member", display_name: "Member" }, - { name: "auditor", display_name: "Auditor" }, - ], - }, - onSignOut: () => { - return Promise.resolve() - }, -} diff --git a/site/src/components/UserProfileCard/UserProfileCard.stories.tsx b/site/src/components/UserProfileCard/UserProfileCard.stories.tsx new file mode 100644 index 0000000000000..160d130c72ac9 --- /dev/null +++ b/site/src/components/UserProfileCard/UserProfileCard.stories.tsx @@ -0,0 +1,56 @@ +import { Story } from "@storybook/react" +import React from "react" +import { UserProfileCard, UserProfileCardProps } from "./UserProfileCard" + +export default { + title: "components/UserDropdown", + component: UserProfileCard, + argTypes: { + onSignOut: { action: "Sign Out" }, + }, +} + +const Template: Story = (args: UserProfileCardProps) => + +export const ExampleNoRoles = Template.bind({}) +ExampleNoRoles.args = { + user: { + id: "1", + username: "CathyCoder", + email: "cathy@coder.com", + created_at: "dawn", + status: "active", + organization_ids: [], + roles: [], + }, +} + +export const ExampleOneRole = Template.bind({}) +ExampleOneRole.args = { + user: { + id: "1", + username: "CathyCoder", + email: "cathy@coder.com", + created_at: "dawn", + status: "active", + organization_ids: [], + roles: [{ name: "member", display_name: "Member" }], + }, +} + +export const ExampleThreeRoles = Template.bind({}) +ExampleThreeRoles.args = { + user: { + id: "1", + username: "CathyCoder", + email: "cathy@coder.com", + created_at: "dawn", + status: "active", + organization_ids: [], + roles: [ + { name: "admin", display_name: "Admin" }, + { name: "member", display_name: "Member" }, + { name: "auditor", display_name: "Auditor" }, + ], + }, +} diff --git a/site/src/components/UserProfileCard/UserProfileCard.tsx b/site/src/components/UserProfileCard/UserProfileCard.tsx index c7e52123d8876..b022e39778b25 100644 --- a/site/src/components/UserProfileCard/UserProfileCard.tsx +++ b/site/src/components/UserProfileCard/UserProfileCard.tsx @@ -6,7 +6,7 @@ import * as TypesGen from "../../api/typesGenerated" import { Role } from "../../api/typesGenerated" import { UserAvatar } from "../UserAvatar/UserAvatar" -interface UserProfileCardProps { +export interface UserProfileCardProps { user: TypesGen.User } From a08f7834ebb5787b1c21732aa23cae3e5a440a14 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 27 May 2022 19:14:09 +0000 Subject: [PATCH 3/3] PR feedback --- .../UserDropdown/UserDropdown.stories.tsx | 11 ++-------- .../UserProfileCard.stories.tsx | 22 ++++--------------- .../UserProfileCard/UserProfileCard.tsx | 5 ++++- site/src/theme/overrides.ts | 5 ----- 4 files changed, 10 insertions(+), 33 deletions(-) diff --git a/site/src/components/UserDropdown/UserDropdown.stories.tsx b/site/src/components/UserDropdown/UserDropdown.stories.tsx index 928a42c5c5039..14d89ee5d37e8 100644 --- a/site/src/components/UserDropdown/UserDropdown.stories.tsx +++ b/site/src/components/UserDropdown/UserDropdown.stories.tsx @@ -1,6 +1,7 @@ import Box from "@material-ui/core/Box" import { Story } from "@storybook/react" import React from "react" +import { MockUser } from "../../testHelpers/entities" import { UserDropdown, UserDropdownProps } from "./UsersDropdown" export default { @@ -19,15 +20,7 @@ const Template: Story = (args: UserDropdownProps) => ( export const ExampleNoRoles = Template.bind({}) ExampleNoRoles.args = { - user: { - id: "1", - username: "CathyCoder", - email: "cathy@coder.com", - created_at: "dawn", - status: "active", - organization_ids: [], - roles: [], - }, + user: MockUser, onSignOut: () => { return Promise.resolve() }, diff --git a/site/src/components/UserProfileCard/UserProfileCard.stories.tsx b/site/src/components/UserProfileCard/UserProfileCard.stories.tsx index 160d130c72ac9..92754f0709fcf 100644 --- a/site/src/components/UserProfileCard/UserProfileCard.stories.tsx +++ b/site/src/components/UserProfileCard/UserProfileCard.stories.tsx @@ -1,5 +1,6 @@ import { Story } from "@storybook/react" import React from "react" +import { MockUser } from "../../testHelpers/entities" import { UserProfileCard, UserProfileCardProps } from "./UserProfileCard" export default { @@ -15,12 +16,7 @@ const Template: Story = (args: UserProfileCardProps) => = ({ user }) => {
    {user.roles.map((role: Role) => (
  • - +
  • ))}
@@ -73,4 +73,7 @@ const useStyles = makeStyles((theme) => ({ chipStyles: { margin: theme.spacing(0.5), }, + chipRoot: { + backgroundColor: "#7057FF", + }, })) diff --git a/site/src/theme/overrides.ts b/site/src/theme/overrides.ts index 63f6aac53ace9..88f78f5d32353 100644 --- a/site/src/theme/overrides.ts +++ b/site/src/theme/overrides.ts @@ -33,11 +33,6 @@ export const getOverrides = (palette: PaletteOptions) => { }, }, }, - MuiChip: { - root: { - backgroundColor: "#7057FF", - }, - }, MuiTableHead: { root: { fontFamily: MONOSPACE_FONT_FAMILY,