diff --git a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/Roles.tsx b/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/Roles.tsx deleted file mode 100644 index 5ec6e78f95ff1..0000000000000 --- a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/Roles.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Teleport - * Copyright (C) 2024 Gravitational, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -import React from 'react'; - -import { ListProps, StyledTable, renderActionCell } from './ResourceList'; - -export function Roles(props: ListProps & { roles: string[] }) { - const { - roles = [], - addedResources, - addOrRemoveResource, - requestStarted, - } = props; - - return ( - ({ role }))} - pagination={{ pagerPosition: 'top', pageSize: 10 }} - isSearchable={true} - columns={[ - { - key: 'role', - headerText: 'Role Name', - isSortable: true, - }, - { - altKey: 'action-btn', - render: ({ role }) => - renderActionCell( - Boolean(addedResources.role[role]), - requestStarted, - () => addOrRemoveResource('role', role) - ), - }, - ]} - emptyText="No Requestable Roles Found" - /> - ); -} diff --git a/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.story.tsx b/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.story.tsx new file mode 100644 index 0000000000000..085bba838ab97 --- /dev/null +++ b/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.story.tsx @@ -0,0 +1,53 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { useState } from 'react'; + +import { Roles } from './Roles'; + +export default { + title: 'Shared/AccessRequests/Roles', +}; + +export function Default() { + const [requested, setRequested] = useState(new Set()); + return ( + + setRequested(prev => { + const newSet = new Set(prev); + newSet.has(role) ? newSet.delete(role) : newSet.add(role); + return newSet; + }) + } + /> + ); +} + +export function Disabled() { + return ( + {}} + disabled + /> + ); +} diff --git a/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.test.tsx b/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.test.tsx new file mode 100644 index 0000000000000..a49da62b82ed4 --- /dev/null +++ b/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.test.tsx @@ -0,0 +1,70 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { within, screen } from '@testing-library/react'; +import { render } from 'design/utils/testing'; + +import { Roles } from './Roles'; + +test('renders requestable roles with a request option', async () => { + render( + {}} + /> + ); + + const row = await screen.findByRole('row', { + name: /editor/i, + }); + + expect( + await within(row).findByRole('button', { + name: /request access/i, + }) + ).toBeVisible(); +}); + +test('renders requested roles with a remove option and requestable roles with an add option', async () => { + render( + {}} + /> + ); + + const rowEditor = await screen.findByRole('row', { + name: /editor/i, + }); + expect( + await within(rowEditor).findByRole('button', { + name: /remove/i, + }) + ).toBeVisible(); + + const rowAccess = await screen.findByRole('row', { + name: /access/i, + }); + expect( + await within(rowAccess).findByRole('button', { + name: /add to request/i, + }) + ).toBeVisible(); +}); diff --git a/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.tsx b/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.tsx new file mode 100644 index 0000000000000..69b56fda3ce93 --- /dev/null +++ b/web/packages/shared/components/AccessRequests/NewRequest/Roles/Roles.tsx @@ -0,0 +1,71 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import Table, { Cell } from 'design/DataTable'; +import { ButtonPrimary, ButtonBorder } from 'design/Button'; + +export function Roles(props: { + requestable: string[]; + requested: Set; + onToggleRole(role: string): void; + /** Disables buttons.*/ + disabled?: boolean; +}) { + const addToRequestText = props.requested.size + ? '+ Add to Request' + : '+ Request Access'; + + return ( + ({ role }))} + pagination={{ pagerPosition: 'top', pageSize: 10 }} + isSearchable={true} + columns={[ + { + key: 'role', + headerText: 'Role Name', + isSortable: true, + }, + { + altKey: 'action', + render: ({ role }) => { + const isAdded = props.requested.has(role); + const commonProps = { + disabled: props.disabled, + width: '137px', + size: 'small' as const, + onClick: () => props.onToggleRole(role), + }; + return ( + + {isAdded ? ( + Remove + ) : ( + + {addToRequestText} + + )} + + ); + }, + }, + ]} + emptyText="No Requestable Roles Found" + /> + ); +} diff --git a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/index.ts b/web/packages/shared/components/AccessRequests/NewRequest/Roles/index.ts similarity index 93% rename from web/packages/shared/components/AccessRequests/NewRequest/ResourceList/index.ts rename to web/packages/shared/components/AccessRequests/NewRequest/Roles/index.ts index c00c1256c7617..0a6e77dddc722 100644 --- a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/index.ts +++ b/web/packages/shared/components/AccessRequests/NewRequest/Roles/index.ts @@ -16,4 +16,4 @@ * along with this program. If not, see . */ -export { ResourceList } from './ResourceList'; +export { Roles } from './Roles'; diff --git a/web/packages/shared/components/AccessRequests/NewRequest/index.ts b/web/packages/shared/components/AccessRequests/NewRequest/index.ts index 61c58603809d1..dc3c2614a9d7d 100644 --- a/web/packages/shared/components/AccessRequests/NewRequest/index.ts +++ b/web/packages/shared/components/AccessRequests/NewRequest/index.ts @@ -17,7 +17,7 @@ */ export * from './RequestCheckout'; -export * from './ResourceList'; +export * from './Roles'; export type { ResourceMap, RequestableResourceKind } from './resource'; export { getEmptyResourceState } from './resource'; export { isKubeClusterWithNamespaces } from './kube';