Skip to content
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

feat: Include VendorApprovalStatus table #1328

Open
wants to merge 13 commits into
base: development
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const ProvideFeedbackModal = ({
changesRequestedIssues = [],
changesRequestedGithubUrl = '',
testPlan = '',
username = ''
username = '',
isAdmin = false
}) => {
const [selectedRadio, setSelectedRadio] = useState('not-approved-input');

Expand Down Expand Up @@ -68,6 +69,8 @@ const ProvideFeedbackModal = ({
name="radio-feedback"
id="approve-input"
type="radio"
disabled={isAdmin}
aria-disabled={isAdmin}
/>
<FormCheck.Label htmlFor="approve-input">
Approve
Expand Down Expand Up @@ -119,7 +122,8 @@ ProvideFeedbackModal.propTypes = {
feedbackGithubUrl: PropTypes.string,
show: PropTypes.bool,
testPlan: PropTypes.string,
username: PropTypes.string
username: PropTypes.string,
isAdmin: PropTypes.bool
};

export default ProvideFeedbackModal;
200 changes: 105 additions & 95 deletions client/components/CandidateReview/CandidateTestPlanRun/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { navigateTests } from '../../../utils/navigateTests';
import {
ADD_VIEWER_MUTATION,
CANDIDATE_REPORTS_QUERY,
PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION
PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION,
VENDOR_APPROVAL_STATUS_QUERY
} from './queries';
import Badge from 'react-bootstrap/Badge';
import Container from 'react-bootstrap/Container';
Expand All @@ -32,32 +33,31 @@ import createIssueLink, {
} from '../../../utils/createIssueLink';
import RunHistory from '../../common/RunHistory';
import { useUrlTestIndex } from '../../../hooks/useUrlTestIndex';
import { evaluateAuth } from '../../../utils/evaluateAuth';
import NotApprovedModal from '../CandidateModals/NotApprovedModal';
import FailingAssertionsSummaryTable from '../../FailingAssertionsSummary/Table';
import FailingAssertionsSummaryHeading from '../../FailingAssertionsSummary/Heading';

const atMap = {
1: 'JAWS',
2: 'NVDA',
3: 'VoiceOver for macOS'
};

const vendorReviewStatusMap = {
READY: 'Ready',
IN_PROGRESS: 'In Progress',
APPROVED: 'Approved'
};

const CandidateTestPlanRun = () => {
const { atId, testPlanVersionId } = useParams();
const navigate = useNavigate();

let testPlanVersionIds = [];
if (testPlanVersionId.includes(','))
testPlanVersionIds = testPlanVersionId.split(',');

const { loading, data, error, refetch } = useQuery(CANDIDATE_REPORTS_QUERY, {
variables: testPlanVersionIds.length
? { testPlanVersionIds, atId }
: { testPlanVersionId, atId }
});
const [addViewer] = useMutation(ADD_VIEWER_MUTATION);
const [promoteVendorReviewStatus] = useMutation(
PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION
);

const nextButtonRef = useRef();
const finishButtonRef = useRef();

const [reviewStatus, setReviewStatus] = useState('');
const [reviewStatus, setReviewStatus] = useState('READY');
const [firstTimeViewing, setFirstTimeViewing] = useState(false);
const [viewedTests, setViewedTests] = useState([]);
const [testsLength, setTestsLength] = useState(0);
Expand All @@ -75,6 +75,61 @@ const CandidateTestPlanRun = () => {
const [showRunHistory, setShowRunHistory] = useState(false);
const [showBrowserClicks, setShowBrowserClicks] = useState([]);

let testPlanVersionIds = [];
if (testPlanVersionId.includes(','))
testPlanVersionIds = testPlanVersionId.split(',');

const { loading, data, error, refetch } = useQuery(CANDIDATE_REPORTS_QUERY, {
variables: testPlanVersionIds.length
? { testPlanVersionIds, atId }
: { testPlanVersionId, atId }
});
const [addViewer] = useMutation(ADD_VIEWER_MUTATION);
const [promoteVendorReviewStatus] = useMutation(
PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION
);

const testPlanReports = [];
if (data?.testPlanReports?.length === 0)
return <Navigate to="/404" replace />;

const getLatestReleasedAtVersionReport = arr => {
return arr.reduce((o1, o2) => {
return new Date(o1.latestAtVersionReleasedAt.releasedAt) >
new Date(o2.latestAtVersionReleasedAt.releasedAt)
? o1
: o2;
});
};

Object.keys(atMap).forEach(k => {
const group = data?.testPlanReports?.filter(t => t.browser.id == k);
if (group?.length) {
const latestReport = getLatestReleasedAtVersionReport(group);
testPlanReports.push(latestReport);
}
});

const testPlanReport = testPlanReports.find(
each =>
each.testPlanVersion.id === testPlanVersionId ||
testPlanVersionIds.includes(each.testPlanVersion.id)
);

const auth = evaluateAuth(data?.me ? data?.me : {});
const { isAdmin, company } = auth;
const { data: vendorApprovalStatusData } = useQuery(
VENDOR_APPROVAL_STATUS_QUERY,
{
variables: {
userId: auth.id,
vendorId: company?.id,
testPlanReportId: testPlanReport?.id
},
skip: !company || !testPlanReport
}
);

const isSummaryView = currentTestIndex === -1;

const isLaptopOrLarger = useMediaQuery({
Expand Down Expand Up @@ -127,7 +182,12 @@ const CandidateTestPlanRun = () => {
};

const addViewerToTest = async testId => {
await addViewer({ variables: { testPlanVersionId, testId } });
await addViewer({
variables: {
testId,
testPlanReportId: testPlanReport.id
}
});
};

const updateTestViewed = async () => {
Expand All @@ -143,31 +203,27 @@ const CandidateTestPlanRun = () => {
}
};

const updateVendorStatus = async (reportApproved = false) => {
if (reviewStatus === 'READY') {
await Promise.all(
testPlanReports?.map(report =>
promoteVendorReviewStatus({
variables: { testReportId: report.id, reviewStatus }
})
)
);
setReviewStatus('IN_PROGRESS');
} else if (reviewStatus === 'IN_PROGRESS' && reportApproved) {
await Promise.all(
testPlanReports?.map(report =>
promoteVendorReviewStatus({
variables: { testReportId: report.id, reviewStatus }
})
)
);
setReviewStatus('APPROVED');
}
const setVendorReviewStatusToApproved = async () => {
const results = await Promise.all(
testPlanReports?.map(report =>
promoteVendorReviewStatus({
variables: { testReportId: report.id, reviewStatus: 'APPROVED' }
})
)
);
const isApproved = results.every(
result =>
result.data.testPlanReport.promoteVendorReviewStatus.testPlanReport
.vendorReviewStatus === 'APPROVED'
);
setReviewStatus(
isApproved ? 'APPROVED' : testPlanReport.vendorReviewStatus
);
};

const submitApproval = async (status = '') => {
if (status === 'APPROVED') {
await updateVendorStatus(true);
await setVendorReviewStatusToApproved();
setConfirmationModal(
<ApprovedModal
handleAction={async () => {
Expand All @@ -193,23 +249,10 @@ const CandidateTestPlanRun = () => {

useEffect(() => {
if (data) {
if (
!tests[0].viewers?.find(viewer => viewer.username === data.me.username)
) {
addViewerToTest(tests[0].id).then(() => {
setFirstTimeViewing(true);
});
}
const viewedTests = [
tests[0].id,
...tests
.filter(test =>
test.viewers?.find(viewer => viewer.username === data.me.username)
)
.map(test => test.id)
];
const viewedTests =
vendorApprovalStatusData?.vendorApprovalStatus?.viewedTests || [];
setViewedTests(viewedTests);
setReviewStatus(vendorReviewStatus);
setReviewStatus(testPlanReport.vendorReviewStatus);

const bools = testPlanReports.map(() => false);
setShowBrowserBools(bools);
Expand All @@ -224,11 +267,10 @@ const CandidateTestPlanRun = () => {
setTestsLength(tests.length);
setShowBrowserClicks(browserClicks);
}
}, [data]);
}, [data, vendorApprovalStatusData]);

useEffect(() => {
if (data) {
updateVendorStatus();
updateTestViewed();
setIsFirstTest(currentTestIndex === 0);
if (tests?.length === 1) setIsLastTest(true);
Expand All @@ -242,6 +284,11 @@ const CandidateTestPlanRun = () => {
if (isLastTest && tests?.length !== 1) finishButtonRef.current.focus();
}, [isLastTest]);

useEffect(() => {
if (viewedTests.length > 0 && currentTest?.id)
addViewerToTest(currentTest.id).then(() => setFirstTimeViewing(true));
}, [viewedTests]);

if (error)
return (
<PageStatus
Expand All @@ -263,56 +310,18 @@ const CandidateTestPlanRun = () => {

if (!data) return null;

const atMap = {
1: 'JAWS',
2: 'NVDA',
3: 'VoiceOver for macOS'
};
const at = atMap[atId];

const testPlanReports = [];
const _testPlanReports = data.testPlanReports;
if (_testPlanReports.length === 0) return <Navigate to="/404" replace />;

const getLatestReleasedAtVersionReport = arr => {
return arr.reduce((o1, o2) => {
return new Date(o1.latestAtVersionReleasedAt.releasedAt) >
new Date(o2.latestAtVersionReleasedAt.releasedAt)
? o1
: o2;
});
};

Object.keys(atMap).forEach(k => {
const group = _testPlanReports.filter(t => t.browser.id == k);
if (group.length) {
const latestReport = getLatestReleasedAtVersionReport(group);
testPlanReports.push(latestReport);
}
});

const testPlanReport = testPlanReports.find(
each =>
each.testPlanVersion.id === testPlanVersionId ||
testPlanVersionIds.includes(each.testPlanVersion.id)
);

const tests = testPlanReport.runnableTests.map((test, index) => ({
...test,
index,
seq: index + 1
}));

const currentTest = tests[currentTestIndex];
const { testPlanVersion, vendorReviewStatus } = testPlanReport;
const { testPlanVersion } = testPlanReport;
const { recommendedPhaseTargetDate } = testPlanVersion;

const vendorReviewStatusMap = {
READY: 'Ready',
IN_PROGRESS: 'In Progress',
APPROVED: 'Approved'
};

const reviewStatusText = vendorReviewStatusMap[reviewStatus];

const targetCompletionDate = dates.convertDateToString(
Expand Down Expand Up @@ -752,6 +761,7 @@ const CandidateTestPlanRun = () => {
changesRequestedGithubUrl={changesRequestedGithubUrl}
handleAction={submitApproval}
handleHide={() => setFeedbackModalShowing(false)}
isAdmin={isAdmin}
/>
)}
{!!confirmationModal && confirmationModal}
Expand Down
25 changes: 19 additions & 6 deletions client/components/CandidateReview/CandidateTestPlanRun/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
} from '@components/common/fragments';

export const ADD_VIEWER_MUTATION = gql`
mutation AddViewerMutation($testPlanVersionId: ID!, $testId: ID!) {
addViewer(testPlanVersionId: $testPlanVersionId, testId: $testId) {
mutation AddViewerMutation($testId: ID!, $testPlanReportId: ID!) {
addViewer(testId: $testId, testPlanReportId: $testPlanReportId) {
username
}
}
Expand All @@ -25,7 +25,7 @@ export const PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION = gql`
$reviewStatus: String!
) {
testPlanReport(id: $testReportId) {
promoteVendorReviewStatus(vendorReviewStatus: $reviewStatus) {
promoteVendorReviewStatus(reviewStatus: $reviewStatus) {
testPlanReport {
id
vendorReviewStatus
Expand All @@ -35,6 +35,22 @@ export const PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION = gql`
}
`;

export const VENDOR_APPROVAL_STATUS_QUERY = gql`
query VendorApprovalStatusQuery(
$userId: ID!
$vendorId: ID!
$testPlanReportId: ID!
) {
vendorApprovalStatus(
userId: $userId
vendorId: $vendorId
testPlanReportId: $testPlanReportId
) {
viewedTests
}
}
`;

export const CANDIDATE_REPORTS_QUERY = gql`
${AT_FIELDS}
${AT_VERSION_FIELDS}
Expand Down Expand Up @@ -93,9 +109,6 @@ export const CANDIDATE_REPORTS_QUERY = gql`
runnableTests {
...TestFieldsSimple
renderableContent
viewers {
username
}
}
finalizedTestResults {
...TestResultFields
Expand Down
Loading
Loading