Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b9830f0
chore: audit log ui
shivani170 Apr 16, 2026
c99d0f6
chore: css fixes
shivani170 Apr 22, 2026
98f084a
chore: audit log fixes
shivani170 May 5, 2026
71603ab
chore: move audit log code
shivani170 May 5, 2026
1aea63a
chore: update target environment URL and sync AuditLogs component pat…
shivani170 May 6, 2026
30791f7
Merge branch 'develop' into feat/audit-logs-ui
shivani170 May 7, 2026
c6de2c3
chore: update @devtron-labs/devtron-fe-common-lib to 4.0.4-beta-7
shivani170 May 8, 2026
699a1a3
feat: position of audit icon
shivani170 May 14, 2026
f5f2ae3
fix: update navigation path for linked CI details in CINode component
arunjaindev Jun 19, 2026
9995cbe
Merge pull request #3114 from devtron-labs/fix/wf-editor-linked-ci
arunjaindev Jun 22, 2026
1633a09
chore: update @devtron-labs/devtron-fe-common-lib to version 4.0.7
arunjaindev Jun 24, 2026
5ebc6db
Merge pull request #3115 from devtron-labs/fix/url-filters-persist
arunjaindev Jun 24, 2026
9a15ed1
fix: update routing structure in DevtronStackManager
arunjaindev Jun 25, 2026
831ce96
Merge pull request #3116 from devtron-labs/fix/stack-manager-routes
arunjaindev Jun 25, 2026
64a7683
fix: redirection from empty state in api token listing
arunjaindev Jun 30, 2026
c7b8966
Merge pull request #3118 from devtron-labs/fix/token-list-redirect
arunjaindev Jul 1, 2026
087cf68
chore: fix resource navigation URL construction in NodeDetails component
Jul 10, 2026
0d8f6cf
Merge pull request #3119 from devtron-labs/chore/cluster-terminal-tab…
arunjaindev Jul 10, 2026
3342627
Merge branch 'main' into feat/audit-logs-ui
shivani170 Jul 13, 2026
9b99c06
chore: fix timestamp order for audit logs
shivani170 Jul 15, 2026
1a55a1e
Dependabot alerts
shivani170 Jul 22, 2026
31e32e3
chore: version bump
shivani170 Jul 23, 2026
57758c5
Merge pull request #3095 from devtron-labs/feat/audit-logs-ui
shivani170 Jul 24, 2026
be0f3be
Merge branch 'main' into chore/vite-update
shivani170 Jul 24, 2026
c06df12
chore: version update
shivani170 Jul 24, 2026
c8fc00c
chore: version bump
shivani170 Jul 24, 2026
f672beb
Merge branch 'develop' into chore/vite-update
Copilot Jul 24, 2026
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
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"homepage": "/dashboard",
"dependencies": {
"@devtron-labs/devtron-fe-common-lib": "4.0.6-pre-0",
"@devtron-labs/devtron-fe-common-lib": "4.0.9",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@sentry/browser": "7.119.1",
"@sentry/integrations": "7.50.0",
Expand Down Expand Up @@ -92,7 +92,7 @@
"svgo": "^3.3.2",
"ts-node": "10.9.2",
"typescript": "5.5.4",
"vite": "8.0.8",
"vite": "8.0.16",
"vite-plugin-compression2": "2.4.0",
"vite-plugin-pwa": "1.2.0",
"vite-plugin-require-transform": "1.0.21",
Expand All @@ -110,7 +110,7 @@
"packageManager": "yarn@4.9.2",
"overrides": {
"vite-plugin-svgr": {
"vite": "8.0.8"
"vite": "8.0.16"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const ApiTokens = () => {
)

const redirectToCreate = () => {
navigate(`../create`)
navigate('create')
}

const renderGenerateButton = () => (
Expand Down
71 changes: 41 additions & 30 deletions src/Pages/Shared/CommandBar/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {

import { QueryParams as ChartStoreQueryParams } from '@Components/charts/constants'
import { getNavigationList } from '@Components/Navigation'
import { hasNavigationGroupItems } from '@Components/Navigation/utils'
import { getClusterChangeRedirectionUrl } from '@Components/ResourceBrowser/Utils'
import { URLS } from '@Config/routes'

Expand Down Expand Up @@ -103,36 +104,46 @@ const getNavItemBreakdownItems = (

export const getNavigationGroups = (serverMode: SERVER_MODE, isSuperAdmin: boolean): CommandBarGroupType[] =>
getNavigationList(serverMode).map<CommandBarGroupType>((group) => {
const parsedItems = group.items.flatMap<CommandBarGroupType['items'][number]>(
({ hasSubMenu, subItems, title, href, id, icon, keywords }) => {
if (hasSubMenu && subItems?.length) {
return subItems.map<CommandBarGroupType['items'][number]>((subItem) => ({
title: `${title} / ${subItem.title}`,
id: subItem.id,
// Since icon is not present for some subItems, using from group
icon: NAV_SUB_ITEMS_ICON_MAPPING[id] || group.icon,
// TODO: No href present for some subItems
href: subItem.href ?? null,
keywords: subItem.keywords || [],
}))
}

const breakdownItems = getNavItemBreakdownItems(id, serverMode, isSuperAdmin)

if (breakdownItems.length) {
return breakdownItems
}

return {
title,
id,
icon: icon || 'ic-arrow-right',
// TODO: No href present for some items
href: href ?? null,
keywords: keywords || [],
}
},
)
const parsedItems = hasNavigationGroupItems(group)
? group.items.flatMap<CommandBarGroupType['items'][number]>(
({ hasSubMenu, subItems, title, href, id, icon, keywords }) => {
if (hasSubMenu && subItems?.length) {
return subItems.map<CommandBarGroupType['items'][number]>((subItem) => ({
title: `${title} / ${subItem.title}`,
id: subItem.id,
// Since icon is not present for some subItems, using from group
icon: NAV_SUB_ITEMS_ICON_MAPPING[id] || group.icon,
// TODO: No href present for some subItems
href: subItem.href ?? null,
keywords: subItem.keywords || [],
}))
}

const breakdownItems = getNavItemBreakdownItems(id, serverMode, isSuperAdmin)

if (breakdownItems.length) {
return breakdownItems
}

return {
title,
id,
icon: icon || 'ic-arrow-right',
// TODO: No href present for some items
href: href ?? null,
keywords: keywords || [],
}
},
)
: [
{
title: group.title,
id: group.id,
icon: group.icon,
href: group.href,
keywords: [],
} as CommandBarGroupType['items'][number],
]

return {
title: group.title,
Expand Down
19 changes: 7 additions & 12 deletions src/components/ClusterNodes/NodeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -708,18 +708,13 @@ const NodeDetails = ({ lowercaseKindToResourceGroupMap, updateTabUrl }: ClusterL

const handleResourceClick = (e) => {
const { name, tab = ResourceBrowserActionMenuEnum.manifest, namespace } = e.currentTarget.dataset
navigate(
getUrlWithSearchParams(
generatePath(RESOURCE_BROWSER_ROUTES.K8S_RESOURCE_DETAIL, {
clusterId,
group: selectedResource?.gvk.Group.toLowerCase() || K8S_EMPTY_GROUP,
kind: 'pod',
name,
namespace,
}),
{ tab },
),
)
navigate(generatePath(`${RESOURCE_BROWSER_ROUTES.K8S_RESOURCE_DETAIL}/${tab}`, {
clusterId,
group: selectedResource?.gvk.Group.toLowerCase() || K8S_EMPTY_GROUP,
kind: 'pod',
name,
namespace,
}))
}

const getTriggerSortingHandler =
Expand Down
70 changes: 50 additions & 20 deletions src/components/Navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ import { NavGroup } from './NavGroup'
import { NavigationLogo, NavigationLogoExpanded } from './NavigationLogo'
import { NavItem } from './NavItem'
import { NavGroupProps, NavigationProps } from './types'
import { doesNavigationItemMatchPath, filterNavigationItems, findActiveNavigationItemOfNavGroup } from './utils'
import {
doesNavigationGroupMatchPath,
doesNavigationItemMatchPath,
filterNavigationItems,
findActiveNavigationItemOfNavGroup,
hasNavigationGroupItems,
} from './utils'

import './styles.scss'

Expand Down Expand Up @@ -143,17 +149,23 @@ export const Navigation = ({
const NAVIGATION_LIST = useMemo(() => getNavigationList(serverMode), [serverMode])

const selectedNavGroup = useMemo(
() => NAVIGATION_LIST.find(({ items }) => items.some((item) => doesNavigationItemMatchPath(item, pathname))),
[pathname],
() => NAVIGATION_LIST.find((group) => doesNavigationGroupMatchPath(group, pathname)),
[NAVIGATION_LIST, pathname],
)

const selectedExpandableNavGroup = useMemo(
() => (hasNavigationGroupItems(selectedNavGroup) ? selectedNavGroup : null),
[selectedNavGroup],
)

// The current navigation group is the one that is hovered or the one that is active, \
// this is used to determine which nav group items are to be shown in expanded state.
const currentNavGroup = hoveredNavGroup || selectedNavGroup
const currentNavGroup = hoveredNavGroup || selectedExpandableNavGroup
const isExpanded = !!hoveredNavGroup

const navItems = useMemo<NavigationGroupType['items']>(
() => (currentNavGroup ? filterNavigationItems(currentNavGroup.items, searchText) : []),
() =>
hasNavigationGroupItems(currentNavGroup) ? filterNavigationItems(currentNavGroup.items, searchText) : [],
[currentNavGroup, searchText],
)

Expand All @@ -164,6 +176,7 @@ export const Navigation = ({
// Prevent navigation, if the item is already active
if (
selectedNavGroup?.id === navItem.id &&
hasNavigationGroupItems(selectedNavGroup) &&
doesNavigationItemMatchPath(findActiveNavigationItemOfNavGroup(selectedNavGroup.items), pathname)
) {
e.preventDefault()
Expand All @@ -172,6 +185,13 @@ export const Navigation = ({
category: 'Navigation',
action: `nav-${navItem.id}`,
})

if (!hasNavigationGroupItems(navItem)) {
setHoveredNavGroup(null)
setSearchText('')
return
}

setHoveredNavGroup(navItem)
setSearchText('')
}
Expand All @@ -186,25 +206,27 @@ export const Navigation = ({
setSearchText('')
}

const handleNavGroupHover = (navGroup: typeof hoveredNavGroup) => (isHovered: boolean) => {
clearTimeout(timeoutRef.current)
const handleNavGroupHover =
(navGroup: NavigationGroupType & { items: NonNullable<NavigationGroupType['items']> }) =>
(isHovered: boolean) => {
clearTimeout(timeoutRef.current)

if (isHovered) {
if (!hoveredNavGroup) {
setHoveredNavGroup(navGroup)
return
}
if (isHovered) {
if (!hoveredNavGroup) {
setHoveredNavGroup(navGroup)
return
}

timeoutRef.current = setTimeout(() => {
setHoveredNavGroup(navGroup)
setSearchText('')
}, 50)
timeoutRef.current = setTimeout(() => {
setHoveredNavGroup(navGroup)
setSearchText('')
}, 50)
}
}
}

const handleOpenExpandedNavigation = (e: MouseEvent<HTMLDivElement>) => {
if (!hoveredNavGroup && e.target === e.currentTarget) {
setHoveredNavGroup(selectedNavGroup)
setHoveredNavGroup(selectedExpandableNavGroup)
}
}

Expand Down Expand Up @@ -253,8 +275,16 @@ export const Navigation = ({
isExpanded={isExpanded}
isSelected={hoveredNavGroup?.id === item.id || selectedNavGroup?.id === item.id}
onClick={handleNavGroupClick(item)}
to={findActiveNavigationItemOfNavGroup(item.items)?.href}
onHover={handleNavGroupHover(item)}
to={
hasNavigationGroupItems(item)
? findActiveNavigationItemOfNavGroup(item.items)?.href
: item.href
}
onHover={
hasNavigationGroupItems(item)
? handleNavGroupHover(item)
: handleCloseExpandedNavigation(true)
}
showTooltip={item.disabled}
/>
))}
Expand Down
76 changes: 43 additions & 33 deletions src/components/Navigation/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { NavigationGroupType, NavigationItemType, ROUTER_URLS, SERVER_MODE } fro

import { importComponentFromFELibrary } from '@Components/common'

import { filterNavGroupAndItem } from './utils'
import { filterNavGroupAndItem, hasNavigationGroupItems } from './utils'

const APPLICATION_MANAGEMENT_POLICIES_NAV_ITEM: NavigationItemType = importComponentFromFELibrary(
'APPLICATION_MANAGEMENT_POLICIES_NAV_ITEM',
Expand Down Expand Up @@ -322,6 +322,12 @@ const NAVIGATION_LIST: NavigationGroupType[] = [
],
isAvailableInEA: true,
},
{
id: 'audit-logs',
title: 'Audit logs',
icon: 'ic-file-log-search',
href: `${ROUTER_URLS.AUDIT_LOGS}?sortBy=timeStamp&sortOrder=DESC`,
},
]

export const getNavigationList = (serverMode: SERVER_MODE): NavigationGroupType[] => {
Expand All @@ -332,37 +338,41 @@ export const getNavigationList = (serverMode: SERVER_MODE): NavigationGroupType[
),
)

const filteredNavItems = filteredNavGroup.map((group) => {
const filteredItems = group.items.filter((item) =>
filterNavGroupAndItem(
{
forceHideEnvKey: item.forceHideEnvKey,
hideNav: item.hideNav,
isAvailableInEA: item.isAvailableInEA,
},
serverMode,
),
)
return { ...group, items: filteredItems }
})
return filteredNavGroup.map((group) => {
if (!hasNavigationGroupItems(group)) {
return group
}

const filteredItems = group.items
.filter((item) =>
filterNavGroupAndItem(
{
forceHideEnvKey: item.forceHideEnvKey,
hideNav: item.hideNav,
isAvailableInEA: item.isAvailableInEA,
},
serverMode,
),
)
.map((item) => {
if (item.hasSubMenu && item.subItems) {
const filteredSubItems = item.subItems.filter((subItem) =>
filterNavGroupAndItem(
{
forceHideEnvKey: subItem.forceHideEnvKey,
hideNav: subItem.hideNav,
isAvailableInEA: subItem.isAvailableInEA,
},
serverMode,
),
)

return filteredNavItems.map((group) => ({
...group,
items: group.items.map((item) => {
if (item.hasSubMenu && item.subItems) {
const filteredSubItems = item.subItems.filter((subItem) =>
filterNavGroupAndItem(
{
forceHideEnvKey: subItem.forceHideEnvKey,
hideNav: subItem.hideNav,
isAvailableInEA: subItem.isAvailableInEA,
},
serverMode,
),
)
return { ...item, subItems: filteredSubItems }
}
return item
}),
}))
return { ...item, subItems: filteredSubItems }
}

return item
})

return { ...group, items: filteredItems } as NavigationGroupType
})
}
Loading
Loading