Skip to content

Commit 847320c

Browse files
committed
refactor: simplify Sidebar component by extracting tree view node logic into utility functions
1 parent b795525 commit 847320c

File tree

2 files changed

+117
-103
lines changed

2 files changed

+117
-103
lines changed

src/components/ResourceBrowser/ResourceList/Sidebar.tsx

Lines changed: 4 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,24 @@ import DOMPurify from 'dompurify'
2222

2323
import {
2424
capitalizeFirstLetter,
25-
GVKType,
2625
highlightSearchText,
2726
K8S_EMPTY_GROUP,
2827
Nodes,
2928
NodeType,
3029
ReactSelectInputAction,
3130
RESOURCE_BROWSER_ROUTES,
32-
TreeHeading,
33-
TreeItem,
3431
TreeNode,
3532
TreeView,
3633
URL_FILTER_KEYS,
3734
useRegisterShortcut,
3835
} from '@devtron-labs/devtron-fe-common-lib'
3936

40-
import { AggregationKeys } from '../../app/types'
41-
import { KIND_SEARCH_COMMON_STYLES, ResourceBrowserTabsId, SIDEBAR_KEYS } from '../Constants'
37+
import { KIND_SEARCH_COMMON_STYLES, ResourceBrowserTabsId } from '../Constants'
4238
import { K8sObjectOptionType, RBResourceSidebarDataAttributeType, SidebarType } from '../Types'
4339
import { convertK8sObjectMapToOptionsList, convertResourceGroupListToK8sObjectList } from '../Utils'
4440
import { KindSearchClearIndicator, KindSearchValueContainer } from './ResourceList.component'
4541
import { K8sResourceListURLParams } from './types'
42+
import { getRBSidebarTreeViewNodeId, getRBSidebarTreeViewNodes } from './utils'
4643

4744
const Sidebar = ({ apiResources, selectedResource, updateK8sResourceTab, updateTabLastSyncMoment }: SidebarType) => {
4845
const { registerShortcut, unregisterShortcut } = useRegisterShortcut()
@@ -199,102 +196,7 @@ const Sidebar = ({ apiResources, selectedResource, updateK8sResourceTab, updateT
199196

200197
const noOptionsMessage = () => 'No matching kind'
201198

202-
const getTreeViewNodeId = ({ Group, Version, Kind }: GVKType) =>
203-
`${Group.toLowerCase()}-${Version.toLowerCase()}-${Kind.toLowerCase()}`
204-
const getTreeViewNodeDataAttributes = ({ Group, Version, Kind }: GVKType): RBResourceSidebarDataAttributeType => ({
205-
'data-group': Group.toLowerCase(),
206-
'data-version': Version.toLowerCase(),
207-
'data-kind': Kind.toLowerCase(),
208-
})
209-
210-
const getTreeViewNodes = () => {
211-
const fixedNodes: TreeNode<RBResourceSidebarDataAttributeType>[] = (
212-
[
213-
!!list?.size &&
214-
!!list.get(AggregationKeys.Nodes) && {
215-
type: 'item',
216-
title: SIDEBAR_KEYS.nodes,
217-
id: getTreeViewNodeId(SIDEBAR_KEYS.nodeGVK),
218-
dataAttributes: getTreeViewNodeDataAttributes(SIDEBAR_KEYS.nodeGVK),
219-
},
220-
221-
!!list?.size &&
222-
!!list.get(AggregationKeys.Events) && {
223-
type: 'item',
224-
title: SIDEBAR_KEYS.events,
225-
id: getTreeViewNodeId(SIDEBAR_KEYS.eventGVK),
226-
dataAttributes: getTreeViewNodeDataAttributes(SIDEBAR_KEYS.eventGVK),
227-
},
228-
229-
!!list?.size &&
230-
!!list.get(AggregationKeys.Namespaces) && {
231-
type: 'item',
232-
title: SIDEBAR_KEYS.namespaces,
233-
id: getTreeViewNodeId(SIDEBAR_KEYS.namespaceGVK),
234-
dataAttributes: getTreeViewNodeDataAttributes(SIDEBAR_KEYS.namespaceGVK),
235-
},
236-
] satisfies TreeNode<RBResourceSidebarDataAttributeType>[]
237-
).filter(Boolean)
238-
239-
const dynamicNodesList = list?.size
240-
? [...list.values()].filter(
241-
(k8sObject) =>
242-
!(
243-
k8sObject.name === AggregationKeys.Events ||
244-
k8sObject.name === AggregationKeys.Namespaces ||
245-
k8sObject.name === AggregationKeys.Nodes
246-
),
247-
)
248-
: []
249-
250-
const dynamicNodes = dynamicNodesList.map<TreeHeading<RBResourceSidebarDataAttributeType>>((k8sObject) => ({
251-
id: `${k8sObject.name}-parent`,
252-
type: 'heading',
253-
title: k8sObject.name,
254-
items: [...k8sObject.child.entries()]
255-
.filter(([key]) => {
256-
const keyLowerCased = key.toLowerCase()
257-
return !(
258-
keyLowerCased === 'node' ||
259-
keyLowerCased === SIDEBAR_KEYS.namespaceGVK.Kind.toLowerCase() ||
260-
keyLowerCased === SIDEBAR_KEYS.eventGVK.Kind.toLowerCase()
261-
)
262-
})
263-
.map<TreeNode<RBResourceSidebarDataAttributeType>>(([key, value]) => {
264-
if (value.data.length === 1) {
265-
const childData = value.data[0]
266-
const nodeName = childData.gvk.Kind
267-
return {
268-
type: 'item',
269-
title: nodeName,
270-
id: getTreeViewNodeId(childData.gvk),
271-
dataAttributes: getTreeViewNodeDataAttributes(childData.gvk),
272-
} satisfies TreeItem<RBResourceSidebarDataAttributeType>
273-
}
274-
275-
return {
276-
type: 'heading',
277-
id: `${k8sObject.name}/${key}-child`,
278-
title: key,
279-
dataAttributes: null,
280-
items: value.data.map<TreeItem<RBResourceSidebarDataAttributeType>>((childData) => {
281-
const nodeName = childData.gvk.Group ? childData.gvk.Group : childData.gvk.Kind
282-
283-
return {
284-
type: 'item',
285-
title: nodeName,
286-
id: getTreeViewNodeId(childData.gvk),
287-
dataAttributes: getTreeViewNodeDataAttributes(childData.gvk),
288-
}
289-
}),
290-
} satisfies TreeHeading<RBResourceSidebarDataAttributeType>
291-
}),
292-
}))
293-
294-
return fixedNodes.concat(dynamicNodes)
295-
}
296-
297-
const treeViewNodes = getTreeViewNodes()
199+
const treeViewNodes = getRBSidebarTreeViewNodes(list)
298200

299201
return (
300202
<div className="w-250 dc__no-shrink dc__overflow-hidden flexbox-col">
@@ -331,7 +233,7 @@ const Sidebar = ({ apiResources, selectedResource, updateK8sResourceTab, updateT
331233
<div className="dc__overflow-auto flexbox-col flex-grow-1 dc__border-top-n1 p-8 dc__user-select-none">
332234
<TreeView<RBResourceSidebarDataAttributeType>
333235
nodes={treeViewNodes}
334-
selectedId={getTreeViewNodeId(
236+
selectedId={getRBSidebarTreeViewNodeId(
335237
selectedResource?.gvk || { Group: '', Version: '', Kind: '' as NodeType },
336238
)}
337239
onSelect={handleTreeViewNodeSelect}

src/components/ResourceBrowser/ResourceList/utils.tsx

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@
1616

1717
import {
1818
ClusterDetail,
19+
GVKType,
1920
logExceptionToSentry,
2021
numberComparatorBySortOrder,
2122
RESOURCE_BROWSER_ROUTES,
2223
stringComparatorBySortOrder,
24+
TreeHeading,
25+
TreeItem,
26+
TreeNode,
2327
versionComparatorBySortOrder,
2428
} from '@devtron-labs/devtron-fe-common-lib'
2529

30+
import { AggregationKeys } from '@Components/app/types'
2631
import { importComponentFromFELibrary, k8sStyledAgeToSeconds, sortObjectArrayAlphabetically } from '@Components/common'
2732
import { UseTabsReturnType } from '@Components/common/DynamicTabs/types'
2833

@@ -35,7 +40,14 @@ import {
3540
TARGET_K8S_VERSION_SEARCH_KEY,
3641
UPGRADE_CLUSTER_CONSTANTS,
3742
} from '../Constants'
38-
import { ClusterOptionType, K8SResourceListType, NODE_SEARCH_KEYS, ShowAIButtonConfig } from '../Types'
43+
import {
44+
ClusterOptionType,
45+
K8SResourceListType,
46+
NODE_SEARCH_KEYS,
47+
RBResourceSidebarDataAttributeType,
48+
ShowAIButtonConfig,
49+
} from '../Types'
50+
import { convertResourceGroupListToK8sObjectList } from '../Utils'
3951
import { K8sResourceListFilterType, ResourceListUrlFiltersType } from './types'
4052

4153
const getFilterOptionsFromSearchParams = importComponentFromFELibrary(
@@ -323,3 +335,103 @@ export const getTabIdForTab = (
323335
const functionParams = getTabIdParamsForPath(path, params)
324336
return functionParams ? getTabId(...functionParams) : null
325337
}
338+
339+
export const getRBSidebarTreeViewNodeId = ({ Group, Version, Kind }: GVKType) =>
340+
`${Group.toLowerCase()}-${Version.toLowerCase()}-${Kind.toLowerCase()}`
341+
342+
const getRBSidebarTreeViewNodeDataAttributes = ({
343+
Group,
344+
Version,
345+
Kind,
346+
}: GVKType): RBResourceSidebarDataAttributeType => ({
347+
'data-group': Group.toLowerCase(),
348+
'data-version': Version.toLowerCase(),
349+
'data-kind': Kind.toLowerCase(),
350+
})
351+
352+
export const getRBSidebarTreeViewNodes = (list: ReturnType<typeof convertResourceGroupListToK8sObjectList>) => {
353+
const fixedNodes: TreeNode<RBResourceSidebarDataAttributeType>[] = (
354+
[
355+
!!list?.size &&
356+
!!list.get(AggregationKeys.Nodes) && {
357+
type: 'item',
358+
title: SIDEBAR_KEYS.nodes,
359+
id: getRBSidebarTreeViewNodeId(SIDEBAR_KEYS.nodeGVK),
360+
dataAttributes: getRBSidebarTreeViewNodeDataAttributes(SIDEBAR_KEYS.nodeGVK),
361+
},
362+
363+
!!list?.size &&
364+
!!list.get(AggregationKeys.Events) && {
365+
type: 'item',
366+
title: SIDEBAR_KEYS.events,
367+
id: getRBSidebarTreeViewNodeId(SIDEBAR_KEYS.eventGVK),
368+
dataAttributes: getRBSidebarTreeViewNodeDataAttributes(SIDEBAR_KEYS.eventGVK),
369+
},
370+
371+
!!list?.size &&
372+
!!list.get(AggregationKeys.Namespaces) && {
373+
type: 'item',
374+
title: SIDEBAR_KEYS.namespaces,
375+
id: getRBSidebarTreeViewNodeId(SIDEBAR_KEYS.namespaceGVK),
376+
dataAttributes: getRBSidebarTreeViewNodeDataAttributes(SIDEBAR_KEYS.namespaceGVK),
377+
},
378+
] satisfies TreeNode<RBResourceSidebarDataAttributeType>[]
379+
).filter(Boolean)
380+
381+
const dynamicNodesList = list?.size
382+
? [...list.values()].filter(
383+
(k8sObject) =>
384+
!(
385+
k8sObject.name === AggregationKeys.Events ||
386+
k8sObject.name === AggregationKeys.Namespaces ||
387+
k8sObject.name === AggregationKeys.Nodes
388+
),
389+
)
390+
: []
391+
392+
const dynamicNodes = dynamicNodesList.map<TreeHeading<RBResourceSidebarDataAttributeType>>((k8sObject) => ({
393+
id: `${k8sObject.name}-parent`,
394+
type: 'heading',
395+
title: k8sObject.name,
396+
items: [...k8sObject.child.entries()]
397+
.filter(([key]) => {
398+
const keyLowerCased = key.toLowerCase()
399+
return !(
400+
keyLowerCased === 'node' ||
401+
keyLowerCased === SIDEBAR_KEYS.namespaceGVK.Kind.toLowerCase() ||
402+
keyLowerCased === SIDEBAR_KEYS.eventGVK.Kind.toLowerCase()
403+
)
404+
})
405+
.map<TreeNode<RBResourceSidebarDataAttributeType>>(([key, value]) => {
406+
if (value.data.length === 1) {
407+
const childData = value.data[0]
408+
const nodeName = childData.gvk.Kind
409+
return {
410+
type: 'item',
411+
title: nodeName,
412+
id: getRBSidebarTreeViewNodeId(childData.gvk),
413+
dataAttributes: getRBSidebarTreeViewNodeDataAttributes(childData.gvk),
414+
} satisfies TreeItem<RBResourceSidebarDataAttributeType>
415+
}
416+
417+
return {
418+
type: 'heading',
419+
id: `${k8sObject.name}/${key}-child`,
420+
title: key,
421+
dataAttributes: null,
422+
items: value.data.map<TreeItem<RBResourceSidebarDataAttributeType>>((childData) => {
423+
const nodeName = childData.gvk.Group ? childData.gvk.Group : childData.gvk.Kind
424+
425+
return {
426+
type: 'item',
427+
title: nodeName,
428+
id: getRBSidebarTreeViewNodeId(childData.gvk),
429+
dataAttributes: getRBSidebarTreeViewNodeDataAttributes(childData.gvk),
430+
}
431+
}),
432+
} satisfies TreeHeading<RBResourceSidebarDataAttributeType>
433+
}),
434+
}))
435+
436+
return fixedNodes.concat(dynamicNodes)
437+
}

0 commit comments

Comments
 (0)