From 76d678dbf9f0b7df4f684f3c14e06718a2da8915 Mon Sep 17 00:00:00 2001 From: Lisa Kim Date: Mon, 28 Oct 2024 13:34:09 -0700 Subject: [PATCH] [v17] Web/Teleterm: add support for requesting for kube namespaces (#48015) * Web: add support for requesting for kube namespaces * Teleterm: add support for access requesting kube namespaces (#47347) --- web/packages/design/src/DataTable/Table.tsx | 28 +- web/packages/design/src/DataTable/types.ts | 8 + web/packages/design/src/Link/Link.jsx | 1 - .../NewRequest/CheckableOption.tsx | 48 +++ .../NewRequest/RequestCheckout/CrossIcon.tsx | 58 +++ .../RequestCheckout/KubeNamespaceSelector.tsx | 211 ++++++++++ .../RequestCheckout/RequestCheckout.story.tsx | 21 + .../RequestCheckout/RequestCheckout.test.tsx | 2 + .../RequestCheckout/RequestCheckout.tsx | 385 ++++++++++++------ .../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 | 61 +++ .../AccessRequests/NewRequest/kube.ts | 94 +++++ .../AccessRequests/NewRequest/resource.ts | 10 +- .../components/AccessRequests/Shared/utils.ts | 3 +- .../components/FieldSelect/FieldSelect.tsx | 52 ++- .../shared/components/FieldSelect/shared.tsx | 14 +- .../services/accessRequests/accessRequests.ts | 4 +- web/packages/shared/utils/text.test.ts | 38 +- web/packages/shared/utils/text.ts | 25 ++ .../teleport/src/AccessRequests/service.ts | 5 +- .../teleport/src/AccessRequests/types.ts | 8 +- web/packages/teleport/src/config.ts | 2 +- .../AccessRequestCheckout.tsx | 205 +++++----- .../useAccessRequestCheckout.test.tsx | 120 ++++++ .../useAccessRequestCheckout.ts | 138 +++++-- .../NewRequest/NewRequest.tsx | 1 + .../NewRequest/useNewRequest.ts | 22 +- .../ui/DocumentCluster/UnifiedResources.tsx | 2 +- .../accessRequestsService.test.ts | 10 +- .../accessRequestsService.ts | 80 +++- 33 files changed, 1374 insertions(+), 302 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 8f3b9bc8bcaa5..d028e1b18a844 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, { ReactNode } from 'react'; +import React, { ReactNode, PropsWithChildren } from 'react'; import { Box, Flex, Indicator, P1, Text } from 'design'; import * as Icons from 'design/Icon'; @@ -108,6 +108,22 @@ export default function Table(props: TableProps) { 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. @@ -125,15 +141,7 @@ export default function Table(props: TableProps) { ); }); - 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 afe803116613a..9f5ec0490653c 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/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