Skip to content

Conversation

@Elessar1802
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings January 5, 2026 16:49
@github-actions
Copy link

github-actions bot commented Jan 5, 2026

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the DevtronAppList component to use a generic Table component from the common library instead of a custom implementation. The change simplifies the codebase by removing custom expand/collapse logic and leveraging the Table component's built-in features for expandable rows, pagination, and filtering.

  • Migrates from custom list rendering to using the generic Table component with built-in pagination and expandable row support
  • Removes custom expanded row component and related state management (expandedRow, isAllExpanded, isAllExpandable)
  • Refactors cell rendering into modular CellComponent functions that handle both regular and expanded rows

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/components/app/list/types.tsx Removes DevtronAppExpandedState interface and adds TableAdditionalPropsType for Table component props
src/components/app/list/list.scss Removes custom cell styling classes and adds generic-table row padding classes
src/components/app/list/expandedRow/types.tsx Deletes file - no longer needed with Table component
src/components/app/list/expandedRow/expandedRow.css Deletes file - styling now handled by Table component
src/components/app/list/expandedRow/ExpandedRow.tsx Deletes file - expanded row logic integrated into Table component
src/components/app/list/constants.tsx Deletes file - INITIAL_EXPANDED_STATE no longer needed
src/components/app/list/DevtronAppListContainer.tsx Complete refactor to use Table component with cell components for rendering, removes manual expand/collapse logic and pagination handling

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +194 to +195
status={isExpandedRow ? env.status : app.defaultEnv.appStatus}
isVirtualEnv={isExpandedRow ? env.isVirtualEnvironment : app.defaultEnv.isVirtualEnvironment}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent null safety handling for app.defaultEnv. Line 194 and 195 access app.defaultEnv.appStatus and app.defaultEnv.isVirtualEnvironment without null checking, but the defaultEnv type is nullable (Environment | null). This could cause a runtime error if defaultEnv is null. Consider using optional chaining like the code does on lines 202, 214 (app.defaultEnv?.clusterName, app.defaultEnv?.namespace).

Copilot uses AI. Check for mistakes.
})
}
if (field === AppListSortableKeys.LAST_DEPLOYED) {
const lastDeployedTime = isExpandedRow ? env.lastDeployedTime : app.defaultEnv.lastDeployedTime
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference error. The code accesses app.defaultEnv.lastDeployedTime without null checking, but defaultEnv is nullable (Environment | null according to the types). This could cause a runtime error if defaultEnv is null. Consider using optional chaining: app.defaultEnv?.lastDeployedTime

Suggested change
const lastDeployedTime = isExpandedRow ? env.lastDeployedTime : app.defaultEnv.lastDeployedTime
const lastDeployedTime = isExpandedRow ? env.lastDeployedTime : app.defaultEnv?.lastDeployedTime

Copilot uses AI. Check for mistakes.
totalRows: totalCount,
}
},
[syncListData, JSON.stringify(filterConfig)],
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency array uses JSON.stringify(filterConfig) which can be inefficient and may cause unnecessary re-renders. JSON.stringify is not recommended for dependency arrays because it creates a new string on every render even if the object content hasn't changed. Consider using individual dependencies from filterConfig (like searchKey, offset, pageSize, appStatus, etc.) or using a more efficient deep comparison approach.

Suggested change
[syncListData, JSON.stringify(filterConfig)],
[syncListData, filterConfig],

Copilot uses AI. Check for mistakes.
data: app,
id: String(app.id),
expandableRows:
app.defaultEnv.name && app.environments.length
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference error. Line 408 accesses app.defaultEnv.name without null checking. Since defaultEnv is nullable (Environment | null), this could cause a runtime error if defaultEnv is null. Consider using optional chaining: app.defaultEnv?.name

Suggested change
app.defaultEnv.name && app.environments.length
app.defaultEnv?.name && app.environments.length

Copilot uses AI. Check for mistakes.
const namespace = isExpandedRow ? env.namespace : app.defaultEnv?.namespace ?? ''
return (
<div className="flex left">
<p data-testid={`${namespace}-namespace`} className="dc__truncate-text m-0">
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra whitespace detected. There's double spacing between 'dc__truncate-text' and 'm-0' in the className. This should be a single space for consistency.

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++

placement="top"
content={moment(lastDeployedTime).format(DATE_TIME_FORMATS.TWELVE_HOURS_FORMAT)}
>
<p className="dc__truncate-text m-0" data-testid="last-deployed-time">
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra whitespace detected. There's double spacing between 'dc__truncate-text' and 'm-0' in the className. This should be a single space for consistency.

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++

Comment on lines 75 to 87
const isEnvConfigured = app.defaultEnv.name

const isSearchOrFilterApplied =
searchKey || appStatus.length || project.length || environment.length || namespace.length || cluster.length
if (!envCount || isRowInExpandState) {
return null
}

const abortControllerRef = useRef<AbortController>(new AbortController())
const [appListResponseLoading, appListResponse, appListError, appListReload] = useAsync(
() =>
abortPreviousRequests(
() =>
getAppList(getDevtronAppListPayload(filterConfig, environmentList, namespaceList), {
signal: abortControllerRef.current.signal,
}),
abortControllerRef,
),
[filterConfig, syncListData],
!appFiltersResponseLoading, // We need to wait until environment filters are created from cluster and namespace
return (
<div className="flex left dc__gap-6">
<span
data-testid={`${app.defaultEnv.name}-environment`}
className={`dc__truncate cn-9 ${isEnvConfigured ? '' : 'cn5'}`}
>
{isEnvConfigured ? app.defaultEnv.name : 'Not configured'}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference error. Lines 75, 84, and 87 access app.defaultEnv.name without null checking, but defaultEnv is nullable (Environment | null according to the types). This could cause a runtime error if defaultEnv is null. Consider using optional chaining: app.defaultEnv?.name

Copilot uses AI. Check for mistakes.
const { name } = app

const onClick = () => {
push(redirectToAppDetails(app, app.defaultEnv.id))
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference error. Line 144 accesses app.defaultEnv.id without null checking. Since defaultEnv is nullable (Environment | null), this could cause a runtime error if defaultEnv is null. Consider using optional chaining and a fallback value: app.defaultEnv?.id ?? 0

Suggested change
push(redirectToAppDetails(app, app.defaultEnv.id))
push(redirectToAppDetails(app, app.defaultEnv?.id ?? 0))

Copilot uses AI. Check for mistakes.
return () => {
signals.removeEventListener(TableSignalEnum.ENTER_PRESSED, handleEnterPressed)
}
}, [])
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing dependencies in useEffect. The effect uses 'id' and 'signals' but the dependency array is empty. This could lead to stale closures where the effect references outdated values. Consider adding 'id' and 'signals' to the dependency array.

Suggested change
}, [])
}, [id, signals])

Copilot uses AI. Check for mistakes.

return (
<div className="flex left">
<p data-testid={`${clusterName}-cluster`} className="dc__truncate-text m-0">
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra whitespace detected. There's double spacing between 'dc__truncate-text' and 'm-0' in the className. This should be a single space for consistency.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

})

const [expandedState, setExpandedState] = useState<DevtronAppExpandedState>(INITIAL_EXPANDED_STATE)
const EnvironmentCellComponent = ({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls move into separate files CellComponents

}
const columns = useMemo(
() => [
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to utils

CellComponent,
},
{
field: AppListSortableKeys.LAST_DEPLOYED,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be conditional? Pls verify with deleted ExpandedRow.tsx

{renderPagination()}
</>
<Table<App, FiltersTypeEnum.URL, TableAdditionalPropsType>
key={JSON.stringify({ syncListData, filterConfig })}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be this big key?

searchKey || appStatus.length || project.length || environment.length || namespace.length || cluster.length

const redirectToAppDetails = (app, envId: number): string => {
setCurrentAppName(app.name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't need this since its set in AppHeader, can you confirm? since otherwise should add this in HoverComponent redirection as well?

event.stopPropagation()
event.preventDefault()
expandRow(event.currentTarget.dataset.key)
const app = data as App
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should fix this by taking additional type param and based on that and isExpandedRow if its true type for row should toggle

return (
<div className="flex left">
{lastDeployedTime && (
<Tippy
Copy link
Member

@AbhishekA1509 AbhishekA1509 Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Tooltip with alwaysShowOnHover

setExpandedState((prevState) => ({ ...prevState, expandedRow: { ...prevState.expandedRow, [id]: true } }))
return (
<div className="flex left dc__gap-4 dc__visible-hover dc__visible-hover--parent">
<Tooltip content={name}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be on span?

@github-actions
Copy link

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

@github-actions
Copy link

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR:Issue-verification-failed PR:Issue-verification-failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants