Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8bffec1
feat: add support for state based collapsible list
arunjaindev Sep 27, 2024
4f408af
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-…
arunjaindev Oct 7, 2024
da3edaa
feat: add key for drift in Node
arunjaindev Oct 8, 2024
a2e1a61
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-…
arunjaindev Oct 8, 2024
40330c2
Merge branch 'feat/collapsible-list-state' of https://github.com/devt…
arunjaindev Oct 8, 2024
02b5542
feat: add filter for drifted nodes in status filter button
arunjaindev Oct 9, 2024
df994f6
chore: use enum for drifted node
arunjaindev Oct 9, 2024
9551c44
chore: version bump
arunjaindev Oct 9, 2024
7115262
chore: edit typing for collapsible list
arunjaindev Oct 9, 2024
03ce4a3
Merge branch 'feat/collapsible-list-state' of https://github.com/devt…
arunjaindev Oct 9, 2024
858e259
chore: version bump
arunjaindev Oct 9, 2024
3ddb76c
chore: version bump
arunjaindev Oct 9, 2024
3e119ee
chore: rename Drifted filter to drifted
arunjaindev Oct 10, 2024
69cab58
chore: version bump
arunjaindev Oct 10, 2024
eca0ef1
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-…
arunjaindev Oct 16, 2024
3ec13ae
feat: add flag for config drift feature
arunjaindev Oct 17, 2024
16e71b5
Merge pull request #361 from devtron-labs/feat/config-drift-flag
arunjaindev Oct 17, 2024
4f98578
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-…
arunjaindev Oct 17, 2024
da74177
Merge branch 'feat/collapsible-list-state' of https://github.com/devt…
arunjaindev Oct 17, 2024
5df60eb
Merge branch 'feat/config-drift' of https://github.com/devtron-labs/d…
arunjaindev Oct 17, 2024
4a6ca3d
chore: version bump
arunjaindev Oct 17, 2024
2e4f158
chore: version bump
arunjaindev Oct 17, 2024
387d6e4
fix: hide drift filter when flag is off
arunjaindev Oct 18, 2024
fe512a6
Merge pull request #342 from devtron-labs/feat/config-drift
arunjaindev Oct 21, 2024
d7a667d
Merge branch 'develop' of https://github.com/devtron-labs/devtron-fe-…
arunjaindev Oct 21, 2024
ae14f5c
chore: version bump
arunjaindev Oct 21, 2024
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
116 changes: 78 additions & 38 deletions src/Shared/Components/CollapsibleList/CollapsibleList.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ConditionalWrap } from '@Common/Helper'
import { ReactComponent as ICExpand } from '@Icons/ic-expand.svg'

import { Collapse } from '../Collapse'
import { CollapsibleListProps } from './CollapsibleList.types'
import { CollapsibleListItem, CollapsibleListProps, TabOptions } from './CollapsibleList.types'
import './CollapsibleList.scss'

const renderWithTippy = (tippyProps: TippyProps) => (children: React.ReactElement) => (
Expand All @@ -14,9 +14,80 @@ const renderWithTippy = (tippyProps: TippyProps) => (children: React.ReactElemen
</Tippy>
)

export const CollapsibleList = ({ config, onCollapseBtnClick }: CollapsibleListProps) => {
export const CollapsibleList = <TabType extends TabOptions>({
config,
tabType,
onCollapseBtnClick,
}: CollapsibleListProps<TabType>) => {
const { pathname } = useLocation()

const getTabContent = (item: CollapsibleListItem<TabOptions>) => {
const { title, subtitle, strikeThrough, iconConfig } = item
return (
<>
<div className="flexbox-col flex-grow-1 mw-none">
<span
className={`collapsible__item__title dc__truncate fs-13 lh-20 ${strikeThrough ? 'dc__strike-through' : ''}`}
>
{title}
</span>
{subtitle && <span className="dc__truncate fw-4 lh-1-5 cn-7">{subtitle}</span>}
</div>
{iconConfig && (
<ConditionalWrap
condition={!!iconConfig.tooltipProps}
wrap={renderWithTippy(iconConfig.tooltipProps)}
>
<iconConfig.Icon
{...iconConfig.props}
className={`icon-dim-20 p-2 dc__no-shrink cursor ${iconConfig.props?.className || ''}`}
/>
</ConditionalWrap>
)}
</>
)
}

const getButtonTabItem = (item: CollapsibleListItem<'button'>) => {
const { title, isActive, onClick } = item
return (
<button
key={title}
className={`collapsible__item flexbox dc__align-items-center dc__gap-8 dc__no-decor br-4 py-6 px-8 cursor ${isActive ? 'active' : ''} dc__unset-button-styles w-100`}
onClick={(e) => {
// Prevent navigation to the same page
if (isActive) {
e.preventDefault()
}
onClick?.(e)
}}
type="button"
>
{getTabContent(item)}
</button>
)
}

const getNavLinkTabItem = (item: CollapsibleListItem<'navLink'>) => {
const { title, href, onClick } = item
return (
<NavLink
key={title}
to={href}
className="collapsible__item flexbox dc__align-items-center dc__gap-8 dc__no-decor br-4 py-6 px-8 cursor"
onClick={(e) => {
// Prevent navigation to the same page
if (href === pathname) {
e.preventDefault()
}
onClick?.(e)
}}
>
{getTabContent(item)}
</NavLink>
)
}

return (
<div className="mw-none bcn-0">
{config.map(({ id, header, headerIconConfig, items, noItemsText, isExpanded }) => (
Expand Down Expand Up @@ -60,42 +131,11 @@ export const CollapsibleList = ({ config, onCollapseBtnClick }: CollapsibleListP
</span>
</div>
) : (
items.map(({ title, strikeThrough, href, iconConfig, subtitle, onClick }) => (
<NavLink
key={title}
to={href}
className="collapsible__item flexbox dc__align-items-center dc__gap-8 dc__no-decor br-4 py-6 px-8 cursor"
onClick={(e) => {
// Prevent navigation to the same page
if (href === pathname) {
e.preventDefault()
}
onClick?.(e)
}}
>
<div className="flexbox-col flex-grow-1 mw-none">
<span
className={`collapsible__item__title dc__truncate fs-13 lh-20 ${strikeThrough ? 'dc__strike-through' : ''}`}
>
{title}
</span>
{subtitle && (
<span className="dc__truncate fw-4 lh-1-5 cn-7">{subtitle}</span>
)}
</div>
{iconConfig && (
<ConditionalWrap
condition={!!iconConfig.tooltipProps}
wrap={renderWithTippy(iconConfig.tooltipProps)}
>
<iconConfig.Icon
{...iconConfig.props}
className={`icon-dim-20 p-2 dc__no-shrink cursor ${iconConfig.props?.className || ''}`}
/>
</ConditionalWrap>
)}
</NavLink>
))
items.map((item) =>
tabType === 'button'
? getButtonTabItem(item as CollapsibleListItem<'button'>)
: getNavLinkTabItem(item as CollapsibleListItem<'navLink'>),
)
)}
</div>
</Collapse>
Expand Down
50 changes: 37 additions & 13 deletions src/Shared/Components/CollapsibleList/CollapsibleList.types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
import React from 'react'
import { TippyProps } from '@tippyjs/react'

export interface CollapsibleListItem {
interface ButtonTab {
/**
* Is tab active ( for button tab )
*/
isActive: boolean
/**
* The callback function to handle click events on the button.
*/
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
href?: never
}

interface NavLinkTab {
/**
* The URL of the nav link.
*/
href: string
/**
* The callback function to handle click events on the nav link.
*/
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void
isActive?: never
}

export type TabOptions = 'button' | 'navLink'

type ConditionalTabType<TabType extends TabOptions> = TabType extends 'button' ? ButtonTab : NavLinkTab

export type CollapsibleListItem<TabType extends TabOptions> = ConditionalTabType<TabType> & {
/**
* The title of the list item.
*/
Expand Down Expand Up @@ -31,17 +59,9 @@ export interface CollapsibleListItem {
*/
tooltipProps?: TippyProps
}
/**
* The URL of the nav link.
*/
href?: string
/**
* The callback function to handle click events on the nav link.
*/
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void
}

export interface CollapsibleListConfig {
export interface CollapsibleListConfig<TabType extends 'button' | 'navLink'> {
/**
* The unique identifier for the collapsible list.
*/
Expand Down Expand Up @@ -79,18 +99,22 @@ export interface CollapsibleListConfig {
/**
* An array of items to be displayed in the collapsible list.
*/
items: CollapsibleListItem[]
items: CollapsibleListItem<TabType>[]
/**
* Boolean indicating whether the list is expanded or not.
*/
isExpanded?: boolean
}

export interface CollapsibleListProps {
export interface CollapsibleListProps<TabType extends TabOptions> {
/**
* An array of collapsible list configurations.
*/
config: CollapsibleListConfig[]
config: CollapsibleListConfig<TabType>[]
/**
* Type of tab list: button or navLink
*/
tabType: TabType
/**
* Function to handle the collapse button click event.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,13 @@ export type DeploymentConfigDiffSelectPickerProps =
selectPickerProps: SelectPickerProps
}

export interface DeploymentConfigDiffNavigationItem extends Pick<CollapsibleListItem, 'href' | 'title' | 'onClick'> {
export interface DeploymentConfigDiffNavigationItem
extends Pick<CollapsibleListItem<'navLink'>, 'href' | 'title' | 'onClick'> {
diffState: DeploymentConfigListItem['diffState']
}

export interface DeploymentConfigDiffNavigationCollapsibleItem
extends Pick<CollapsibleListConfig, 'id' | 'header' | 'noItemsText'> {
extends Pick<CollapsibleListConfig<'navLink'>, 'id' | 'header' | 'noItemsText'> {
items: DeploymentConfigDiffNavigationItem[]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,30 @@ export const DeploymentConfigDiffNavigation = ({
}, [collapsibleNavList])

/** Collapsible List Config. */
const collapsibleListConfig = collapsibleNavList.map<CollapsibleListConfig>(({ items, ...resListItem }) => ({
...resListItem,
isExpanded: expandedIds[resListItem.id],
items: items.map<CollapsibleListConfig['items'][0]>(({ diffState, ...resItem }) => ({
...resItem,
strikeThrough: showDetailedDiffState && diffState === DeploymentConfigDiffState.DELETED,
...(!hideDiffState && diffState !== DeploymentConfigDiffState.NO_DIFF
? {
iconConfig: {
Icon: showDetailedDiffState ? diffStateIconMap[diffState] : diffStateIconMap.hasDiff,
tooltipProps: {
content: showDetailedDiffState
? diffStateTooltipTextMap[diffState]
: diffStateTooltipTextMap.hasDiff,
arrow: false,
placement: 'right' as const,
const collapsibleListConfig = collapsibleNavList.map<CollapsibleListConfig<'navLink'>>(
({ items, ...resListItem }) => ({
...resListItem,
isExpanded: expandedIds[resListItem.id],
items: items.map<CollapsibleListConfig<'navLink'>['items'][0]>(({ diffState, ...resItem }) => ({
...resItem,
strikeThrough: showDetailedDiffState && diffState === DeploymentConfigDiffState.DELETED,
...(!hideDiffState && diffState !== DeploymentConfigDiffState.NO_DIFF
? {
iconConfig: {
Icon: showDetailedDiffState ? diffStateIconMap[diffState] : diffStateIconMap.hasDiff,
tooltipProps: {
content: showDetailedDiffState
? diffStateTooltipTextMap[diffState]
: diffStateTooltipTextMap.hasDiff,
arrow: false,
placement: 'right' as const,
},
},
},
}
: {}),
})),
}))
}
: {}),
})),
}),
)

// METHODS
/** Handles collapse button click. */
Expand Down Expand Up @@ -143,7 +145,7 @@ export const DeploymentConfigDiffNavigation = ({
</NavLink>
)
})}
<CollapsibleList config={collapsibleListConfig} onCollapseBtnClick={onCollapseBtnClick} />
<CollapsibleList config={collapsibleListConfig} tabType="navLink" onCollapseBtnClick={onCollapseBtnClick} />
{navHelpText && (
<div className="mt-8 py-6 px-8 flexbox dc__align-items-center dc__gap-8">
<span className="flex p-2 dc__align-self-start">
Expand Down