Skip to content

feat(PM-4079): UI updates on Review/Appeals tab#1508

Closed
hentrymartin wants to merge 8 commits intodevfrom
pm-4079
Closed

feat(PM-4079): UI updates on Review/Appeals tab#1508
hentrymartin wants to merge 8 commits intodevfrom
pm-4079

Conversation

@hentrymartin
Copy link
Collaborator

@hentrymartin hentrymartin commented Mar 3, 2026

Related JIRA Ticket:

https://topcoder.atlassian.net/browse/PM-4079

What's in this PR?

  • Combined the tabs - Reviews, Appeals and Appeal Response into one tab - Review/Appeals
  • Converted the reviewers layout from column to row stack.
Screenshot 2026-03-03 at 23 23 16

@hentrymartin hentrymartin changed the title feat(PM-4079): UI updates on Revew feat(PM-4079): UI updates on Review/Appeals tab Mar 3, 2026
{!runs.length && isLoading && (
<tr>
<td colSpan={4}>Loading...</td>
<td colSpan={5}>Loading...</td>
Copy link

Choose a reason for hiding this comment

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

[⚠️ maintainability]
The colSpan value was updated from 4 to 5 to accommodate the new 'Min Score' column. Ensure that this change is consistent with all other parts of the code where the table structure is used, especially in different responsive layouts, to avoid layout issues.

)}
</td>
<td>
{run.workflow?.scorecard?.minimumPassingScore ?? '-'}
Copy link

Choose a reason for hiding this comment

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

[⚠️ correctness]
The use of optional chaining (?.) with run.workflow?.scorecard?.minimumPassingScore is a good practice to prevent runtime errors if any of these properties are undefined. However, ensure that the default value '-' is appropriate for all contexts where this value might be displayed, as it might affect the user interface or data interpretation.

@@ -1,3 +1,4 @@
/* eslint-disable complexity */
Copy link

Choose a reason for hiding this comment

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

[⚠️ maintainability]
Disabling ESLint's complexity rule might hide potential maintainability issues. Consider refactoring the component to reduce complexity instead of disabling the rule.

() => !props.isActiveChallenge && normalizedSelectedTab === 'review',
[normalizedSelectedTab, props.isActiveChallenge],
)
const isCombinedReviewAppeals = useMemo(
Copy link

Choose a reason for hiding this comment

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

[💡 performance]
The useMemo hook is used correctly here to memoize the isCombinedReviewAppeals value. However, ensure that the normalizedSelectedTab value is not expected to change frequently, as excessive use of useMemo can lead to unnecessary complexity.

downloadSubmission={props.downloadSubmission}
mappingReviewAppeal={props.mappingReviewAppeal}
hideHandleColumn={hideHandleColumn}
mode={isCombinedReviewAppeals ? 'combined-review-appeals' : 'default'}
Copy link

Choose a reason for hiding this comment

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

[⚠️ correctness]
Passing the mode prop with a dynamic value is a good approach. Ensure that the TableReview component handles both 'combined-review-appeals' and 'default' modes correctly, especially if there are significant differences in behavior.


&:global(.enhanced-table) table tbody tr:global(.row-before-expand) td[data-col-index='0'],
&:global(.enhanced-table) table tbody tr:global(.row-before-expand) td[data-col-index='1'] {
border-bottom: none !important;
Copy link

Choose a reason for hiding this comment

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

[⚠️ maintainability]
Using !important can make future maintenance difficult as it overrides other styles. Consider if !important is necessary here or if the specificity of the selector can be increased instead.

}

&:global(.enhanced-table) table tbody tr:not(:global(.expand-row)) td {
border-top: none !important;
Copy link

Choose a reason for hiding this comment

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

[⚠️ maintainability]
Using !important can make future maintenance difficult as it overrides other styles. Consider if !important is necessary here or if the specificity of the selector can be increased instead.

}

&:global(.enhanced-table) table tbody tr:global(.expand-row):has(.aiReviews) td {
border-bottom: var(--TableBorderColor) solid 1px !important;
Copy link

Choose a reason for hiding this comment

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

[⚠️ maintainability]
Using !important can make future maintenance difficult as it overrides other styles. Consider if !important is necessary here or if the specificity of the selector can be increased instead.

for (const aggregated of list) {
const base = {
...(aggregated.submission ?? {}),
...aggregated.submission,
Copy link

Choose a reason for hiding this comment

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

[⚠️ correctness]
The spread operator is used twice on aggregated.submission. This is redundant and could lead to unexpected behavior if properties are overwritten. Consider using it only once.

])

const tableRows = useMemo<SubmissionRow[]>(
() => (props.mode === 'combined-review-appeals' ? expandedReviewRows : aggregatedRows),
Copy link

Choose a reason for hiding this comment

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

[❗❗ correctness]
The useMemo dependency array includes aggregatedRows, which is not defined in the diff. Ensure that aggregatedRows is correctly defined and included in the dependencies.

}

// Combined Review/Appeals layout
if (props.mode === 'combined-review-appeals') {
Copy link

Choose a reason for hiding this comment

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

[💡 performance]
The submissionGroupRowSpan function iterates over allRows to count rows with the same submissionId. This could be optimized by using a more efficient data structure or algorithm if performance becomes an issue with large datasets.

}

if (props.aiReviewers) {
combinedColumns.push({
Copy link

Choose a reason for hiding this comment

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

[⚠️ design]
The combinedColumns array is conditionally extended with AI review columns. Ensure that props.aiReviewers is always defined when expected, as this could lead to inconsistent table structures.

disableSorting
onToggleSort={_.noop}
removeDefaultSort
expandContentStartIndex={
Copy link

Choose a reason for hiding this comment

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

[⚠️ correctness]
The expandContentStartIndex is conditionally set based on props.mode. Ensure that the index calculation is correct and that columns always contains the expected structure to avoid runtime errors.

const reviewTab = tabs.find(tab => {
const normalizedValue = normalize(tab.value)
return normalizedValue === 'review'
|| normalizedValue === 'review / appeals'
Copy link

Choose a reason for hiding this comment

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

[⚠️ maintainability]
Consider using a more robust method for comparing tab values, such as a set of allowed values, to avoid potential issues with string comparison errors or typos. This will improve maintainability and reduce the risk of bugs if more tab names are added in the future.

{!!col.label && (
<strong
{props.showExpand && isExpanded && (() => {
const skippedByRowSpan = props.skipCellByColumn?.filter(Boolean).length ?? 0
Copy link

Choose a reason for hiding this comment

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

[⚠️ correctness]
The calculation of effectiveSkippedCount assumes that skipCellByColumn and expandContentStartIndex are always defined and valid. Consider adding validation or default values to handle cases where these props might be undefined or contain unexpected values.

// eslint-disable-next-line jsx-a11y/control-has-associated-label
<td key={`expand-pad-${i}`} />
))}
<td className={styles.expandContentCell} colSpan={expandColSpan}>
Copy link

Choose a reason for hiding this comment

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

[❗❗ correctness]
The colSpan attribute for the <td> element is calculated as displayColumns.length - effectiveSkippedCount. Ensure that effectiveSkippedCount does not exceed displayColumns.length to prevent rendering issues.

indexColumns
=== props.columns.length - 1
(itemItemColumns, indexItemColumns) => {
const { rowSpan: rowSpanOrFn, ...cellColumnProps } = itemItemColumns
Copy link

Choose a reason for hiding this comment

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

[⚠️ performance]
The use of rowSpanOrFn as a function to determine rowSpan is flexible, but ensure that the function is performant and doesn't introduce unnecessary complexity or performance overhead, especially if props.data is large or complex.

Copy link
Collaborator

@kkartunov kkartunov left a comment

Choose a reason for hiding this comment

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

@hentrymartin remove the combo - we said we want to keep phase tabs separated.

@hentrymartin hentrymartin deleted the pm-4079 branch March 4, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants