From be8945403f59b88179bd81b0a8f8b7602d8294df Mon Sep 17 00:00:00 2001 From: Lisa Kim Date: Tue, 5 Nov 2024 12:52:14 -0800 Subject: [PATCH] [v16] Add Connect and Web UI support for selecting Kubernetes namespaces during access requests (#48413) * Web: add support for requesting for kube namespaces (#47345) * Teleterm: add support for access requesting kube namespaces (#47347) * WebShared: Update how request checkout handles kube resource related errors (#48168) * WebShared: Update how request checkout handles kube resource related errors * Fix bug where after create/cancel, specifiable fields were retained * Remove single toggler for kube resources * Address CR * Update snaps * Backport fixes - teleport version v16 and less uses react select version 3 which required to add manual support for initially fetching namespaces on select dropdown - hover tooltip design diffs - field select design diffs --- web/packages/design/src/DataTable/Table.tsx | 28 +- web/packages/design/src/DataTable/types.ts | 8 + web/packages/design/src/Link/Link.jsx | 1 - .../WelcomeWrapper.story.test.tsx.snap | 1 - .../NewRequest/CheckableOption.tsx | 48 + .../NewRequest/RequestCheckout/CrossIcon.tsx | 58 + .../RequestCheckout/KubeNamespaceSelector.tsx | 231 ++++ .../RequestCheckout/RequestCheckout.story.tsx | 33 + .../RequestCheckout/RequestCheckout.test.tsx | 2 + .../RequestCheckout/RequestCheckout.tsx | 394 ++++-- .../RequestCheckout.story.test.tsx.snap | 1232 +++++++++++------ .../NewRequest/RequestCheckout/index.ts | 6 +- .../NewRequest/ResourceList/Apps.tsx | 4 +- .../NewRequest/ResourceList/ResourceList.tsx | 6 +- .../AccessRequests/NewRequest/index.ts | 4 +- .../AccessRequests/NewRequest/kube.test.ts | 163 +++ .../AccessRequests/NewRequest/kube.ts | 99 ++ .../AccessRequests/NewRequest/resource.ts | 10 +- .../NewRequest/useSpecifiableFields.ts | 11 + .../components/AccessRequests/Shared/utils.ts | 3 +- .../components/FieldSelect/FieldSelect.tsx | 11 +- .../shared/components/Select/types.ts | 4 + .../services/accessRequests/accessRequests.ts | 4 +- web/packages/shared/utils/text.test.ts | 38 +- web/packages/shared/utils/text.ts | 25 + .../AccessRequests.story.test.tsx.snap | 1 - .../teleport/src/AccessRequests/service.ts | 5 +- .../teleport/src/AccessRequests/types.ts | 8 +- .../__snapshots__/ConnectDialog.test.tsx.snap | 2 - .../SelectResource.story.test.tsx.snap | 8 - .../NewCredentials.story.test.tsx.snap | 10 - web/packages/teleport/src/config.ts | 2 +- .../AccessRequestCheckout.tsx | 203 +-- .../useAccessRequestCheckout.test.tsx | 219 +++ .../useAccessRequestCheckout.ts | 140 +- .../NewRequest/NewRequest.tsx | 1 + .../NewRequest/useNewRequest.ts | 18 +- .../ui/DocumentCluster/UnifiedResources.tsx | 2 +- .../accessRequestsService.test.ts | 10 +- .../accessRequestsService.ts | 80 +- 40 files changed, 2371 insertions(+), 762 deletions(-) create mode 100644 web/packages/shared/components/AccessRequests/NewRequest/CheckableOption.tsx create mode 100644 web/packages/shared/components/AccessRequests/NewRequest/RequestCheckout/CrossIcon.tsx create mode 100644 web/packages/shared/components/AccessRequests/NewRequest/RequestCheckout/KubeNamespaceSelector.tsx create mode 100644 web/packages/shared/components/AccessRequests/NewRequest/kube.test.ts create mode 100644 web/packages/shared/components/AccessRequests/NewRequest/kube.ts diff --git a/web/packages/design/src/DataTable/Table.tsx b/web/packages/design/src/DataTable/Table.tsx index 47cc0348eb861..fd4b76ca2378a 100644 --- a/web/packages/design/src/DataTable/Table.tsx +++ b/web/packages/design/src/DataTable/Table.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import React from 'react'; +import React, { PropsWithChildren } from 'react'; import { Box, Flex, Indicator, Text } from 'design'; import * as Icons from 'design/Icon'; @@ -110,6 +110,22 @@ export function Table({ return ; } data.map((item, rowIdx) => { + const TableRow: React.FC = ({ children }) => ( + row?.onClick?.(item)} + style={row?.getStyle?.(item)} + > + {children} + + ); + + const customRow = row?.customRow?.(item); + if (customRow) { + rows.push({customRow}); + return; + } + const cells = columns.flatMap((column, columnIdx) => { if (column.isNonRender) { return []; // does not include this column. @@ -127,15 +143,7 @@ export function Table({ ); }); - rows.push( - row?.onClick?.(item)} - style={row?.getStyle?.(item)} - > - {cells} - - ); + rows.push({cells}); }); if (rows.length) { diff --git a/web/packages/design/src/DataTable/types.ts b/web/packages/design/src/DataTable/types.ts index 53a0abe644e60..afdaf940c2212 100644 --- a/web/packages/design/src/DataTable/types.ts +++ b/web/packages/design/src/DataTable/types.ts @@ -79,6 +79,14 @@ export type TableProps = { * conditionally style a row (eg: cursor: pointer, disabled) */ getStyle?(row: T): React.CSSProperties; + /** + * conditionally render a custom row + * use case: by default all columns are represented by cells + * but certain rows you need all the columns to be merged + * into one cell to render other related elements like a + * dropdown selector. + */ + customRow?(row: T): JSX.Element; }; }; diff --git a/web/packages/design/src/Link/Link.jsx b/web/packages/design/src/Link/Link.jsx index 957be80a5f7be..260c31f85094b 100644 --- a/web/packages/design/src/Link/Link.jsx +++ b/web/packages/design/src/Link/Link.jsx @@ -31,7 +31,6 @@ const StyledButtonLink = styled.a.attrs({ rel: 'noreferrer', })` color: ${({ theme }) => theme.colors.buttons.link.default}; - font-weight: normal; background: none; text-decoration: underline; text-transform: none; diff --git a/web/packages/design/src/Onboard/__snapshots__/WelcomeWrapper.story.test.tsx.snap b/web/packages/design/src/Onboard/__snapshots__/WelcomeWrapper.story.test.tsx.snap index 7a40b24bb5ff9..71b0808b0f065 100644 --- a/web/packages/design/src/Onboard/__snapshots__/WelcomeWrapper.story.test.tsx.snap +++ b/web/packages/design/src/Onboard/__snapshots__/WelcomeWrapper.story.test.tsx.snap @@ -35,7 +35,6 @@ exports[`wrapper 1`] = ` .c13 { color: #009EFF; - font-weight: normal; background: none; text-decoration: underline; text-transform: none; diff --git a/web/packages/shared/components/AccessRequests/NewRequest/CheckableOption.tsx b/web/packages/shared/components/AccessRequests/NewRequest/CheckableOption.tsx new file mode 100644 index 0000000000000..f10b940050628 --- /dev/null +++ b/web/packages/shared/components/AccessRequests/NewRequest/CheckableOption.tsx @@ -0,0 +1,48 @@ +/** + * 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 { Flex, Text } from 'design'; +import { components, OptionProps } from 'react-select'; + +import { Option as BaseOption } from 'shared/components/Select'; + +export type Option = BaseOption & { + isAdded?: boolean; + kind: 'app' | 'user_group' | 'namespace'; +}; + +export const CheckableOptionComponent = ( + props: OptionProps