Skip to content

Commit e97b69a

Browse files
committed
feat: add recent actions integration to CommandBar and enhance CommandGroup component
1 parent 6deca88 commit e97b69a

File tree

4 files changed

+97
-91
lines changed

4 files changed

+97
-91
lines changed

src/Pages/Shared/CommandBar/CommandBar.component.tsx

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,53 @@
11
import { useEffect, useState } from 'react'
22

3-
import { Backdrop, KeyboardShortcut, SearchBar, useRegisterShortcut } from '@devtron-labs/devtron-fe-common-lib'
3+
import {
4+
API_STATUS_CODES,
5+
Backdrop,
6+
getUserPreferences,
7+
KeyboardShortcut,
8+
ResponseType,
9+
SearchBar,
10+
useQuery,
11+
useRegisterShortcut,
12+
} from '@devtron-labs/devtron-fe-common-lib'
413

514
import CommandGroup from './CommandGroup'
6-
import { NAVIGATION_GROUPS, SHORT_CUTS } from './constants'
15+
import { NAVIGATION_GROUPS, RECENT_ACTIONS_GROUP, SHORT_CUTS } from './constants'
16+
import { CommandBarGroupType } from './types'
717

818
import './CommandBar.scss'
919

1020
const CommandBar = () => {
1121
const [showCommandBar, setShowCommandBar] = useState(false)
1222

23+
const { data: recentActionsGroup, isLoading } = useQuery({
24+
queryFn: ({ signal }) =>
25+
getUserPreferences(signal).then((response) => {
26+
const responseData: ResponseType<typeof response> = {
27+
code: API_STATUS_CODES.OK,
28+
status: 'OK',
29+
result: response,
30+
}
31+
return responseData
32+
}),
33+
queryKey: [showCommandBar, 'recentNavigationActions'],
34+
enabled: showCommandBar,
35+
select: ({ result }) =>
36+
result.commandBar.recentNavigationActions.reduce<CommandBarGroupType>((acc, action) => {
37+
const requiredGroup = NAVIGATION_GROUPS.find((group) =>
38+
group.items.some((item) => item.id === action.id),
39+
)
40+
41+
if (requiredGroup) {
42+
const requiredItem = requiredGroup.items.find((item) => item.id === action.id)
43+
if (requiredItem) {
44+
acc.items.push(structuredClone(requiredItem))
45+
}
46+
}
47+
return acc
48+
}, structuredClone(RECENT_ACTIONS_GROUP)),
49+
})
50+
1351
const { registerShortcut, unregisterShortcut } = useRegisterShortcut()
1452

1553
const handleClose = () => {
@@ -40,7 +78,7 @@ const CommandBar = () => {
4078
<Backdrop onEscape={handleClose}>
4179
<div className="dc__mxw-800 mxh-450 flexbox-col dc__overflow-auto dc__content-space br-12 bg__modal--primary command-bar__container w-100 h-100">
4280
<div className="flexbox-col dc__overflow-auto">
43-
<div className="px-16">
81+
<div className="px-20 py-8">
4482
<SearchBar
4583
inputProps={{
4684
autoFocus: true,
@@ -56,8 +94,10 @@ const CommandBar = () => {
5694
aria-label="Command Menu"
5795
// TODO: aria-activedescendant for the currently focused item
5896
>
97+
<CommandGroup isLoading={isLoading} {...(recentActionsGroup || RECENT_ACTIONS_GROUP)} />
98+
5999
{NAVIGATION_GROUPS.map((group) => (
60-
<CommandGroup key={group.id} groupDetails={group} />
100+
<CommandGroup key={group.id} {...group} />
61101
))}
62102
</div>
63103
</div>

src/Pages/Shared/CommandBar/CommandGroup.tsx

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,45 @@ import { Icon } from '@devtron-labs/devtron-fe-common-lib'
22

33
import { CommandGroupProps } from './types'
44

5-
const CommandGroup = ({ groupDetails }: CommandGroupProps) => (
6-
<div className="flexbox-col p-8">
7-
<div className="flexbox px-16 py-6 dc__gap-4">
8-
<h2 className="m-0 cn-7 fs-13 fw-6 lh-20 dc__uppercase font-ibm-plex-mono" id={groupDetails.id}>
9-
{groupDetails.title}
10-
</h2>
11-
</div>
5+
const CommandGroup = ({ title, id, items, isLoading }: CommandGroupProps) => {
6+
const renderContent = () => {
7+
if (isLoading || !items?.length) {
8+
return (
9+
<div className="px-16 py-12 flexbox dc__align-items-center dc__gap-8">
10+
<span className="cn-7 fs-13 fw-6 lh-20">{isLoading ? 'Loading...' : 'No items found'}</span>
11+
</div>
12+
)
13+
}
1214

13-
{/* TODO: Empty/Loading/Error state */}
14-
<div className="flexbox-col" key={groupDetails.id} role="group" aria-labelledby={groupDetails.id}>
15-
{groupDetails.items.map((item) => (
16-
<div
17-
className="flexbox px-16 py-12 dc__align-items-center dc__gap-8"
18-
role="option"
19-
// TODO: Fix later
20-
aria-selected="false"
21-
>
22-
<div className="flexbox dc__align-items-center dc__gap-12">
23-
<Icon name={item.icon} size={24} color="N700" />
24-
<h3 className="m-0 cn-9 fs-14 fw-4 lh-20 dc__truncate">{item.title}</h3>
25-
</div>
15+
return items.map((item) => (
16+
<div
17+
className="flexbox px-16 py-12 dc__align-items-center dc__gap-8"
18+
role="option"
19+
// TODO: Fix later
20+
aria-selected="false"
21+
>
22+
<div className="flexbox dc__align-items-center dc__gap-12">
23+
<Icon name={item.icon} size={24} color="N700" />
24+
<h3 className="m-0 cn-9 fs-14 fw-4 lh-20 dc__truncate">{item.title}</h3>
2625
</div>
27-
))}
26+
</div>
27+
))
28+
}
29+
30+
return (
31+
<div className="flexbox-col p-8">
32+
<div className="flexbox px-16 py-6 dc__gap-4">
33+
<h2 className="m-0 cn-7 fs-13 fw-6 lh-20 dc__uppercase font-ibm-plex-mono" id={id}>
34+
{title}
35+
</h2>
36+
</div>
37+
38+
{/* TODO: Empty/Loading/Error state */}
39+
<div className="flexbox-col" key={id} role="group" aria-labelledby={id}>
40+
{renderContent()}
41+
</div>
2842
</div>
29-
</div>
30-
)
43+
)
44+
}
3145

3246
export default CommandGroup

src/Pages/Shared/CommandBar/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,12 @@ export const NAVIGATION_GROUPS: CommandBarGroupType[] = NAVIGATION_LIST.map((gro
433433
}),
434434
}))
435435

436+
export const RECENT_ACTIONS_GROUP: CommandBarGroupType = {
437+
id: 'command-bar-recent-navigation-group',
438+
items: [],
439+
title: 'Recent Navigation',
440+
}
441+
436442
export const SHORT_CUTS: Record<
437443
'OPEN_COMMAND_BAR',
438444
{

src/Pages/Shared/CommandBar/types.ts

Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,14 @@
1-
import { customEnv, IconsProps, Never, URLS as CommonURLS } from '@devtron-labs/devtron-fe-common-lib'
1+
import {
2+
customEnv,
3+
IconsProps,
4+
NavigationItemID,
5+
NavigationSubMenuItemID,
6+
Never,
7+
URLS as CommonURLS,
8+
} from '@devtron-labs/devtron-fe-common-lib'
29

310
import { URLS } from '@Config/routes'
411

5-
export type NavigationItemID =
6-
| 'application-management-overview'
7-
| 'application-management-applications'
8-
| 'application-management-application-groups'
9-
| 'application-management-chart-store'
10-
| 'application-management-bulk-edit'
11-
| 'application-management-configurations'
12-
| 'application-management-policies'
13-
| 'application-management-others'
14-
| 'infrastructure-management-overview'
15-
| 'infrastructure-management-resource-browser'
16-
| 'infrastructure-management-intercepted-changes'
17-
| 'infrastructure-management-resource-watcher'
18-
| 'infrastructure-management-catalog-framework'
19-
| 'software-release-management-overview'
20-
| 'software-release-management-software-release'
21-
| 'cost-visibility-overview'
22-
| 'cost-visibility-trends'
23-
| 'cost-visibility-cost-breakdown'
24-
| 'cost-visibility-configurations'
25-
| 'security-center-overview'
26-
| 'security-center-application-security'
27-
| 'security-center-security-policies'
28-
| 'automation-and-enablement-jobs'
29-
| 'automation-and-enablement-alerting'
30-
| 'automation-and-enablement-incident-response'
31-
| 'automation-and-enablement-api-portal'
32-
| 'automation-and-enablement-runbook-automation'
33-
| 'global-configuration-sso-login-services'
34-
| 'global-configuration-host-urls'
35-
| 'global-configuration-cluster-and-environments'
36-
| 'global-configuration-container-oci-registry'
37-
| 'global-configuration-authorization'
38-
39-
export type NavigationSubMenuItemID =
40-
| 'application-management-configurations-gitops'
41-
| 'application-management-configurations-git-accounts'
42-
| 'application-management-configurations-external-links'
43-
| 'application-management-configurations-chart-repository'
44-
| 'application-management-configurations-deployment-charts'
45-
| 'application-management-configurations-notifications'
46-
| 'application-management-configurations-catalog-frameworks'
47-
| 'application-management-configurations-scoped-variables'
48-
| 'application-management-configurations-build-infra'
49-
| 'application-management-policies-deployment-window'
50-
| 'application-management-policies-approval-policy'
51-
| 'application-management-policies-plugin-policy'
52-
| 'application-management-policies-pull-image-digest'
53-
| 'application-management-policies-tag-policy'
54-
| 'application-management-policies-filter-conditions'
55-
| 'application-management-policies-lock-deployment-configuration'
56-
| 'application-management-others-application-templates'
57-
| 'application-management-others-projects'
58-
| 'cost-visibility-cost-breakdown-clusters'
59-
| 'cost-visibility-cost-breakdown-environments'
60-
| 'cost-visibility-cost-breakdown-projects'
61-
| 'cost-visibility-cost-breakdown-applications'
62-
| 'global-configuration-authorization-user-permissions'
63-
| 'global-configuration-authorization-permission-groups'
64-
| 'global-configuration-authorization-api-tokens'
65-
6612
export type NavigationRootItemID =
6713
| 'application-management'
6814
| 'infrastructure-management'
@@ -127,6 +73,6 @@ export interface CommandBarGroupType {
12773
items: CommandBarItemType[]
12874
}
12975

130-
export interface CommandGroupProps {
131-
groupDetails: CommandBarGroupType
76+
export interface CommandGroupProps extends CommandBarGroupType {
77+
isLoading?: boolean
13278
}

0 commit comments

Comments
 (0)