From 9c7612beb5a3f30e0f493d3f3f70b3cb539ddcf3 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 14 Feb 2025 22:48:35 +0000 Subject: [PATCH 1/7] fix: sort orgs alphabetically in dropdown --- .../OrganizationSidebarView.stories.tsx | 47 ++++++++++++++++++- .../management/OrganizationSidebarView.tsx | 14 ++++-- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/site/src/modules/management/OrganizationSidebarView.stories.tsx b/site/src/modules/management/OrganizationSidebarView.stories.tsx index 4f1b17a27c181..3f323e5e90be8 100644 --- a/site/src/modules/management/OrganizationSidebarView.stories.tsx +++ b/site/src/modules/management/OrganizationSidebarView.stories.tsx @@ -6,8 +6,12 @@ import { MockOrganization2, MockPermissions, } from "testHelpers/entities"; +import type { AuthorizationResponse } from "api/typesGenerated"; import { withDashboardProvider } from "testHelpers/storybook"; -import { OrganizationSidebarView } from "./OrganizationSidebarView"; +import { + OrganizationSidebarView, + type OrganizationWithPermissions, +} from "./OrganizationSidebarView"; const meta: Meta = { title: "modules/management/OrganizationSidebarView", @@ -286,3 +290,44 @@ export const OrgsDisabled: Story = { showOrganizations: false, }, }; + +const commonPerms: AuthorizationResponse = { + editOrganization: true, + editMembers: true, + editGroups: true, + auditOrganization: true, +}; + +const activeOrganization: OrganizationWithPermissions = { + ...MockOrganization, + display_name: "Omega org", + name: "omega", + id: "1", + permissions: { + ...commonPerms, + }, +}; + +export const OrgsSortedAlphabetically: Story = { + args: { + activeOrganization, + permissions: MockPermissions, + organizations: [ + { + ...MockOrganization, + display_name: "Zeta Org", + id: "2", + name: "zeta", + permissions: commonPerms, + }, + { + ...MockOrganization, + display_name: "alpha Org", + id: "3", + name: "alpha", + permissions: commonPerms, + }, + activeOrganization, + ], + }, +}; diff --git a/site/src/modules/management/OrganizationSidebarView.tsx b/site/src/modules/management/OrganizationSidebarView.tsx index 8d913edf87df3..0049b20e4a319 100644 --- a/site/src/modules/management/OrganizationSidebarView.tsx +++ b/site/src/modules/management/OrganizationSidebarView.tsx @@ -88,11 +88,15 @@ const OrganizationsSettingsNavigation: FC< return ; } - // Sort organizations to put active organization first - const sortedOrganizations = [ - activeOrganization, - ...organizations.filter((org) => org.id !== activeOrganization.id), - ]; + const sortedOrganizations = [...organizations].sort((a, b) => { + // active org first + if (a.id === activeOrganization.id) return -1; + if (b.id === activeOrganization.id) return 1; + + return a.display_name + .toLowerCase() + .localeCompare(b.display_name.toLowerCase()); + }); const [isPopoverOpen, setIsPopoverOpen] = useState(false); const navigate = useNavigate(); From 54c1ba4dab9a26902cbbec73028261f3bbd54a3e Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 14 Feb 2025 23:26:11 +0000 Subject: [PATCH 2/7] sort imports --- site/src/modules/management/OrganizationSidebarView.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/modules/management/OrganizationSidebarView.stories.tsx b/site/src/modules/management/OrganizationSidebarView.stories.tsx index 3f323e5e90be8..974b19cc57285 100644 --- a/site/src/modules/management/OrganizationSidebarView.stories.tsx +++ b/site/src/modules/management/OrganizationSidebarView.stories.tsx @@ -1,12 +1,12 @@ import type { Meta, StoryObj } from "@storybook/react"; import { expect, userEvent, waitFor, within } from "@storybook/test"; +import type { AuthorizationResponse } from "api/typesGenerated"; import { MockNoPermissions, MockOrganization, MockOrganization2, MockPermissions, } from "testHelpers/entities"; -import type { AuthorizationResponse } from "api/typesGenerated"; import { withDashboardProvider } from "testHelpers/storybook"; import { OrganizationSidebarView, From 3484dd2d287a9e1f8875ed6739524f2073423b0d Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 18 Feb 2025 17:15:32 +0000 Subject: [PATCH 3/7] add search bar --- .../OrganizationSidebarView.stories.tsx | 43 +++++++++++++++++++ .../management/OrganizationSidebarView.tsx | 4 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/site/src/modules/management/OrganizationSidebarView.stories.tsx b/site/src/modules/management/OrganizationSidebarView.stories.tsx index 974b19cc57285..b19a5d5803471 100644 --- a/site/src/modules/management/OrganizationSidebarView.stories.tsx +++ b/site/src/modules/management/OrganizationSidebarView.stories.tsx @@ -331,3 +331,46 @@ export const OrgsSortedAlphabetically: Story = { ], }, }; + +export const SearchAndSelectOrg: Story = { + args: { + activeOrganization, + permissions: MockPermissions, + organizations: [ + { + ...MockOrganization, + display_name: "Zeta Org", + id: "2", + name: "zeta", + permissions: commonPerms, + }, + { + ...MockOrganization, + display_name: "alpha Org", + id: "3", + name: "fish", + permissions: commonPerms, + }, + activeOrganization, + ], + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByRole("button", { name: /Omega org/i })); + + // searchInput is not in #storybook-root so must query full document + const globalScreen = within(document.body); + const searchInput = + await globalScreen.getByPlaceholderText("Find organization"); + + await userEvent.type(searchInput, "ALPHA"); + + const filteredResult = await globalScreen.findByText("alpha Org"); + expect(filteredResult).toBeInTheDocument(); + + // Omega org remains visible as the default org + await waitFor(() => { + expect(globalScreen.queryByText("Zeta Org")).not.toBeInTheDocument(); + }); + }, +}; diff --git a/site/src/modules/management/OrganizationSidebarView.tsx b/site/src/modules/management/OrganizationSidebarView.tsx index 0049b20e4a319..0d0b04ee41e69 100644 --- a/site/src/modules/management/OrganizationSidebarView.tsx +++ b/site/src/modules/management/OrganizationSidebarView.tsx @@ -3,6 +3,7 @@ import { Avatar } from "components/Avatar/Avatar"; import { Button } from "components/Button/Button"; import { Command, + CommandInput, CommandGroup, CommandItem, CommandList, @@ -127,6 +128,7 @@ const OrganizationsSettingsNavigation: FC< + {sortedOrganizations.length > 1 && ( @@ -134,7 +136,7 @@ const OrganizationsSettingsNavigation: FC< {sortedOrganizations.map((organization) => ( { setIsPopoverOpen(false); navigate(urlForSubpage(organization.name)); From 4d5ac449910b36da535ec67e6d9ce164c3c28d71 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 18 Feb 2025 17:18:31 +0000 Subject: [PATCH 4/7] import order fix --- site/src/modules/management/OrganizationSidebarView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/modules/management/OrganizationSidebarView.tsx b/site/src/modules/management/OrganizationSidebarView.tsx index 0d0b04ee41e69..ef31fc15726b1 100644 --- a/site/src/modules/management/OrganizationSidebarView.tsx +++ b/site/src/modules/management/OrganizationSidebarView.tsx @@ -3,8 +3,8 @@ import { Avatar } from "components/Avatar/Avatar"; import { Button } from "components/Button/Button"; import { Command, - CommandInput, CommandGroup, + CommandInput, CommandItem, CommandList, } from "components/Command/Command"; From b39f5b5dbfab5990912f45a97033de227cad5bf7 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Tue, 18 Feb 2025 20:25:38 +0000 Subject: [PATCH 5/7] fix: handle create org button when searching --- .../management/OrganizationSidebarView.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/site/src/modules/management/OrganizationSidebarView.tsx b/site/src/modules/management/OrganizationSidebarView.tsx index ef31fc15726b1..b618c4f72bd3d 100644 --- a/site/src/modules/management/OrganizationSidebarView.tsx +++ b/site/src/modules/management/OrganizationSidebarView.tsx @@ -3,10 +3,12 @@ import { Avatar } from "components/Avatar/Avatar"; import { Button } from "components/Button/Button"; import { Command, + CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, + CommandSeparator, } from "components/Command/Command"; import { Loader } from "components/Loader/Loader"; import { @@ -130,6 +132,7 @@ const OrganizationsSettingsNavigation: FC< + No organization found. {sortedOrganizations.length > 1 && (
@@ -164,11 +167,11 @@ const OrganizationsSettingsNavigation: FC< ))}
)} - {permissions.createOrganization && ( - <> - {organizations.length > 1 && ( -
- )} +
+ {permissions.createOrganization && ( + <> + {organizations.length > 1 && } + { @@ -180,9 +183,9 @@ const OrganizationsSettingsNavigation: FC< > Create Organization - - )} - +
+ + )}
From ef75407f73767515c222fb4099fbbb894ccd3577 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 18 Feb 2025 21:27:19 +0000 Subject: [PATCH 6/7] improve test --- .../OrganizationSidebarView.stories.tsx | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/site/src/modules/management/OrganizationSidebarView.stories.tsx b/site/src/modules/management/OrganizationSidebarView.stories.tsx index b19a5d5803471..29517f8a21ad4 100644 --- a/site/src/modules/management/OrganizationSidebarView.stories.tsx +++ b/site/src/modules/management/OrganizationSidebarView.stories.tsx @@ -311,7 +311,10 @@ const activeOrganization: OrganizationWithPermissions = { export const OrgsSortedAlphabetically: Story = { args: { activeOrganization, - permissions: MockPermissions, + permissions: { + ...MockPermissions, + createOrganization: true, + }, organizations: [ { ...MockOrganization, @@ -330,9 +333,30 @@ export const OrgsSortedAlphabetically: Story = { activeOrganization, ], }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByRole("button", { name: /Omega org/i })); + + // dropdown is not in #storybook-root so must query full document + const globalScreen = within(document.body); + + await waitFor(() => { + expect(globalScreen.queryByText("alpha Org")).toBeInTheDocument(); + expect(globalScreen.queryByText("Zeta Org")).toBeInTheDocument(); + }); + + const orgElements = globalScreen.getAllByRole("option"); + const orgNames = orgElements.map( + // handling fuzzy matching + (el) => el.textContent?.replace(/^[A-Z]/, "").trim() || "", + ); + + // active name first + expect(orgNames).toEqual(["Omega org", "alpha Org", "Zeta Org"]); + }, }; -export const SearchAndSelectOrg: Story = { +export const SearchForOrg: Story = { args: { activeOrganization, permissions: MockPermissions, @@ -358,7 +382,7 @@ export const SearchAndSelectOrg: Story = { const canvas = within(canvasElement); await userEvent.click(canvas.getByRole("button", { name: /Omega org/i })); - // searchInput is not in #storybook-root so must query full document + // dropdown is not in #storybook-root so must query full document const globalScreen = within(document.body); const searchInput = await globalScreen.getByPlaceholderText("Find organization"); From c1e6f48132b861be0665be1d12403697fc481e08 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 18 Feb 2025 21:40:12 +0000 Subject: [PATCH 7/7] filter button out --- .../modules/management/OrganizationSidebarView.stories.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/site/src/modules/management/OrganizationSidebarView.stories.tsx b/site/src/modules/management/OrganizationSidebarView.stories.tsx index 29517f8a21ad4..6533a5e004ef5 100644 --- a/site/src/modules/management/OrganizationSidebarView.stories.tsx +++ b/site/src/modules/management/OrganizationSidebarView.stories.tsx @@ -346,7 +346,10 @@ export const OrgsSortedAlphabetically: Story = { }); const orgElements = globalScreen.getAllByRole("option"); - const orgNames = orgElements.map( + // filter out Create btn + const filteredElems = orgElements.slice(0, 3); + + const orgNames = filteredElems.map( // handling fuzzy matching (el) => el.textContent?.replace(/^[A-Z]/, "").trim() || "", );