diff --git a/src/components/Landing/index.js b/src/components/Landing/index.js index d0daff8db..5a9b64b5d 100644 --- a/src/components/Landing/index.js +++ b/src/components/Landing/index.js @@ -547,6 +547,7 @@ export default class Landing extends Component { report: summary.ReportSummary, survey: summary.SurveySummary, }} + sectionFlags={sectionFlags} > )} {/* other tab panel as specified here */} diff --git a/src/components/Landing/utility.js b/src/components/Landing/utility.js index 6c76ec083..40f7eec2b 100644 --- a/src/components/Landing/utility.js +++ b/src/components/Landing/utility.js @@ -26,7 +26,10 @@ export function processEndPoint(endpoint, endpointParams) { if (!endpoint) return ""; const params = endpointParams ? endpointParams : {}; return endpoint - .replace(`{process.env.${ENV_VAR_PREFIX}_CONF_API_URL}`, getEnvConfidentialAPIURL()) + .replace( + `{process.env.${ENV_VAR_PREFIX}_CONF_API_URL}`, + getEnvConfidentialAPIURL() + ) .replace("{process.env.PUBLIC_URL}", getEnv("PUBLIC_URL")) .replace("{patientId}", params.patientId); } @@ -149,7 +152,7 @@ export function getDemoData(section, params) { } export function getProcessedSummaryData(summary, summaryMap) { - const sectionFlags = {}; + let sectionFlags = {}; const sectionKeys = Object.keys(summaryMap || {}); let flaggedCount = 0; diff --git a/src/components/Report/components/MedicationList.js b/src/components/Report/components/MedicationList.js new file mode 100644 index 000000000..7ae797ad4 --- /dev/null +++ b/src/components/Report/components/MedicationList.js @@ -0,0 +1,8 @@ +import React, { Component } from "react"; +import Table from "./Table"; + +export default class MedicationList extends Component { + render() { + return
; + } +} diff --git a/src/components/Report/components/Table.js b/src/components/Report/components/Table.js index 64c74bb48..4696b75c6 100644 --- a/src/components/Report/components/Table.js +++ b/src/components/Report/components/Table.js @@ -46,9 +46,12 @@ export default class Table extends Component { id: headerID, Header: () => { if (headerKey.omitHeader) return ""; + const displayName = header.replace(/_/g, " "); if (headerKey.header) - return

{header}

; - return {header}; + return

{displayName}

; + return ( + {displayName} + ); }, accessor: (entry) => { let value = entry[headerKey]; @@ -64,7 +67,9 @@ export default class Table extends Component { return ( {value - ? value + ? typeof value === "object" + ? value.toString() + : value : headerKey.default ? headerKey.default : entry[headerKey.key]} diff --git a/src/components/Report/index.js b/src/components/Report/index.js index a71c75edf..46568337b 100644 --- a/src/components/Report/index.js +++ b/src/components/Report/index.js @@ -8,6 +8,7 @@ import SideNav from "../SideNav"; import Version from "../../elements/Version"; import reportSummarySections from "../../config/report_config"; import { + dedupArrObjects, getQuestionnaireDescription, getQuestionnaireTitle, isEmptyArray, @@ -100,6 +101,55 @@ export default class Report extends Component { ); } + getSectionFlags(section) { + if (isEmptyArray(section.flags)) return null; + const sectionFlags = this.props.sectionFlags; + if (!sectionFlags) return null; + return dedupArrObjects( + section.flags + .map((o) => { + if ( + sectionFlags[o.parentKey] && + sectionFlags[o.parentKey][o.dataKey] + ) { + return sectionFlags[o.parentKey][o.dataKey]; + } + return null; + }) + .filter((o) => !!o) + .flat() + .map((o) => { + return { + flagText: o.flagText, + flagClass: o.flagClass, + }; + }), + "flagText" + ); + } + renderFlagIconsInHeader(section) { + const flagObj = this.getSectionFlags(section); + if (isEmptyArray(flagObj)) return null; + return ( +
+ {flagObj.map((o, index) => { + return ( +
+ +
+ ); + })} +
+ ); + } renderSectionBody(summaryData, section) { const surveySummaryData = reportUtil.getSurveySummaryData(summaryData); const scoringData = this.getScoringData(surveySummaryData); @@ -115,6 +165,9 @@ export default class Report extends Component { bodyDiagramData: bodyDiagramData, procedureData: procedureData, referralData: referralData, + reportData: reportData, + medicationListData: reportUtil.getMedicationListData(reportData), + sectionFlags: this.props.sectionFlags, }; if (section.component) { return
{section.component(propData)}
; @@ -142,6 +195,7 @@ export default class Report extends Component { surveyData: matchedData, })} {this.renderSubSectionAnchor(item)} + {this.renderSubSectionFlags(item)} ); })} @@ -169,10 +223,30 @@ export default class Report extends Component { > {this.renderSubSectionTitle(item, summaryData)} {this.renderSubSectionInfo(item, summaryData)} + {this.renderFlagIconsInHeader(item)} ); } + renderSubSectionFlags(section) { + const flagObj = this.getSectionFlags(section); + if (isEmptyArray(flagObj)) return null; + return ( +
+ {flagObj.map((o, index) => { + return ( +
+ + {o.flagText} +
+ ); + })} +
+ ); + } renderSubSectionTitle(item, summaryData) { const title = summaryData?.Questionnaire ? getQuestionnaireTitle(summaryData?.Questionnaire) @@ -297,4 +371,5 @@ export default class Report extends Component { Report.propTypes = { summaryData: PropTypes.object, + sectionFlags: PropTypes.object, }; diff --git a/src/components/Report/utility.js b/src/components/Report/utility.js index fbc8c4070..9d25eb3bf 100644 --- a/src/components/Report/utility.js +++ b/src/components/Report/utility.js @@ -21,6 +21,11 @@ export function getReferralData(summaryData) { if (!summaryData || !summaryData.TreatmentHistory) return null; return summaryData.TreatmentHistory.Referrals; } +export function getMedicationListData(summaryData) { + if (!summaryData) return null; + if (summaryData.MedicationList) return summaryData.MedicationList; + return null; +} export function hasReportSummaryData(summaryData) { if (!summaryData) return false; let sectionData = []; diff --git a/src/components/Summary.js b/src/components/Summary.js index 27b6f16c8..18d7445d4 100644 --- a/src/components/Summary.js +++ b/src/components/Summary.js @@ -504,7 +504,11 @@ export default class Summary extends Component { )} - + ); } @@ -556,7 +560,11 @@ export default class Summary extends Component {
{panel.alertsData.title}
{alertsContent}
- + ); } diff --git a/src/components/graph/ReportOverviewGraph.js b/src/components/graph/ReportOverviewGraph.js index 7dab6602b..f63f3c858 100644 --- a/src/components/graph/ReportOverviewGraph.js +++ b/src/components/graph/ReportOverviewGraph.js @@ -722,7 +722,7 @@ export default class ReportOverviewGraph extends Component { const inYears = unit === "year"; const min = arrNum[0]; const max = arrNum[arrNum.length - 1]; - const shouldRotate = (inYears && max >= 10); + const shouldRotate = inYears && max >= 10; const revArrNum = JSON.parse(JSON.stringify(arrNum)).reverse(); const arrDisplayValues = arrNum.map((item, index) => { const prevItem = revArrNum.find( diff --git a/src/config/report_config.js b/src/config/report_config.js index 3221ddd1d..8cd773770 100644 --- a/src/config/report_config.js +++ b/src/config/report_config.js @@ -9,6 +9,7 @@ import ResponsesSummary from "../components/Report/components/ResponsesSummary"; import RankedResponses from "../components/Report/components/RankedResponses"; import Procedures from "../components/Report/components/Procedures"; import Referrals from "../components/Report/components/Referrals"; +import MedicationList from "../components/Report/components/MedicationList"; const iconProps = { width: 35, @@ -27,6 +28,7 @@ export const STOP_DATA_KEY = "PAINTRACKER-STOP"; export const TRT_DATA_KEY = "PAINTRACKER-TRT"; export const PROCECURE_DATA_KEY = "PROCEDURE_HISTORY"; export const REFERRAL_DATA_KEY = "REFERRAL_HISTORY"; +export const MEDICATION_LIST_DATA_KEY = "MedicationList"; const reportConfig = [ { @@ -391,10 +393,6 @@ const reportConfig = [ ), }, + { + dataKey: MEDICATION_LIST_DATA_KEY, + dataKeySource: "ReportSummary", + title: "Medications", + flags: [ + { + parentKey: "PDMPMedications", + dataKey: "PDMPMedications" + } + ], + component: (props) => ( + + ), + }, { dataKey: TRT_DATA_KEY, title: "Patient-reported Treatments Questionnaire", diff --git a/src/cql/r4/Report_LogicLibrary.cql b/src/cql/r4/Report_LogicLibrary.cql index 4994061d3..3b127bd18 100644 --- a/src/cql/r4/Report_LogicLibrary.cql +++ b/src/cql/r4/Report_LogicLibrary.cql @@ -1,11 +1,15 @@ library ReportLogicLibrary version '1.0.0' using FHIR version '4.0.0' +// The FHIRHelpers library provides common functions for simplifying interaction w/ the FHIR R4 data model. +include FHIRHelpers version '4.0.0' called FHIRHelpers // ----------------------------------------------------------------------------- // PATIENT INFORMATION // ----------------------------------------------------------------------------- context Patient +//system url identifier used to identify resources, e.g. MedicationRequest, from PDMP +define UWMC_SYSTEM_VALUE: 'http://www.uwmedicine.org/medication_id' // ## Re-usable functions ## // Returns the first-found display text for a CodeableConcept, looking first at the `text` attribute, then the @@ -46,14 +50,20 @@ define ReferralCodeList: { // REPORT LOGIC, e.g. Procedure, Condition, ServiceRequest //------------------------------------------------------------------------------ +define function GetEncounterLocation(enc_id String): + First(([Encounter] E where E.id = enc_id) P return P.location.location.display.value) + define ProcedureHistory: ([Procedure] ProcList where ProcList.status.value = 'completed' and not (ReferralCodeList contains ConceptCode(ProcList.code))) P - let performDate: (P.performed as FHIR.dateTime).value + let + performDate: (P.performed as FHIR.dateTime).value, + encounterReference: if P.encounter is not null and P.encounter.reference is not null then P.encounter.reference.value else null return { Name: ConceptText(P.code), Date: performDate, DateText: DateTimeText(P.performed as FHIR.dateTime), + Location: if encounterReference is not null then GetEncounterLocation(Split(encounterReference, '/')[1]) else null, CPT_CODE: ConceptCode(P.code) } sort by Date desc @@ -61,18 +71,38 @@ define ProcedureHistory: define ReferralHistory: ([Procedure] ProcList where ProcList.status.value = 'completed' and (ReferralCodeList contains ConceptCode(ProcList.code))) P - let performDate: (P.performed as FHIR.dateTime).value + let + performDate: (P.performed as FHIR.dateTime).value, + encounterReference: if P.encounter is not null and P.encounter.reference is not null then P.encounter.reference.value else null return { Name: ConceptText(P.code), Date: performDate, DateText: DateTimeText(P.performed as FHIR.dateTime), + Location: if encounterReference is not null then GetEncounterLocation(Split(encounterReference, '/')[1]) else null, CPT_CODE: ConceptCode(P.code) } sort by Date desc +define MedicationList: + [MedicationRequest] M + // within 2 years + where M.identifier[0].system = UWMC_SYSTEM_VALUE + and M.authoredOn.value <= Today() + and M.authoredOn.value >= (Today() - 2 year) + return { + Name: ConceptText(M.medication as FHIR.CodeableConcept), + Start: DateTimeText(M.authoredOn), + Dosage: M.dosageInstruction.text.value, + Quantity: if M.dispenseRequest is not null and M.dispenseRequest.quantity is not null then M.dispenseRequest.quantity.value.value else null, + Prescriber: M.requester.display.value, + Authored: M.authoredOn.value + } + sort by Authored desc + define Summary: { TreatmentHistory: { Procedures: ProcedureHistory, Referrals: ReferralHistory - } + }, + MedicationList: MedicationList } diff --git a/src/cql/r4/Report_LogicLibrary.json b/src/cql/r4/Report_LogicLibrary.json index 5c8e555b9..7a7dca498 100644 --- a/src/cql/r4/Report_LogicLibrary.json +++ b/src/cql/r4/Report_LogicLibrary.json @@ -22,6 +22,13 @@ "version" : "4.0.0" } ] }, + "includes" : { + "def" : [ { + "localIdentifier" : "FHIRHelpers", + "path" : "FHIRHelpers", + "version" : "4.0.0" + } ] + }, "contexts" : { "def" : [ { "name" : "Patient" @@ -38,6 +45,15 @@ "type" : "Retrieve" } } + }, { + "name" : "UWMC_SYSTEM_VALUE", + "context" : "Patient", + "accessLevel" : "Public", + "expression" : { + "valueType" : "{urn:hl7-org:elm-types:r1}String", + "value" : "http://www.uwmedicine.org/medication_id", + "type" : "Literal" + } }, { "name" : "ConceptText", "context" : "Patient", @@ -208,6 +224,155 @@ "type" : "Literal" } ] } + }, { + "name" : "GetEncounterLocation", + "context" : "Patient", + "accessLevel" : "Public", + "type" : "FunctionDef", + "expression" : { + "type" : "First", + "source" : { + "type" : "Query", + "source" : [ { + "alias" : "P", + "expression" : { + "type" : "Query", + "source" : [ { + "alias" : "E", + "expression" : { + "dataType" : "{http://hl7.org/fhir}Encounter", + "type" : "Retrieve" + } + } ], + "relationship" : [ ], + "where" : { + "type" : "Equal", + "operand" : [ { + "name" : "ToString", + "libraryName" : "FHIRHelpers", + "type" : "FunctionRef", + "operand" : [ { + "path" : "id", + "scope" : "E", + "type" : "Property" + } ] + }, { + "name" : "enc_id", + "type" : "OperandRef" + } ] + } + } + } ], + "relationship" : [ ], + "return" : { + "expression" : { + "type" : "Query", + "source" : [ { + "alias" : "$this", + "expression" : { + "type" : "Query", + "source" : [ { + "alias" : "$this", + "expression" : { + "type" : "Query", + "source" : [ { + "alias" : "$this", + "expression" : { + "path" : "location", + "scope" : "P", + "type" : "Property" + } + } ], + "where" : { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "location", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + }, + "return" : { + "distinct" : false, + "expression" : { + "path" : "location", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + } + } ], + "where" : { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "display", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + }, + "return" : { + "distinct" : false, + "expression" : { + "path" : "display", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + } + } ], + "where" : { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "value", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + }, + "return" : { + "distinct" : false, + "expression" : { + "path" : "value", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + } + } + } + }, + "operand" : [ { + "name" : "enc_id", + "operandTypeSpecifier" : { + "name" : "{urn:hl7-org:elm-types:r1}String", + "type" : "NamedTypeSpecifier" + } + } ] }, { "name" : "ProcedureHistory", "context" : "Patient", @@ -283,6 +448,59 @@ } } } + }, { + "identifier" : "encounterReference", + "expression" : { + "type" : "If", + "condition" : { + "type" : "And", + "operand" : [ { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "encounter", + "scope" : "P", + "type" : "Property" + } + } + }, { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "reference", + "type" : "Property", + "source" : { + "path" : "encounter", + "scope" : "P", + "type" : "Property" + } + } + } + } ] + }, + "then" : { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "reference", + "type" : "Property", + "source" : { + "path" : "encounter", + "scope" : "P", + "type" : "Property" + } + } + }, + "else" : { + "asType" : "{urn:hl7-org:elm-types:r1}String", + "type" : "As", + "operand" : { + "type" : "Null" + } + } + } } ], "relationship" : [ ], "return" : { @@ -324,6 +542,57 @@ } } ] } + }, { + "name" : "Location", + "value" : { + "type" : "If", + "condition" : { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "name" : "encounterReference", + "type" : "QueryLetRef" + } + } + }, + "then" : { + "name" : "GetEncounterLocation", + "type" : "FunctionRef", + "operand" : [ { + "type" : "Indexer", + "operand" : [ { + "type" : "Split", + "stringToSplit" : { + "name" : "encounterReference", + "type" : "QueryLetRef" + }, + "separator" : { + "valueType" : "{urn:hl7-org:elm-types:r1}String", + "value" : "/", + "type" : "Literal" + } + }, { + "valueType" : "{urn:hl7-org:elm-types:r1}Integer", + "value" : "1", + "type" : "Literal" + } ] + } ] + }, + "else" : { + "type" : "As", + "operand" : { + "type" : "Null" + }, + "asTypeSpecifier" : { + "type" : "ListTypeSpecifier", + "elementType" : { + "name" : "{urn:hl7-org:elm-types:r1}String", + "type" : "NamedTypeSpecifier" + } + } + } + } }, { "name" : "CPT_CODE", "value" : { @@ -418,6 +687,59 @@ } } } + }, { + "identifier" : "encounterReference", + "expression" : { + "type" : "If", + "condition" : { + "type" : "And", + "operand" : [ { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "encounter", + "scope" : "P", + "type" : "Property" + } + } + }, { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "reference", + "type" : "Property", + "source" : { + "path" : "encounter", + "scope" : "P", + "type" : "Property" + } + } + } + } ] + }, + "then" : { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "reference", + "type" : "Property", + "source" : { + "path" : "encounter", + "scope" : "P", + "type" : "Property" + } + } + }, + "else" : { + "asType" : "{urn:hl7-org:elm-types:r1}String", + "type" : "As", + "operand" : { + "type" : "Null" + } + } + } } ], "relationship" : [ ], "return" : { @@ -459,6 +781,57 @@ } } ] } + }, { + "name" : "Location", + "value" : { + "type" : "If", + "condition" : { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "name" : "encounterReference", + "type" : "QueryLetRef" + } + } + }, + "then" : { + "name" : "GetEncounterLocation", + "type" : "FunctionRef", + "operand" : [ { + "type" : "Indexer", + "operand" : [ { + "type" : "Split", + "stringToSplit" : { + "name" : "encounterReference", + "type" : "QueryLetRef" + }, + "separator" : { + "valueType" : "{urn:hl7-org:elm-types:r1}String", + "value" : "/", + "type" : "Literal" + } + }, { + "valueType" : "{urn:hl7-org:elm-types:r1}Integer", + "value" : "1", + "type" : "Literal" + } ] + } ] + }, + "else" : { + "type" : "As", + "operand" : { + "type" : "Null" + }, + "asTypeSpecifier" : { + "type" : "ListTypeSpecifier", + "elementType" : { + "name" : "{urn:hl7-org:elm-types:r1}String", + "type" : "NamedTypeSpecifier" + } + } + } + } }, { "name" : "CPT_CODE", "value" : { @@ -481,6 +854,288 @@ } ] } } + }, { + "name" : "MedicationList", + "context" : "Patient", + "accessLevel" : "Public", + "expression" : { + "type" : "Query", + "source" : [ { + "alias" : "M", + "expression" : { + "dataType" : "{http://hl7.org/fhir}MedicationRequest", + "type" : "Retrieve" + } + } ], + "relationship" : [ ], + "where" : { + "type" : "And", + "operand" : [ { + "type" : "And", + "operand" : [ { + "type" : "Equal", + "operand" : [ { + "name" : "ToString", + "libraryName" : "FHIRHelpers", + "type" : "FunctionRef", + "operand" : [ { + "path" : "system", + "type" : "Property", + "source" : { + "type" : "Indexer", + "operand" : [ { + "path" : "identifier", + "scope" : "M", + "type" : "Property" + }, { + "valueType" : "{urn:hl7-org:elm-types:r1}Integer", + "value" : "0", + "type" : "Literal" + } ] + } + } ] + }, { + "name" : "UWMC_SYSTEM_VALUE", + "type" : "ExpressionRef" + } ] + }, { + "type" : "LessOrEqual", + "operand" : [ { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "authoredOn", + "scope" : "M", + "type" : "Property" + } + }, { + "type" : "ToDateTime", + "operand" : { + "type" : "Today" + } + } ] + } ] + }, { + "type" : "GreaterOrEqual", + "operand" : [ { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "authoredOn", + "scope" : "M", + "type" : "Property" + } + }, { + "type" : "ToDateTime", + "operand" : { + "type" : "Subtract", + "operand" : [ { + "type" : "Today" + }, { + "value" : 2, + "unit" : "year", + "type" : "Quantity" + } ] + } + } ] + } ] + }, + "return" : { + "expression" : { + "type" : "Tuple", + "element" : [ { + "name" : "Name", + "value" : { + "name" : "ConceptText", + "type" : "FunctionRef", + "operand" : [ { + "strict" : false, + "type" : "As", + "operand" : { + "path" : "medication", + "scope" : "M", + "type" : "Property" + }, + "asTypeSpecifier" : { + "name" : "{http://hl7.org/fhir}CodeableConcept", + "type" : "NamedTypeSpecifier" + } + } ] + } + }, { + "name" : "Start", + "value" : { + "name" : "DateTimeText", + "type" : "FunctionRef", + "operand" : [ { + "path" : "authoredOn", + "scope" : "M", + "type" : "Property" + } ] + } + }, { + "name" : "Dosage", + "value" : { + "type" : "Query", + "source" : [ { + "alias" : "$this", + "expression" : { + "type" : "Query", + "source" : [ { + "alias" : "$this", + "expression" : { + "path" : "dosageInstruction", + "scope" : "M", + "type" : "Property" + } + } ], + "where" : { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "text", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + }, + "return" : { + "distinct" : false, + "expression" : { + "path" : "text", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + } + } ], + "where" : { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "value", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + }, + "return" : { + "distinct" : false, + "expression" : { + "path" : "value", + "type" : "Property", + "source" : { + "name" : "$this", + "type" : "AliasRef" + } + } + } + } + }, { + "name" : "Quantity", + "value" : { + "type" : "If", + "condition" : { + "type" : "And", + "operand" : [ { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "dispenseRequest", + "scope" : "M", + "type" : "Property" + } + } + }, { + "type" : "Not", + "operand" : { + "type" : "IsNull", + "operand" : { + "path" : "quantity", + "type" : "Property", + "source" : { + "path" : "dispenseRequest", + "scope" : "M", + "type" : "Property" + } + } + } + } ] + }, + "then" : { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "quantity", + "type" : "Property", + "source" : { + "path" : "dispenseRequest", + "scope" : "M", + "type" : "Property" + } + } + } + }, + "else" : { + "asType" : "{urn:hl7-org:elm-types:r1}Decimal", + "type" : "As", + "operand" : { + "type" : "Null" + } + } + } + }, { + "name" : "Prescriber", + "value" : { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "display", + "type" : "Property", + "source" : { + "path" : "requester", + "scope" : "M", + "type" : "Property" + } + } + } + }, { + "name" : "Authored", + "value" : { + "path" : "value", + "type" : "Property", + "source" : { + "path" : "authoredOn", + "scope" : "M", + "type" : "Property" + } + } + } ] + } + }, + "sort" : { + "by" : [ { + "direction" : "desc", + "path" : "Authored", + "type" : "ByColumn" + } ] + } + } }, { "name" : "Summary", "context" : "Patient", @@ -505,6 +1160,12 @@ } } ] } + }, { + "name" : "MedicationList", + "value" : { + "name" : "MedicationList", + "type" : "ExpressionRef" + } } ] } } ] diff --git a/src/helpers/utility.js b/src/helpers/utility.js index 975930896..4cfd5a8ad 100644 --- a/src/helpers/utility.js +++ b/src/helpers/utility.js @@ -696,3 +696,14 @@ export function getPatientSearchURL(shouldClearSession) { export function getEnvVersionString() { return getEnv(`${ENV_VAR_PREFIX}_VERSION_STRING`); } + +export function dedupArrObjects(arr, key) { + if (isEmptyArray(arr)) return null; + if (!key) return arr; + return arr.reduce((acc, obj) => { + if (!acc.find(item => item[key] === obj[key])) { + acc.push(obj); + } + return acc; + }, []); +} diff --git a/src/styles/components/_Report.scss b/src/styles/components/_Report.scss index 1d60a9f2f..cc7361644 100644 --- a/src/styles/components/_Report.scss +++ b/src/styles/components/_Report.scss @@ -7,6 +7,28 @@ $selector-box-shadow: 0 2px 2px #383e40; background-color: $color-gray-lightest; border-top: 4px solid $color-blue; } + .flags-container { + .flag-item { + display: flex; + align-items: center; + gap: 8px; + } + .flag { + color: $color-red-darker; + font-size: 1.2rem; + &.info { + color: $color-info; + } + &:hover { + color: $color-red; + cursor: pointer; + } + &.info:hover { + color: $color-info-light; + cursor: auto; + } + } + } .summary__nav { padding: 64px 0 24px 0px; .title-text-container { @@ -51,15 +73,29 @@ $selector-box-shadow: 0 2px 2px #383e40; min-height: 72px; background: $color-white; padding: 8px; + .flags-container { + margin-left: 24px; + margin-right: 24px; + margin-bottom: 16px; + } } .sub-section { border: 1px solid $color-gray-lighter; margin-bottom: 8px; margin-top: 8px; &__header { - padding: 0 20px 4px; + padding: 0 20px 12px; margin-block-start: 0.5em; margin-block-end: 0.5em; + display: flex; + align-items: center; + gap: 8px; + .flags-container { + margin: 0; + .flag { + font-size: 1rem; + } + } } &__anchor { width: 2px; @@ -69,7 +105,6 @@ $selector-box-shadow: 0 2px 2px #383e40; display: flex; align-items: center; margin-block-start: 0; - margin-block-end: 8px; } &:not(.sub-section-notitle):first-of-type { margin-top: 0; @@ -188,7 +223,7 @@ $selector-box-shadow: 0 2px 2px #383e40; } .rt-th:has(.col-Name_column), .rt-td:has(.col-Name_column) { - min-width: 70%; + min-width: 40%; } } } diff --git a/src/utils/executeELM.js b/src/utils/executeELM.js index 0c4c6171f..6bfc052c8 100644 --- a/src/utils/executeELM.js +++ b/src/utils/executeELM.js @@ -152,7 +152,10 @@ async function executeELM(collector, oResourceTypes) { if (!evalResults[PATIENT_SUMMARY_KEY]) { evalResults[PATIENT_SUMMARY_KEY] = {}; } - Promise.allSettled([executeELMForReport(patientBundle), ...elmLibs]).then( + Promise.allSettled([ + executeELMForReport(patientBundle), + ...elmLibs, + ]).then( (results) => { evalResults[PATIENT_SUMMARY_KEY]["ReportSummary"] = results[0].status !== "rejected" ? results[0].value : null; @@ -190,9 +193,12 @@ async function executeELMForReport(bundle) { console.log("Issue occurred loading ELM lib for reoirt", e); r4ReportCommonELM = null; }); + if (!r4ReportCommonELM) return null; - let reportLib = new cql.Library(r4ReportCommonELM); + let reportLib = new cql.Library(r4ReportCommonELM, new cql.Repository({ + FHIRHelpers: r4HelpersELM, + })); const reportExecutor = new cql.Executor( reportLib, new cql.CodeService(valueSetDB)