-
Notifications
You must be signed in to change notification settings - Fork 21
QA fixes for reviewers seeing screenings even if they aren't a screener #1278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,6 +58,14 @@ export const TableRegistration: FC<Props> = (props: Props) => { | |
| [myRoles], | ||
| ) | ||
|
|
||
| const hasManagerRole = useMemo( | ||
| () => (myRoles ?? []) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| .some(role => role | ||
| ?.trim() | ||
| .toLowerCase() === 'manager'), | ||
| [myRoles], | ||
| ) | ||
|
|
||
| const isAdmin = useMemo( | ||
| () => loginUserInfo?.roles?.some( | ||
| role => typeof role === 'string' | ||
|
|
@@ -66,7 +74,7 @@ export const TableRegistration: FC<Props> = (props: Props) => { | |
| [loginUserInfo?.roles], | ||
| ) | ||
|
|
||
| const shouldDisplayEmail = hasCopilotRole || isAdmin | ||
| const shouldDisplayEmail = hasCopilotRole || hasManagerRole || isAdmin | ||
|
|
||
| const columns = useMemo<TableColumn<BackendResource>[]>( | ||
| () => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,8 +44,9 @@ import { | |
| import { ChallengeDetailContext, ReviewAppContext } from '../../contexts' | ||
| import { updateReview } from '../../services' | ||
| import { ConfirmModal } from '../ConfirmModal' | ||
| import { useSubmissionDownloadAccess } from '../../hooks' | ||
| import { useRole, useSubmissionDownloadAccess } from '../../hooks' | ||
| import type { UseSubmissionDownloadAccessResult } from '../../hooks/useSubmissionDownloadAccess' | ||
| import type { useRoleProps } from '../../hooks/useRole' | ||
|
|
||
| import styles from './TableSubmissionScreening.module.scss' | ||
|
|
||
|
|
@@ -424,48 +425,79 @@ const isScreeningReviewInProgress = (entry: Screening): boolean => ( | |
| || isInProgressStatus(entry.myReviewStatus) | ||
| ) | ||
|
|
||
| /** | ||
| * Creates columns for displaying screening review data. | ||
| * | ||
| * Note: This function assumes that the input data has been validated | ||
| * to contain only Screening phase reviews. Defensive filtering is | ||
| * performed in TabContentScreening to ensure phase data isolation. | ||
| * | ||
| * @param config - Configuration for scorecard access and score masking | ||
| * @returns Array of table columns for screening data | ||
| */ | ||
| const createScreeningColumns = ({ | ||
| canViewScorecard, | ||
| shouldMaskScore, | ||
| }: ScreeningColumnConfig): TableColumn<Screening>[] => [ | ||
| { | ||
| label: 'Screener', | ||
| propertyName: 'screenerHandle', | ||
| renderer: (data: Screening) => (data.screener?.memberHandle ? ( | ||
| <a | ||
| href={getHandleUrl(data.screener)} | ||
| target='_blank' | ||
| rel='noreferrer' | ||
| style={{ | ||
| color: data.screener?.handleColor, | ||
| }} | ||
| onClick={function onClick() { | ||
| window.open( | ||
| getHandleUrl(data.screener), | ||
| '_blank', | ||
| ) | ||
| }} | ||
| > | ||
| {data.screener?.memberHandle ?? ''} | ||
| </a> | ||
| ) : ( | ||
| <span | ||
| style={{ | ||
| color: data.screener?.handleColor, | ||
| }} | ||
| > | ||
| {data.screener?.memberHandle ?? ''} | ||
| </span> | ||
| )), | ||
| propertyName: 'screener', | ||
| renderer: (data: Screening) => { | ||
| const normalizedPhaseName = data.phaseName | ||
| ?.toLowerCase() | ||
| .trim() | ||
|
|
||
| if (normalizedPhaseName && normalizedPhaseName !== 'screening') { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| return <span /> | ||
| } | ||
|
|
||
| // Display the screener handle from the Screening phase review | ||
| // (Review phase data is filtered out in TabContentScreening) | ||
| return data.screener?.memberHandle ? ( | ||
| <a | ||
| href={getHandleUrl(data.screener)} | ||
| target='_blank' | ||
| rel='noreferrer' | ||
| style={{ | ||
| color: data.screener?.handleColor, | ||
| }} | ||
| onClick={function onClick() { | ||
| window.open( | ||
| getHandleUrl(data.screener), | ||
| '_blank', | ||
| ) | ||
| }} | ||
| > | ||
| {data.screener?.memberHandle ?? ''} | ||
| </a> | ||
| ) : ( | ||
| <span | ||
| style={{ | ||
| color: data.screener?.handleColor, | ||
| }} | ||
| > | ||
| {data.screener?.memberHandle ?? ''} | ||
| </span> | ||
| ) | ||
| }, | ||
| type: 'element', | ||
| }, | ||
| { | ||
| label: 'Screening Score', | ||
| propertyName: 'score', | ||
| renderer: (data: Screening) => { | ||
| const normalizedPhaseName = data.phaseName | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| ?.toLowerCase() | ||
| .trim() | ||
| // Link to the Screening phase scorecard | ||
| // (Review phase scorecards are filtered out upstream) | ||
| const maskScore = shouldMaskScore(data) | ||
| const scoreValue = maskScore ? '--' : (data.score ?? '-') | ||
|
|
||
| if (normalizedPhaseName && normalizedPhaseName !== 'screening') { | ||
| return <span>{scoreValue}</span> | ||
| } | ||
|
|
||
| if (!data.reviewId || maskScore) { | ||
| return <span>{scoreValue}</span> | ||
| } | ||
|
|
@@ -631,6 +663,7 @@ export const TableSubmissionScreening: FC<Props> = (props: Props) => { | |
| getRestrictionMessageForMember, | ||
| currentMemberId, | ||
| }: UseSubmissionDownloadAccessResult = useSubmissionDownloadAccess() | ||
| const { hasReviewerRole }: useRoleProps = useRole() | ||
|
|
||
| const normalisedRoles = useMemo( | ||
| () => (myRoles ?? []).map(role => role.toLowerCase()), | ||
|
|
@@ -971,7 +1004,7 @@ export const TableSubmissionScreening: FC<Props> = (props: Props) => { | |
| return false | ||
| } | ||
|
|
||
| if (canViewAllScorecards) { | ||
| if (canViewAllScorecards || hasReviewerRole) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [💡 |
||
| return true | ||
| } | ||
|
|
||
|
|
@@ -996,6 +1029,7 @@ export const TableSubmissionScreening: FC<Props> = (props: Props) => { | |
| }, | ||
| [ | ||
| canViewAllScorecards, | ||
| hasReviewerRole, | ||
| currentMemberId, | ||
| myResourceIds, | ||
| ], | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1045,13 +1045,20 @@ export const ChallengeDetailsPage: FC<Props> = (props: Props) => { | |
| }), | ||
| [myResources], | ||
| ) | ||
| const hasManagerRole = useMemo( | ||
| () => (myResources ?? []) | ||
| .some(resource => (resource.roleName ?? '') | ||
| .trim() | ||
| .toLowerCase() === 'manager'), | ||
| [myResources], | ||
| ) | ||
| const isAdmin = useMemo( | ||
| () => loginUserInfo?.roles?.some( | ||
| role => typeof role === 'string' && role.toLowerCase() === 'administrator', | ||
| ) ?? false, | ||
| [loginUserInfo?.roles], | ||
| ) | ||
| const shouldShowResourcesSection = hasCopilotRole || isAdmin | ||
| const shouldShowResourcesSection = hasCopilotRole || hasManagerRole || isAdmin | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| const canManagePhases = useMemo( | ||
| () => !isPastReviewDetail && (hasCopilotRole || isAdmin), | ||
| [hasCopilotRole, isAdmin, isPastReviewDetail], | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[❗❗
correctness]Consider checking for
row.phaseNamebefore callingtoLowerCase()andtrim(). Ifrow.phaseNameisnullorundefined, this could lead to a runtime error.