From bc35726cbfeacdff8c3c816db153c01cef8622e2 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Tue, 12 Mar 2024 20:41:17 -0700 Subject: [PATCH 1/6] Add Type column to access table --- app/components/AccessNameCell.tsx | 23 ++----------------- app/components/AccessTypeCell.tsx | 20 ++++++++++++++++ app/pages/SiloAccessPage.tsx | 2 ++ .../project/access/ProjectAccessPage.tsx | 2 ++ test/e2e/project-access.e2e.ts | 8 +++++-- test/e2e/silo-access.e2e.ts | 4 +++- 6 files changed, 35 insertions(+), 24 deletions(-) create mode 100644 app/components/AccessTypeCell.tsx diff --git a/app/components/AccessNameCell.tsx b/app/components/AccessNameCell.tsx index f3d0b920be..52ea03db32 100644 --- a/app/components/AccessNameCell.tsx +++ b/app/components/AccessNameCell.tsx @@ -7,28 +7,9 @@ */ import type { CellContext } from '@tanstack/react-table' -import type { IdentityType } from '@oxide/api' - -import { Badge } from '~/ui/lib/Badge' - /** * Display the user or group name. If the row is for a group, add a GROUP badge. */ -export const AccessNameCell = < - RowData extends { name: string; identityType: IdentityType }, ->( +export const AccessNameCell = ( info: CellContext -) => { - const name = info.getValue() - const identityType = info.row.original.identityType - return ( - <> - {name} - {identityType === 'silo_group' ? ( - - Group - - ) : null} - - ) -} +) => {info.getValue()} diff --git a/app/components/AccessTypeCell.tsx b/app/components/AccessTypeCell.tsx new file mode 100644 index 0000000000..223b7f97b7 --- /dev/null +++ b/app/components/AccessTypeCell.tsx @@ -0,0 +1,20 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import type { CellContext } from '@tanstack/react-table' + +import type { IdentityType } from '~/api' + +/** + * Display the user or group name. If the row is for a group, add a GROUP badge. + */ +export const AccessTypeCell = ( + info: CellContext +) => { + const identityType = info.row.original.identityType + return {identityType === 'silo_group' ? 'Group' : 'User'} +} diff --git a/app/pages/SiloAccessPage.tsx b/app/pages/SiloAccessPage.tsx index 0ba0d4f014..54db9a9b08 100644 --- a/app/pages/SiloAccessPage.tsx +++ b/app/pages/SiloAccessPage.tsx @@ -23,6 +23,7 @@ import { import { Access24Icon } from '@oxide/design-system/icons/react' import { AccessNameCell } from '~/components/AccessNameCell' +import { AccessTypeCell } from '~/components/AccessTypeCell' import { HL } from '~/components/HL' import { RoleBadgeCell } from '~/components/RoleBadgeCell' import { @@ -112,6 +113,7 @@ export function SiloAccessPage() { const columns = useMemo( () => [ colHelper.accessor('name', { header: 'Name', cell: AccessNameCell }), + colHelper.accessor('identityType', { header: 'Type', cell: AccessTypeCell }), colHelper.accessor('siloRole', { header: 'Silo role', cell: RoleBadgeCell, diff --git a/app/pages/project/access/ProjectAccessPage.tsx b/app/pages/project/access/ProjectAccessPage.tsx index 08d365b291..3a263cc92b 100644 --- a/app/pages/project/access/ProjectAccessPage.tsx +++ b/app/pages/project/access/ProjectAccessPage.tsx @@ -25,6 +25,7 @@ import { import { Access24Icon } from '@oxide/design-system/icons/react' import { AccessNameCell } from '~/components/AccessNameCell' +import { AccessTypeCell } from '~/components/AccessTypeCell' import { HL } from '~/components/HL' import { RoleBadgeCell } from '~/components/RoleBadgeCell' import { @@ -128,6 +129,7 @@ export function ProjectAccessPage() { const columns = useMemo( () => [ colHelper.accessor('name', { header: 'Name', cell: AccessNameCell }), + colHelper.accessor('identityType', { header: 'Type', cell: AccessTypeCell }), colHelper.accessor('siloRole', { header: 'Silo role', cell: RoleBadgeCell, diff --git a/test/e2e/project-access.e2e.ts b/test/e2e/project-access.e2e.ts index a6481688bc..cc177ced09 100644 --- a/test/e2e/project-access.e2e.ts +++ b/test/e2e/project-access.e2e.ts @@ -18,22 +18,26 @@ test('Click through project access page', async ({ page }) => { const table = page.locator('table') await expectRowVisible(table, { Name: 'Hannah Arendt', + Type: 'User', 'Silo role': 'admin', 'Project role': '', }) await expectRowVisible(table, { Name: 'Jacob Klein', + Type: 'User', 'Silo role': '', 'Project role': 'collaborator', }) await expectRowVisible(table, { // no space because expectRowVisible uses textContent, not accessible name - Name: 'real-estate-devsGroup', + Name: 'real-estate-devs', + Type: 'Group', 'Silo role': 'collaborator', }) await expectRowVisible(table, { // no space because expectRowVisible uses textContent, not accessible name - Name: 'kernel-devsGroup', + Name: 'kernel-devs', + Type: 'Group', 'Silo role': '', 'Project role': 'viewer', }) diff --git a/test/e2e/silo-access.e2e.ts b/test/e2e/silo-access.e2e.ts index aaf6142c59..ec45ede7b7 100644 --- a/test/e2e/silo-access.e2e.ts +++ b/test/e2e/silo-access.e2e.ts @@ -20,11 +20,13 @@ test('Click through silo access page', async ({ page }) => { await expectVisible(page, ['role=heading[name*="Access & IAM"]']) await expectRowVisible(table, { // no space because expectRowVisible uses textContent, not accessible name - Name: 'real-estate-devsGroup', + Name: 'real-estate-devs', + Type: 'Group', 'Silo role': 'collaborator', }) await expectRowVisible(table, { Name: 'Hannah Arendt', + Type: 'User', 'Silo role': 'admin', }) await expectNotVisible(page, [`role=cell[name="${user4.display_name}"]`]) From 2b83127adbe8f58c62e11337170c467a302118f0 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Tue, 12 Mar 2024 20:46:50 -0700 Subject: [PATCH 2/6] import from @oxide/api --- app/components/AccessTypeCell.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/AccessTypeCell.tsx b/app/components/AccessTypeCell.tsx index 223b7f97b7..8282dd876a 100644 --- a/app/components/AccessTypeCell.tsx +++ b/app/components/AccessTypeCell.tsx @@ -7,7 +7,7 @@ */ import type { CellContext } from '@tanstack/react-table' -import type { IdentityType } from '~/api' +import type { IdentityType } from '@oxide/api' /** * Display the user or group name. If the row is for a group, add a GROUP badge. From cccdcc5a1f800a2f990137ac8ae0b80286a95c12 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Tue, 12 Mar 2024 21:06:30 -0700 Subject: [PATCH 3/6] Proper description --- app/components/AccessTypeCell.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/AccessTypeCell.tsx b/app/components/AccessTypeCell.tsx index 8282dd876a..8b00f60fc7 100644 --- a/app/components/AccessTypeCell.tsx +++ b/app/components/AccessTypeCell.tsx @@ -10,7 +10,7 @@ import type { CellContext } from '@tanstack/react-table' import type { IdentityType } from '@oxide/api' /** - * Display the user or group name. If the row is for a group, add a GROUP badge. + * Display whether this row displays a User or Group. */ export const AccessTypeCell = ( info: CellContext From d4e9086e78761d5cd87fd7ebe309eaa64c535cdf Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 13 Mar 2024 10:36:43 -0700 Subject: [PATCH 4/6] Update app/components/AccessTypeCell.tsx Co-authored-by: David Crespo --- app/components/AccessTypeCell.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/components/AccessTypeCell.tsx b/app/components/AccessTypeCell.tsx index 8b00f60fc7..e671a8d2e0 100644 --- a/app/components/AccessTypeCell.tsx +++ b/app/components/AccessTypeCell.tsx @@ -13,8 +13,7 @@ import type { IdentityType } from '@oxide/api' * Display whether this row displays a User or Group. */ export const AccessTypeCell = ( - info: CellContext + info: CellContext ) => { - const identityType = info.row.original.identityType - return {identityType === 'silo_group' ? 'Group' : 'User'} + return <>{info.getValue() === 'silo_group' ? 'Group' : 'User'} } From 60c92581719222fbee2408b36a88a4abb415eae5 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 13 Mar 2024 10:45:18 -0700 Subject: [PATCH 5/6] Refactor with accessTypeLabel --- app/components/AccessTypeCell.tsx | 19 ------------------- app/pages/SiloAccessPage.tsx | 7 +++++-- .../project/access/ProjectAccessPage.tsx | 7 +++++-- app/util/access.spec.tsx | 15 +++++++++++++++ app/util/access.ts | 11 +++++++++++ 5 files changed, 36 insertions(+), 23 deletions(-) delete mode 100644 app/components/AccessTypeCell.tsx create mode 100644 app/util/access.spec.tsx create mode 100644 app/util/access.ts diff --git a/app/components/AccessTypeCell.tsx b/app/components/AccessTypeCell.tsx deleted file mode 100644 index e671a8d2e0..0000000000 --- a/app/components/AccessTypeCell.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * Copyright Oxide Computer Company - */ -import type { CellContext } from '@tanstack/react-table' - -import type { IdentityType } from '@oxide/api' - -/** - * Display whether this row displays a User or Group. - */ -export const AccessTypeCell = ( - info: CellContext -) => { - return <>{info.getValue() === 'silo_group' ? 'Group' : 'User'} -} diff --git a/app/pages/SiloAccessPage.tsx b/app/pages/SiloAccessPage.tsx index 54db9a9b08..a7bfb9e86a 100644 --- a/app/pages/SiloAccessPage.tsx +++ b/app/pages/SiloAccessPage.tsx @@ -23,7 +23,6 @@ import { import { Access24Icon } from '@oxide/design-system/icons/react' import { AccessNameCell } from '~/components/AccessNameCell' -import { AccessTypeCell } from '~/components/AccessTypeCell' import { HL } from '~/components/HL' import { RoleBadgeCell } from '~/components/RoleBadgeCell' import { @@ -37,6 +36,7 @@ import { Button } from '~/ui/lib/Button' import { EmptyMessage } from '~/ui/lib/EmptyMessage' import { PageHeader, PageTitle } from '~/ui/lib/PageHeader' import { TableActions, TableEmptyBox } from '~/ui/lib/Table' +import { accessTypeLabel } from '~/util/access' import { groupBy, isTruthy } from '~/util/array' const EmptyState = ({ onClick }: { onClick: () => void }) => ( @@ -113,7 +113,10 @@ export function SiloAccessPage() { const columns = useMemo( () => [ colHelper.accessor('name', { header: 'Name', cell: AccessNameCell }), - colHelper.accessor('identityType', { header: 'Type', cell: AccessTypeCell }), + colHelper.accessor('identityType', { + header: 'Type', + cell: (props) => accessTypeLabel(props.getValue()), + }), colHelper.accessor('siloRole', { header: 'Silo role', cell: RoleBadgeCell, diff --git a/app/pages/project/access/ProjectAccessPage.tsx b/app/pages/project/access/ProjectAccessPage.tsx index 3a263cc92b..8b363b8646 100644 --- a/app/pages/project/access/ProjectAccessPage.tsx +++ b/app/pages/project/access/ProjectAccessPage.tsx @@ -25,7 +25,6 @@ import { import { Access24Icon } from '@oxide/design-system/icons/react' import { AccessNameCell } from '~/components/AccessNameCell' -import { AccessTypeCell } from '~/components/AccessTypeCell' import { HL } from '~/components/HL' import { RoleBadgeCell } from '~/components/RoleBadgeCell' import { @@ -40,6 +39,7 @@ import { Button } from '~/ui/lib/Button' import { EmptyMessage } from '~/ui/lib/EmptyMessage' import { PageHeader, PageTitle } from '~/ui/lib/PageHeader' import { TableActions, TableEmptyBox } from '~/ui/lib/Table' +import { accessTypeLabel } from '~/util/access' import { groupBy, isTruthy } from '~/util/array' const EmptyState = ({ onClick }: { onClick: () => void }) => ( @@ -129,7 +129,10 @@ export function ProjectAccessPage() { const columns = useMemo( () => [ colHelper.accessor('name', { header: 'Name', cell: AccessNameCell }), - colHelper.accessor('identityType', { header: 'Type', cell: AccessTypeCell }), + colHelper.accessor('identityType', { + header: 'Type', + cell: (props) => accessTypeLabel(props.getValue()), + }), colHelper.accessor('siloRole', { header: 'Silo role', cell: RoleBadgeCell, diff --git a/app/util/access.spec.tsx b/app/util/access.spec.tsx new file mode 100644 index 0000000000..2f0ed47884 --- /dev/null +++ b/app/util/access.spec.tsx @@ -0,0 +1,15 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { expect, test } from 'vitest' + +import { accessTypeLabel } from './access' + +test('accessTypeLabel', () => { + expect(accessTypeLabel('silo_group')).toEqual('Group') + expect(accessTypeLabel('silo_user')).toEqual('User') +}) diff --git a/app/util/access.ts b/app/util/access.ts new file mode 100644 index 0000000000..0816af6136 --- /dev/null +++ b/app/util/access.ts @@ -0,0 +1,11 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import type { IdentityType } from '~/api' + +export const accessTypeLabel = (identityType: IdentityType) => + identityType === 'silo_group' ? 'Group' : 'User' From 8a436d741475b61ee9dc8eac24fd49c94fbdba11 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 13 Mar 2024 10:48:24 -0700 Subject: [PATCH 6/6] Remove AccessNameCell --- app/components/AccessNameCell.tsx | 15 --------------- app/pages/SiloAccessPage.tsx | 3 +-- app/pages/project/access/ProjectAccessPage.tsx | 3 +-- 3 files changed, 2 insertions(+), 19 deletions(-) delete mode 100644 app/components/AccessNameCell.tsx diff --git a/app/components/AccessNameCell.tsx b/app/components/AccessNameCell.tsx deleted file mode 100644 index 52ea03db32..0000000000 --- a/app/components/AccessNameCell.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * Copyright Oxide Computer Company - */ -import type { CellContext } from '@tanstack/react-table' - -/** - * Display the user or group name. If the row is for a group, add a GROUP badge. - */ -export const AccessNameCell = ( - info: CellContext -) => {info.getValue()} diff --git a/app/pages/SiloAccessPage.tsx b/app/pages/SiloAccessPage.tsx index a7bfb9e86a..f331a3d877 100644 --- a/app/pages/SiloAccessPage.tsx +++ b/app/pages/SiloAccessPage.tsx @@ -22,7 +22,6 @@ import { } from '@oxide/api' import { Access24Icon } from '@oxide/design-system/icons/react' -import { AccessNameCell } from '~/components/AccessNameCell' import { HL } from '~/components/HL' import { RoleBadgeCell } from '~/components/RoleBadgeCell' import { @@ -112,7 +111,7 @@ export function SiloAccessPage() { const columns = useMemo( () => [ - colHelper.accessor('name', { header: 'Name', cell: AccessNameCell }), + colHelper.accessor('name', { header: 'Name' }), colHelper.accessor('identityType', { header: 'Type', cell: (props) => accessTypeLabel(props.getValue()), diff --git a/app/pages/project/access/ProjectAccessPage.tsx b/app/pages/project/access/ProjectAccessPage.tsx index 8b363b8646..e81c245d40 100644 --- a/app/pages/project/access/ProjectAccessPage.tsx +++ b/app/pages/project/access/ProjectAccessPage.tsx @@ -24,7 +24,6 @@ import { } from '@oxide/api' import { Access24Icon } from '@oxide/design-system/icons/react' -import { AccessNameCell } from '~/components/AccessNameCell' import { HL } from '~/components/HL' import { RoleBadgeCell } from '~/components/RoleBadgeCell' import { @@ -128,7 +127,7 @@ export function ProjectAccessPage() { const columns = useMemo( () => [ - colHelper.accessor('name', { header: 'Name', cell: AccessNameCell }), + colHelper.accessor('name', { header: 'Name' }), colHelper.accessor('identityType', { header: 'Type', cell: (props) => accessTypeLabel(props.getValue()),