From d0568c23f4df626bcee7f738b8fdeb47cd02102b Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Thu, 22 May 2025 12:54:57 +0530 Subject: [PATCH 1/6] feat: add spray can icon to the icon library --- src/Assets/IconV2/ic-spray-can.svg | 3 +++ src/Shared/Components/Icon/Icon.tsx | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 src/Assets/IconV2/ic-spray-can.svg diff --git a/src/Assets/IconV2/ic-spray-can.svg b/src/Assets/IconV2/ic-spray-can.svg new file mode 100644 index 000000000..d7ac168eb --- /dev/null +++ b/src/Assets/IconV2/ic-spray-can.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/Shared/Components/Icon/Icon.tsx b/src/Shared/Components/Icon/Icon.tsx index 0a543e5fe..64ab92468 100644 --- a/src/Shared/Components/Icon/Icon.tsx +++ b/src/Shared/Components/Icon/Icon.tsx @@ -136,6 +136,7 @@ import { ReactComponent as ICSortDescending } from '@IconsV2/ic-sort-descending. import { ReactComponent as ICSortable } from '@IconsV2/ic-sortable.svg' import { ReactComponent as ICSparkleColor } from '@IconsV2/ic-sparkle-color.svg' import { ReactComponent as ICSpinny } from '@IconsV2/ic-spinny.svg' +import { ReactComponent as ICSprayCan } from '@IconsV2/ic-spray-can.svg' import { ReactComponent as ICStack } from '@IconsV2/ic-stack.svg' import { ReactComponent as ICStamp } from '@IconsV2/ic-stamp.svg' import { ReactComponent as ICSuccess } from '@IconsV2/ic-success.svg' @@ -298,6 +299,7 @@ export const iconMap = { 'ic-sortable': ICSortable, 'ic-sparkle-color': ICSparkleColor, 'ic-spinny': ICSpinny, + 'ic-spray-can': ICSprayCan, 'ic-stack': ICStack, 'ic-stamp': ICStamp, 'ic-success': ICSuccess, From 59d07cdcf02552a38d758283730f43056c9ad49b Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Thu, 22 May 2025 12:56:27 +0530 Subject: [PATCH 2/6] feat: add taint documentation link to constants --- src/Shared/DocLink/constants.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Shared/DocLink/constants.ts b/src/Shared/DocLink/constants.ts index 9df6d6791..ed342b4c4 100644 --- a/src/Shared/DocLink/constants.ts +++ b/src/Shared/DocLink/constants.ts @@ -33,6 +33,7 @@ export const DOCUMENTATION = { EXTERNAL_SECRET: 'usage/applications/creating-application/secrets#external-secrets', HOME_PAGE: 'https://devtron.ai', KUBE_CONFIG: 'usage/resource-browser#running-kubectl-commands-locally', + TAINT: 'usage/resource-browser#taint-a-node', // Global Configurations GLOBAL_CONFIG_API_TOKEN: 'getting-started/global-configurations/authorization/api-tokens', From b652bdeda0fc6b62f32fdfd1dfc0b30e663e2375 Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Thu, 22 May 2025 13:01:54 +0530 Subject: [PATCH 3/6] chore(version): bump to 1.14.0-pre-1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3f402a30e..8e04875c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.14.0-pre-0", + "version": "1.14.0-pre-1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.14.0-pre-0", + "version": "1.14.0-pre-1", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 733ca4fa2..b627292bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.14.0-pre-0", + "version": "1.14.0-pre-1", "description": "Supporting common component library", "type": "module", "main": "dist/index.js", From dff22de0f6d5f1c14dd37f2a1c6025dfb678e900 Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Fri, 23 May 2025 17:05:39 +0530 Subject: [PATCH 4/6] feat: DynamicDataTable - update handling of autoFocus on new row add, styles update --- .../DynamicDataTable/DynamicDataTable.tsx | 21 +----- .../DynamicDataTable/DynamicDataTableRow.tsx | 68 ++++++++----------- .../Components/DynamicDataTable/styles.scss | 20 +++--- .../Components/DynamicDataTable/types.ts | 14 ++-- .../KeyValueTable/KeyValueTable.component.tsx | 2 + .../KeyValueTable/KeyValueTable.types.ts | 2 +- 6 files changed, 53 insertions(+), 74 deletions(-) diff --git a/src/Shared/Components/DynamicDataTable/DynamicDataTable.tsx b/src/Shared/Components/DynamicDataTable/DynamicDataTable.tsx index 95349fc75..dd6580a52 100644 --- a/src/Shared/Components/DynamicDataTable/DynamicDataTable.tsx +++ b/src/Shared/Components/DynamicDataTable/DynamicDataTable.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useMemo, useState } from 'react' +import { useMemo } from 'react' import { DynamicDataTableHeader } from './DynamicDataTableHeader' import { DynamicDataTableRow } from './DynamicDataTableRow' @@ -24,30 +24,15 @@ import './styles.scss' export const DynamicDataTable = >({ headers, - onRowAdd, ...props }: DynamicDataTableProps) => { - // STATES - const [isAddRowButtonClicked, setIsAddRowButtonClicked] = useState(false) - // CONSTANTS const filteredHeaders = useMemo(() => headers.filter(({ isHidden }) => !isHidden), [headers]) - // HANDLERS - const handleRowAdd = () => { - setIsAddRowButtonClicked(true) - onRowAdd() - } - return (
- - + +
) } diff --git a/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx b/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx index 45b141d80..7b1bb8556 100644 --- a/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx +++ b/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx @@ -14,17 +14,7 @@ * limitations under the License. */ -import { - createElement, - createRef, - Fragment, - ReactElement, - RefObject, - useEffect, - useMemo, - useRef, - useState, -} from 'react' +import { createElement, createRef, Fragment, ReactElement, RefObject, useEffect, useMemo, useRef } from 'react' // eslint-disable-next-line import/no-extraneous-dependencies import { followCursor } from 'tippy.js' @@ -73,8 +63,7 @@ export const DynamicDataTableRow = ) => { // CONSTANTS const isFirstRowEmpty = headers.every(({ key }) => !rows[0]?.data[key].value) @@ -88,25 +77,18 @@ export const DynamicDataTableRow = >>>() + const shouldAutoFocusNewRowRef = useRef(shouldAutoFocusOnMount) + const cellRef = useRef>>>(null) if (!cellRef.current) { - cellRef.current = rows.reduce( - (acc, curr) => ({ - ...acc, - [curr.id]: headers.reduce((headerAcc, { key }) => ({ ...headerAcc, [key]: createRef() }), {}), - }), - {}, - ) + cellRef.current = rows.reduce((acc, curr) => { + acc[curr.id] = headers.reduce((headerAcc, { key }) => ({ ...headerAcc, [key]: createRef() }), {}) + return acc + }, {}) } const rowIds = useMemo(() => rows.map(({ id }) => id), [rows]) useEffect(() => { - setIsRowAdded(rows.length > 0 && Object.keys(cellRef.current).length < rows.length) - // When a new row is added, we create references for its cells. // This logic ensures that references are created only for the newly added row, while retaining the existing references. const updatedCellRef = rowIds.reduce((acc, curr) => { @@ -121,18 +103,6 @@ export const DynamicDataTableRow = { - if (isAddRowButtonClicked && isRowAdded) { - // Using the below logic to ensure the cell is focused after row addition. - const cell = cellRef.current[rows[0].id][focusableFieldKey || headers[0].key].current - if (cell) { - cell.focus() - setIsRowAdded(false) - setIsAddRowButtonClicked(false) - } - } - }, [isRowAdded, isAddRowButtonClicked]) - // METHODS const onChange = (row: DynamicDataTableRowType, key: K) => @@ -163,14 +133,30 @@ export const DynamicDataTableRow = , key: K) => { + const renderCellContent = (row: DynamicDataTableRowType, key: K, index: number) => { const isDisabled = readOnly || row.data[key].disabled + const autoFocus = + shouldAutoFocusNewRowRef.current && key === (focusableFieldKey ?? headers[0].key) && index === 0 + + // This logic ensures only newly added rows get autofocus. + // On the initial mount, all rows are treated as new, so autofocus is enabled. + // After the first render, when cellRef is set (DOM rendered), we set shouldAutoFocusNewRowRef to true, + // so autofocus is applied only to the correct cell in any subsequently added row. + if ( + !shouldAutoFocusOnMount && + !shouldAutoFocusNewRowRef.current && + index === 0 && + cellRef?.current?.[row.id]?.[key].current + ) { + shouldAutoFocusNewRowRef.current = true + } switch (row.data[key].type) { case DynamicDataTableRowDataType.DROPDOWN: return (
+ autoFocus={autoFocus} {...row.data[key].props} inputId={`data-table-${row.id}-${key}-cell`} classNamePrefix="dynamic-data-table__cell__select-picker" @@ -193,6 +179,7 @@ export const DynamicDataTableRow = {renderCellIcon(row, key, true)} - {renderCellContent(row, key)} + {renderCellContent(row, key, index)} {renderAsterisk(row, key)} {renderCellIcon(row, key)} {renderErrorMessages(row, key)} diff --git a/src/Shared/Components/DynamicDataTable/styles.scss b/src/Shared/Components/DynamicDataTable/styles.scss index bea6f38b1..015d955f1 100644 --- a/src/Shared/Components/DynamicDataTable/styles.scss +++ b/src/Shared/Components/DynamicDataTable/styles.scss @@ -69,21 +69,21 @@ height: 36px; width: 100%; background: inherit; - - &--add { - resize: none; - border-radius: 4px; - outline: none; - } } &__cell { min-width: 0; - &__select-picker__control { - gap: 6px !important; - padding: 8px !important; - max-height: 160px !important; + &__select-picker { + &__control { + gap: 6px !important; + padding: 8px !important; + max-height: 160px !important; + } + + &__single-value { + font-weight: 400 !important; + } } &__select-picker-text-area { diff --git a/src/Shared/Components/DynamicDataTable/types.ts b/src/Shared/Components/DynamicDataTable/types.ts index 3e9574cb1..a7b8b3981 100644 --- a/src/Shared/Components/DynamicDataTable/types.ts +++ b/src/Shared/Components/DynamicDataTable/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { DetailedHTMLProps, Dispatch, ReactElement, ReactNode, SetStateAction } from 'react' +import { DetailedHTMLProps, ReactElement, ReactNode } from 'react' import { ResizableTagTextAreaProps } from '@Common/CustomTagSelector' import { UseStateFiltersReturnType } from '@Common/Hooks' @@ -228,6 +228,12 @@ export type DynamicDataTableProps> @@ -261,7 +267,5 @@ export interface DynamicDataTableRowProps { - isAddRowButtonClicked: boolean - setIsAddRowButtonClicked: Dispatch> -} + | 'shouldAutoFocusOnMount' + > {} diff --git a/src/Shared/Components/KeyValueTable/KeyValueTable.component.tsx b/src/Shared/Components/KeyValueTable/KeyValueTable.component.tsx index e43a693a9..6b11c369a 100644 --- a/src/Shared/Components/KeyValueTable/KeyValueTable.component.tsx +++ b/src/Shared/Components/KeyValueTable/KeyValueTable.component.tsx @@ -41,6 +41,7 @@ export const KeyValueTable = ({ headerComponent, onChange, isAdditionNotAllowed, + shouldAutoFocusOnMount, readOnly, showError, validationSchema: parentValidationSchema, @@ -180,6 +181,7 @@ export const KeyValueTable = ({ headerComponent={headerComponent} readOnly={readOnly} isAdditionNotAllowed={isAdditionNotAllowed} + shouldAutoFocusOnMount={shouldAutoFocusOnMount} sortingConfig={{ sortBy, sortOrder, diff --git a/src/Shared/Components/KeyValueTable/KeyValueTable.types.ts b/src/Shared/Components/KeyValueTable/KeyValueTable.types.ts index fff70a1b0..a245542b7 100644 --- a/src/Shared/Components/KeyValueTable/KeyValueTable.types.ts +++ b/src/Shared/Components/KeyValueTable/KeyValueTable.types.ts @@ -85,7 +85,7 @@ export interface KeyValueTableData extends Pick { */ export type KeyValueTableProps = Pick< DynamicDataTableProps, - 'isAdditionNotAllowed' | 'readOnly' | 'headerComponent' + 'isAdditionNotAllowed' | 'readOnly' | 'headerComponent' | 'shouldAutoFocusOnMount' > & { /** * The label for the table header. From 344b6841a04bb7765ab09d11709aed1c01b0ba9c Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Fri, 23 May 2025 17:54:46 +0530 Subject: [PATCH 5/6] feat: DynamicDataTable - update error and delete row icon --- .../Components/DynamicDataTable/DynamicDataTableRow.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx b/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx index 7b1bb8556..3b1c438e4 100644 --- a/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx +++ b/src/Shared/Components/DynamicDataTable/DynamicDataTableRow.tsx @@ -18,7 +18,6 @@ import { createElement, createRef, Fragment, ReactElement, RefObject, useEffect, // eslint-disable-next-line import/no-extraneous-dependencies import { followCursor } from 'tippy.js' -import { ReactComponent as ICClose } from '@Icons/ic-close.svg' import { ResizableTagTextArea } from '@Common/CustomTagSelector' import { ConditionalWrap } from '@Common/Helper' import { Tooltip } from '@Common/Tooltip' @@ -26,6 +25,7 @@ import { ComponentSizeType } from '@Shared/constants' import { Button, ButtonStyleType, ButtonVariantType } from '../Button' import { FileUpload } from '../FileUpload' +import { Icon } from '../Icon' import { getSelectPickerOptionByValue, SelectPicker, @@ -271,8 +271,8 @@ export const DynamicDataTableRow = ( -
- +
+

{errorMessage}

) @@ -371,7 +371,7 @@ export const DynamicDataTableRow = } + icon={} disabled={disableDeleteRow || row.disableDelete} onClick={onDelete(row)} variant={ButtonVariantType.borderLess} From 803de19c61229b8c2bd02aaa6aec5d9ee6650bb5 Mon Sep 17 00:00:00 2001 From: Rohit Raj Date: Mon, 26 May 2025 18:32:35 +0530 Subject: [PATCH 6/6] chore(version): bump to 1.14.1-pre-3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9438c49e9..792a15a00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.14.1-pre-2", + "version": "1.14.1-pre-3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.14.1-pre-2", + "version": "1.14.1-pre-3", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index a1816526f..83e709071 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@devtron-labs/devtron-fe-common-lib", - "version": "1.14.1-pre-2", + "version": "1.14.1-pre-3", "description": "Supporting common component library", "type": "module", "main": "dist/index.js",