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

[GLT-4252] Case QC Report improvements for stopped cases #226

Merged
merged 1 commit into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions changes/change_case_qc_stopped.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The Case QC Report now displays "CASE STOPPED" along with the stop reason if the case is stopped,
and correctly shows incomplete sign-offs as "N/A (case stopped)"
81 changes: 66 additions & 15 deletions ts/case-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
deliverableTypeLabels,
} from "./data/case";
import { qcStatuses } from "./data/qc-status";
import { makeTextDiv } from "./util/html-utils";
import { makeTextDiv, styleText } from "./util/html-utils";
import {
addMetricValueContents,
getFirstReviewStatus,
Expand All @@ -27,10 +27,7 @@ import {
subcategoryApplies as sampleSubcategoryApplies,
} from "./data/sample";
import { addTextDiv, makeNameDiv } from "./util/html-utils";
import {
getBooleanMetricValueIcon,
getMetricRequirementText,
} from "./util/metrics";
import { getMetricRequirementText } from "./util/metrics";
import { get } from "./util/requests";
import { siteConfig } from "./util/site-config";
import { urls } from "./util/urls";
Expand All @@ -42,6 +39,7 @@ interface ReportSample {
metricCategory: MetricCategory;
metricSubcategory: MetricSubcategory;
caseAssayId: number;
caseStopped: boolean;
}

interface ReportAnalysisReview {
Expand All @@ -50,6 +48,7 @@ interface ReportAnalysisReview {
deliverable: CaseDeliverable;
metricCategory: MetricCategory;
metricSubcategory: MetricSubcategory;
caseStopped: boolean;
}

const attributes: AttributeDefinition<Case>[] = [
Expand All @@ -59,6 +58,21 @@ const attributes: AttributeDefinition<Case>[] = [
fragment.appendChild(
makeNameDiv(object.id, undefined, urls.dimsum.case(object.id))
);
if (object.requisition.stopped) {
const stopDiv = document.createElement("div");
const stopText = document.createElement("span");
stopText.innerText = "CASE STOPPED";
styleText(stopText, "error");
stopDiv.appendChild(stopText);

if (object.requisition.stopReason) {
const reasonText = document.createElement("span");
reasonText.innerText = ` (${object.requisition.stopReason})`;
stopDiv.appendChild(reasonText);
}

fragment.appendChild(stopDiv);
}
},
},
{
Expand Down Expand Up @@ -230,14 +244,20 @@ const sampleGateMetricsDefinition: TableDefinition<ReportSample, Metric> = {
{
title: "QC Metric Sign-Off",
addParentContents(object, fragment) {
displayQcSignOff(fragment, getRunOrSampleLevel(object));
displayQcSignOff(
fragment,
getRunOrSampleLevel(object),
object.caseStopped
);
addAssayMismatchText(fragment, object);
},
getCellHighlight(object) {
const qcable = getRunOrSampleLevel(object);
const reviewStatus = getFirstReviewStatus(qcable).cellStatus;
if (reviewStatus) {
return reviewStatus;
const reviewStatus = getFirstReviewStatus(qcable);
if (reviewStatus === qcStatuses.qc && object.caseStopped) {
return "na";
} else if (reviewStatus.cellStatus) {
return reviewStatus.cellStatus;
} else if (!object.sample.assayIds?.includes(object.caseAssayId)) {
return "warning";
}
Expand All @@ -248,7 +268,11 @@ const sampleGateMetricsDefinition: TableDefinition<ReportSample, Metric> = {
title: "QC Stage Sign-Off",
addParentContents(object, fragment) {
if (object.sample.run) {
displayDataReviewSignOff(fragment, getRunOrSampleLevel(object));
displayDataReviewSignOff(
fragment,
getRunOrSampleLevel(object),
object.caseStopped
);
addAssayMismatchText(fragment, object);
} else {
addText(fragment, "No second review required");
Expand All @@ -261,7 +285,11 @@ const sampleGateMetricsDefinition: TableDefinition<ReportSample, Metric> = {
if (object.sample.run) {
const qcable = getRunOrSampleLevel(object);
if (!qcable.dataReviewDate) {
return qcStatuses.dataReview.cellStatus;
if (object.caseStopped) {
return "na";
} else {
return qcStatuses.dataReview.cellStatus;
}
} else if (qcable.dataReviewPassed) {
return assayStatus;
} else {
Expand Down Expand Up @@ -393,6 +421,7 @@ const analysisReviewMetricsDefinition: TableDefinition<
const deliverable = object.deliverable;
displaySignOff(
fragment,
object.caseStopped,
deliverable.analysisReviewQcPassed,
undefined,
deliverable.analysisReviewQcUser,
Expand All @@ -401,8 +430,14 @@ const analysisReviewMetricsDefinition: TableDefinition<
);
},
getCellHighlight(object) {
return getDeliverableQcStatus(object.deliverable.analysisReviewQcPassed)
.cellStatus;
const status = getDeliverableQcStatus(
object.deliverable.analysisReviewQcPassed
);
if (status === qcStatuses.qc && object.caseStopped) {
return "na";
} else {
return status.cellStatus;
}
},
},
{
Expand All @@ -417,9 +452,14 @@ const analysisReviewMetricsDefinition: TableDefinition<
],
};

function displayQcSignOff(fragment: DocumentFragment, qcable: Qcable) {
function displayQcSignOff(
fragment: DocumentFragment,
qcable: Qcable,
caseStopped: boolean
) {
displaySignOff(
fragment,
caseStopped,
qcable.qcPassed,
qcable.qcReason,
qcable.qcUser,
Expand All @@ -428,9 +468,14 @@ function displayQcSignOff(fragment: DocumentFragment, qcable: Qcable) {
);
}

function displayDataReviewSignOff(fragment: DocumentFragment, qcable: Qcable) {
function displayDataReviewSignOff(
fragment: DocumentFragment,
qcable: Qcable,
caseStopped: boolean
) {
displaySignOff(
fragment,
caseStopped,
qcable.dataReviewPassed,
undefined,
qcable.dataReviewUser,
Expand All @@ -440,6 +485,7 @@ function displayDataReviewSignOff(fragment: DocumentFragment, qcable: Qcable) {

function displaySignOff(
fragment: DocumentFragment,
caseStopped: boolean,
qcPassed?: boolean,
qcReason?: string,
qcUser?: string,
Expand All @@ -461,6 +507,8 @@ function displaySignOff(
noteDiv.classList.add("mt-1em");
fragment.appendChild(noteDiv);
}
} else if (caseStopped) {
fragment.appendChild(document.createTextNode("N/A (case stopped)"));
} else {
addPendingText(fragment);
}
Expand Down Expand Up @@ -617,6 +665,7 @@ function getReportSamples(
metrics: [],
},
caseAssayId: kase.assayId,
caseStopped: kase.requisition.stopped,
},
];
}
Expand All @@ -628,6 +677,7 @@ function getReportSamples(
metricCategory: category,
metricSubcategory: subcategory,
caseAssayId: kase.assayId,
caseStopped: kase.requisition.stopped,
};
});
})
Expand Down Expand Up @@ -689,6 +739,7 @@ function getReportAnalysisReviews(kase: Case) {
deliverable: deliverable,
metricCategory: "ANALYSIS_REVIEW",
metricSubcategory: subcategory,
caseStopped: kase.requisition.stopped,
};
});
});
Expand Down
Loading