Skip to content

feat: add tree view component #803

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 35 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
67af0c3
feat: refactor ActionMenuItem and add TrailingItem component for impr…
AbhishekA1509 Jun 23, 2025
0c20da6
feat: add base structure for TreeView
AbhishekA1509 Jun 23, 2025
73acec4
fix: css alignment for dividers
AbhishekA1509 Jun 25, 2025
739b759
feat: make variant prop optional in TrailingItemProps and improve Tre…
AbhishekA1509 Jun 25, 2025
439a4c6
feat: add mode prop to TreeViewProps for navigation and form modes, a…
AbhishekA1509 Jun 26, 2025
5eba693
feat: update TreeViewProps to support optional depth, flatNodeList, a…
AbhishekA1509 Jun 27, 2025
9367515
feat: enhance TreeView component with selected state styling and refa…
AbhishekA1509 Jun 27, 2025
4be78b7
feat: refactor Tooltip component and introduce TreeViewNodeContent fo…
AbhishekA1509 Jun 30, 2025
d0fc33f
feat: integrate framer-motion for animated transitions in TreeView co…
AbhishekA1509 Jun 30, 2025
7db4a2d
feat: copilot review
AbhishekA1509 Jun 30, 2025
6aa852b
feat: add click handlers for TreeView node items to manage button and…
AbhishekA1509 Jun 30, 2025
029324c
feat: update TreeView and related components to support selection sta…
AbhishekA1509 Jul 1, 2025
fa6b56e
feat: enhance Sidebar component to support TreeView structure and add…
AbhishekA1509 Jul 1, 2025
6445985
feat: refactor TreeView component to support uncontrolled mode and up…
AbhishekA1509 Jul 1, 2025
1df23b8
Merge branch 'fix/rb-table' of https://github.com/devtron-labs/devtro…
AbhishekA1509 Jul 1, 2025
4e9118d
feat: add variant support to TreeView for customizable background and…
AbhishekA1509 Jul 1, 2025
e9355d7
feat: add scroll to selected item functionality in TreeView component
AbhishekA1509 Jul 2, 2025
6cb2706
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-…
AbhishekA1509 Jul 2, 2025
5e6c67d
feat: add defaultExpandedMap prop to TreeView and update state initia…
AbhishekA1509 Jul 2, 2025
577b204
fix: tabbing
Elessar1802 Jul 2, 2025
2363357
revert: version in k8s resource detail & list
Elessar1802 Jul 2, 2025
d3c6788
Merge branch 'release-candidate-v0.39.0' of github.com:devtron-labs/d…
Elessar1802 Jul 2, 2025
d31006e
feat: remove isExpanded property from K8SObjectBaseType interface
AbhishekA1509 Jul 2, 2025
276bacd
chore: bump version to 1.16.0-pre-8 in package.json and package-lock.…
AbhishekA1509 Jul 2, 2025
8e4707e
Merge pull request #806 from devtron-labs/feat/rb-table
AbhishekA1509 Jul 2, 2025
9a0f92c
fix: WorkflowOptionsModal - add check for linkedCDSourceVariant
RohitRaj011 Jul 3, 2025
c190402
chore(version): bump to 1.16.0-pre-9
RohitRaj011 Jul 3, 2025
321c03f
Merge pull request #807 from devtron-labs/fix/workflow-options-modal
RohitRaj011 Jul 3, 2025
181f899
fix: node-detail route in RB
Elessar1802 Jul 3, 2025
fa34d9c
Merge branch 'release-candidate-v0.39.0' of github.com:devtron-labs/d…
Elessar1802 Jul 3, 2025
383d046
chore: update common-lib version
Elessar1802 Jul 3, 2025
bb07d3d
Merge pull request #808 from devtron-labs/feat/rb-table
Elessar1802 Jul 3, 2025
443d6e4
feat: add generic support for DataAttributeType in TreeView component…
AbhishekA1509 Jul 3, 2025
494c363
Merge branch 'release-candidate-v0.39.0' of https://github.com/devtro…
AbhishekA1509 Jul 3, 2025
f5469f0
feat: enhance TreeView component with controlled state management and…
AbhishekA1509 Jul 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@devtron-labs/devtron-fe-common-lib",
"version": "1.16.0-pre-7",
"version": "1.16.0-pre-10",
"description": "Supporting common component library",
"type": "module",
"main": "dist/index.js",
Expand Down
2 changes: 2 additions & 0 deletions src/Common/Hooks/UseRegisterShortcut/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const KEYBOARD_KEYS_MAP = {
X: 'X',
A: 'A',
N: 'N',
S: 'S',
'/': '/',
Escape: 'Esc',
Enter: '↩',
ArrowLeft: '←',
Expand Down
18 changes: 3 additions & 15 deletions src/Common/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
* limitations under the License.
*/

import { cloneElement, useState } from 'react'
import { cloneElement } from 'react'
import TippyJS from '@tippyjs/react'

import { SUB_PIXEL_ERROR } from './constants'
import ShortcutKeyComboTooltipContent from './ShortcutKeyComboTooltipContent'
import { TooltipProps } from './types'
import useIsTextTruncated from './UseIsTextTruncated'

import './styles.scss'

Expand All @@ -32,19 +32,7 @@ const Tooltip = ({
children: child,
...rest
}: TooltipProps) => {
const [isTextTruncated, setIsTextTruncated] = useState(false)

const handleMouseEnterEvent: React.MouseEventHandler = (event) => {
const { currentTarget: node } = event
const isTextOverflowing =
node.scrollWidth > node.clientWidth + SUB_PIXEL_ERROR ||
node.scrollHeight > node.clientHeight + SUB_PIXEL_ERROR
if (isTextOverflowing && !isTextTruncated) {
setIsTextTruncated(true)
} else if (!isTextOverflowing && isTextTruncated) {
setIsTextTruncated(false)
}
}
const { isTextTruncated, handleMouseEnterEvent } = useIsTextTruncated()

const showTooltipWhenShortcutKeyComboProvided =
!!shortcutKeyCombo && (alwaysShowTippyOnHover === undefined || alwaysShowTippyOnHover)
Expand Down
26 changes: 26 additions & 0 deletions src/Common/Tooltip/UseIsTextTruncated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useState } from 'react'

import { SUB_PIXEL_ERROR } from './constants'

const useIsTextTruncated = () => {
const [isTextTruncated, setIsTextTruncated] = useState(false)

const handleMouseEnterEvent: React.MouseEventHandler = (event) => {
const { currentTarget: node } = event
const isTextOverflowing =
node.scrollWidth > node.clientWidth + SUB_PIXEL_ERROR ||
node.scrollHeight > node.clientHeight + SUB_PIXEL_ERROR
if (isTextOverflowing && !isTextTruncated) {
setIsTextTruncated(true)
} else if (!isTextOverflowing && isTextTruncated) {
setIsTextTruncated(false)
}
}

return {
isTextTruncated,
handleMouseEnterEvent,
}
}

export default useIsTextTruncated
1 change: 1 addition & 0 deletions src/Common/Tooltip/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
export { TOOLTIP_CONTENTS } from './constants'
export { default as Tooltip } from './Tooltip'
export type { TooltipProps } from './types'
export { default as useIsTextTruncated } from './UseIsTextTruncated'
1 change: 0 additions & 1 deletion src/Pages/ResourceBrowser/ResourceBrowser.Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export interface ApiResourceType {

export interface K8SObjectBaseType {
name: string
isExpanded: boolean
}

interface K8sRequestResourceIdentifierType {
Expand Down
8 changes: 3 additions & 5 deletions src/Pages/ResourceBrowser/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,14 @@ export const NODE_DRAIN_OPTIONS_CHECKBOX_CONFIG: {
export const GVK_FILTER_KIND_QUERY_PARAM_KEY = 'gvkFilterKind'
export const GVK_FILTER_API_VERSION_QUERY_PARAM_KEY = 'gvkFilterApiVersion'

export const DUMMY_RESOURCE_GVK_VERSION = 'v1'

export const RESOURCE_BROWSER_ROUTES = {
OVERVIEW: `${URLS.RESOURCE_BROWSER}/:clusterId/overview`,
MONITORING_DASHBOARD: `${URLS.RESOURCE_BROWSER}/:clusterId/monitoring-dashboard`,
TERMINAL: `${URLS.RESOURCE_BROWSER}/:clusterId/terminal`,
CLUSTER_UPGRADE: `${URLS.RESOURCE_BROWSER}/:clusterId/cluster-upgrade`,
NODE_DETAIL: `${URLS.RESOURCE_BROWSER}/:clusterId/node/:name`,
K8S_RESOURCE_DETAIL: `${URLS.RESOURCE_BROWSER}/:clusterId/:namespace/:kind/:group/:version/:name`,
K8S_RESOURCE_LIST: `${URLS.RESOURCE_BROWSER}/:clusterId/:kind/:group/:version`,
NODE_DETAIL: `${URLS.RESOURCE_BROWSER}/:clusterId/node/detail/:name`,
K8S_RESOURCE_DETAIL: `${URLS.RESOURCE_BROWSER}/:clusterId/:namespace/:kind/:group/:name`,
K8S_RESOURCE_LIST: `${URLS.RESOURCE_BROWSER}/:clusterId/:kind/:group`,
RESOURCE_RECOMMENDER: `${URLS.RESOURCE_BROWSER}/:clusterId/resource-recommender`,
} as const

Expand Down
62 changes: 3 additions & 59 deletions src/Shared/Components/ActionMenu/ActionMenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ import { LegacyRef, MouseEvent, Ref } from 'react'
import { Link } from 'react-router-dom'

import { Tooltip } from '@Common/Tooltip'
import { ComponentSizeType } from '@Shared/constants'

import { Button, ButtonProps, ButtonVariantType } from '../Button'
import { Icon } from '../Icon'
import { NumbersCount } from '../NumbersCount'
import { getTooltipProps } from '../SelectPicker/common'
import { DTSwitch, DTSwitchProps } from '../Switch'
import { ActionMenuItemProps, ActionMenuItemType } from './types'
import { TrailingItem } from '../TrailingItem'
import { ActionMenuItemProps } from './types'

const COMMON_ACTION_MENU_ITEM_CLASS = 'w-100 flex left top dc__gap-8 py-6 px-8'

Expand Down Expand Up @@ -48,24 +45,6 @@ export const ActionMenuItem = <T extends string | number>({
onClick(item, e)
}

const handleTrailingSwitchChange =
({ type: trailingItemType, config }: ActionMenuItemType<T>['trailingItem']): DTSwitchProps['onChange'] =>
(e) => {
if (trailingItemType === 'switch') {
e.stopPropagation()
config.onChange(e)
}
}

const handleTrailingButtonClick =
({ type: trailingItemType, config }: ActionMenuItemType<T>['trailingItem']): ButtonProps['onClick'] =>
(e) => {
e.stopPropagation()
if (trailingItemType === 'button' && config.onClick) {
config.onClick(e)
}
}

// RENDERERS
const renderIcon = (iconProps: typeof startIcon) =>
iconProps && (
Expand All @@ -79,42 +58,7 @@ export const ActionMenuItem = <T extends string | number>({
return null
}

const { type: trailingItemType, config } = trailingItem

switch (trailingItemType) {
case 'icon':
return renderIcon(config)
case 'text': {
const { value, icon } = config
return (
<span className="flex dc__gap-2 mt-2">
<span className="fs-12 lh-1-5 fw-4 cn-7">{value}</span>
{icon && <Icon name={icon.name} color={icon.color || (isNegativeType ? 'R500' : 'N700')} />}
</span>
)
}
case 'counter':
return <NumbersCount count={config.value} />
case 'switch':
return (
<DTSwitch
{...config}
onChange={handleTrailingSwitchChange(trailingItem)}
size={ComponentSizeType.small}
/>
)
case 'button':
return (
<Button
{...(config as ButtonProps)}
onClick={handleTrailingButtonClick(trailingItem)}
variant={ButtonVariantType.borderLess}
size={ComponentSizeType.xxs}
/>
)
default:
return null
}
return <TrailingItem {...trailingItem} variant={type} />
}

const renderContent = () => (
Expand Down
51 changes: 2 additions & 49 deletions src/Shared/Components/ActionMenu/types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { LegacyRef, MouseEvent, ReactElement, Ref } from 'react'
import { LegacyRef, MouseEvent, Ref } from 'react'
import { LinkProps } from 'react-router-dom'

import { OmitNever } from '@Shared/types'

import { ButtonProps } from '../Button'
import { IconsProps } from '../Icon'
import { NumbersCountProps } from '../NumbersCount'
import { PopoverProps, UsePopoverProps } from '../Popover'
import { SelectPickerOptionType, SelectPickerProps } from '../SelectPicker'
import { DTSwitchProps } from '../Switch'
import { ActionMenuItemIconType, TrailingItemType } from '../TrailingItem'

type ConditionalActionMenuComponentType =
| {
Expand All @@ -32,48 +27,6 @@ type ConditionalActionMenuComponentType =
href?: never
}

type ActionMenuItemIconType = Pick<IconsProps, 'name'> & {
/** @default 'N800' */
color?: IconsProps['color']
}

type TrailingItemType =
| {
type: 'icon'
config: ActionMenuItemIconType
}
| {
type: 'text'
config: {
value: string
icon?: ActionMenuItemIconType
}
}
| {
type: 'counter'
config: {
value: NumbersCountProps['count']
}
}
| {
type: 'switch'
config: Pick<
DTSwitchProps,
| 'ariaLabel'
| 'isChecked'
| 'indeterminate'
| 'isDisabled'
| 'isLoading'
| 'name'
| 'onChange'
| 'tooltipContent'
>
}
| {
type: 'button'
config: OmitNever<Omit<Extract<ButtonProps, { icon: ReactElement }>, 'size' | 'variant'>>
}

export type ActionMenuItemType<T extends string | number = string | number> = Omit<
SelectPickerOptionType,
'label' | 'value' | 'endIcon' | 'startIcon'
Expand Down
4 changes: 2 additions & 2 deletions src/Shared/Components/CICDHistory/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { DATE_TIME_FORMATS, URLS } from '@Common/Constants'
import { DeploymentAppTypes } from '@Common/Types'
import { ALL_RESOURCE_KIND_FILTER } from '@Shared/constants'
import { isTimeStringAvailable } from '@Shared/Helpers'
import { DUMMY_RESOURCE_GVK_VERSION, K8S_EMPTY_GROUP } from '@Pages/ResourceBrowser'
import { K8S_EMPTY_GROUP } from '@Pages/ResourceBrowser'

import { DeploymentStatusBreakdownItemType, Node, ResourceKindType, WorkflowStatusEnum } from '../../types'
import { Icon } from '../Icon'
Expand Down Expand Up @@ -234,7 +234,7 @@ export const getHistoryItemStatusIconFromWorkflowStages = (
}

export const getWorkerPodBaseUrl = (clusterId: number = DEFAULT_CLUSTER_ID, podNamespace: string = DEFAULT_NAMESPACE) =>
`${URLS.RESOURCE_BROWSER}/${clusterId}/${podNamespace}/pod/${K8S_EMPTY_GROUP}/${DUMMY_RESOURCE_GVK_VERSION}`
`${URLS.RESOURCE_BROWSER}/${clusterId}/${podNamespace}/pod/${K8S_EMPTY_GROUP}`

export const getWorkflowNodeStatusTitle = (status: string) => {
if (!status) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ const renderWithTippy = (tippyProps: TippyProps) => (children: React.ReactElemen
</Tippy>
)

/**
* @deprecated - Please use `TreeView` component instead.
*/
export const CollapsibleList = <TabType extends TabOptions>({
config,
tabType,
Expand Down
Loading