From 9d39684b6b8927a1c791ec79a0aa0b3466d326c3 Mon Sep 17 00:00:00 2001 From: KeeyanGhoreshi Date: Thu, 25 Jan 2024 14:50:14 -0500 Subject: [PATCH 1/4] reset submod to dev head --- src/rems-cds-hooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rems-cds-hooks b/src/rems-cds-hooks index da1a46d2..94a78e8c 160000 --- a/src/rems-cds-hooks +++ b/src/rems-cds-hooks @@ -1 +1 @@ -Subproject commit da1a46d22b1d5ded3afe1be73dde06d20d080b53 +Subproject commit 94a78e8cd27734938ec41858f8d0ca4028da5f21 From 700270801744ec5efdb44d63de991a9723c706b7 Mon Sep 17 00:00:00 2001 From: Joyce Quach <33106214+jtquach1@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:14:03 -0500 Subject: [PATCH 2/4] Fix typo (#130) --- .../CRD-DTR/IPledge/R4/resources/Questionnaire-R4-IPledge.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cds-library/CRD-DTR/IPledge/R4/resources/Questionnaire-R4-IPledge.json b/src/cds-library/CRD-DTR/IPledge/R4/resources/Questionnaire-R4-IPledge.json index e98d8807..f869aaea 100644 --- a/src/cds-library/CRD-DTR/IPledge/R4/resources/Questionnaire-R4-IPledge.json +++ b/src/cds-library/CRD-DTR/IPledge/R4/resources/Questionnaire-R4-IPledge.json @@ -415,7 +415,7 @@ }, { "linkId": "6.11", - "text": "10. I will not give blood while taking isotretinoin or for 1 moth after I stop taking isotretinoin. I understand that if someone who is pregnant gets my donated blood, their baby may be exposed to isotretinoin and may be born with serious birth defects.", + "text": "10. I will not give blood while taking isotretinoin or for 1 month after I stop taking isotretinoin. I understand that if someone who is pregnant gets my donated blood, their baby may be exposed to isotretinoin and may be born with serious birth defects.", "type": "boolean", "required": true }, From 193de2ead26e124a83f485d4ad2343e0e9da99ec Mon Sep 17 00:00:00 2001 From: Keeyan Date: Tue, 13 Feb 2024 10:49:10 -0500 Subject: [PATCH 3/4] make task on questionnaires (#132) * make task on questionnaires * fix hook issue * fix date * cover other link cases --- src/cards/Card.ts | 4 +- src/hooks/hookResources.ts | 99 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/src/cards/Card.ts b/src/cards/Card.ts index c79b9103..f269ae3d 100644 --- a/src/cards/Card.ts +++ b/src/cards/Card.ts @@ -5,12 +5,12 @@ interface Source { url: URL; icon?: URL; } -interface Action { +export interface Action { type: string; description: string; resource?: Resource | string; } -interface Suggestion { +export interface Suggestion { label: string; uuid?: string; actions: Action[]; diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index ff7588f6..2bea88c7 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -1,5 +1,13 @@ -import { MedicationRequest, Coding, FhirResource, Identifier } from 'fhir/r4'; -import Card, { Link } from '../cards/Card'; +import { + MedicationRequest, + Coding, + FhirResource, + Identifier, + Task, + Questionnaire, + Patient +} from 'fhir/r4'; +import Card, { Link, Suggestion, Action } from '../cards/Card'; import { HookPrefetch, OrderSignPrefetch, @@ -17,6 +25,16 @@ type HandleCallback = ( contextRequest: FhirResource | undefined, patient: FhirResource | undefined ) => Promise; + +interface Requirement { + name: string; + description: string; + stakeholderType: string; + createNewCase: boolean; + resourceId: string; + requiredToDispense: boolean; + appContext?: string; +} export interface CardRule { links: Link[]; summary?: string; @@ -364,6 +382,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } @@ -372,6 +393,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } else { @@ -380,6 +404,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } @@ -421,14 +448,14 @@ export async function handleCard( // verify ids if ( patient?.id && - patient.id.replace('Patient/', '') !== context.patientId.replace('Patient/', '') + patient.id.replace('Patient/', '') !== context.patientId?.replace('Patient/', '') ) { res.json(buildErrorCard('Context patientId does not match prefetch Patient ID')); return; } if ( practitioner?.id && - practitioner.id.replace('Practitioner/', '') !== context.userId.replace('Practitioner/', '') + practitioner.id.replace('Practitioner/', '') !== context.userId?.replace('Practitioner/', '') ) { res.json(buildErrorCard('Context userId does not match prefetch Practitioner ID')); return; @@ -463,3 +490,67 @@ export function handleHook( res.json(buildErrorCard('Unknown Error')); } } + +export function createQuestionnaireSuggestion( + card: Card, + requirement: Requirement, + patient: Patient +) { + if (requirement.appContext && requirement.appContext.includes('=')) { + const qArr = requirement.appContext.split('='); // break up into parts + let qUrl = null; + for (let i = 0; i < qArr.length; i++) { + if (qArr[i].toLowerCase() === 'questionnaire') { + if (i + 1 < qArr.length) { + // not at end of array + qUrl = qArr[i + 1]; + } + } + } + if (qUrl) { + const action: Action = { + type: 'create', + description: `Create task for "completion of ${requirement.name} Questionnaire`, + resource: createQuestionnaireCompletionTask(requirement.name, qUrl, patient) + }; + const suggestion: Suggestion = { + label: `Add "Completion of ${requirement.name} Questionnaire" to task list`, + actions: [action] + }; + card.addSuggestion(suggestion); + } + } +} +export function createQuestionnaireCompletionTask( + questionnaireTitle: string, + questionnaireUrl: string, + patient: Patient +) { + const taskResource: Task = { + resourceType: 'Task', + status: 'ready', + intent: 'order', + code: { + coding: [ + { + system: 'http://hl7.org/fhir/uv/sdc/CodeSystem/temp', + code: 'complete-questionnaire' + } + ] + }, + description: `Complete ${questionnaireTitle} Questionnaire`, + for: { + reference: `${patient.resourceType}/${patient.id}` + }, + authoredOn: `${new Date(Date.now()).toISOString()}`, + input: [ + { + type: { + text: 'questionnaire' + }, + valueCanonical: `${questionnaireUrl}` + } + ] + }; + return taskResource; +} From d32b27ca37b193c658f088422f3774a97a6edcad Mon Sep 17 00:00:00 2001 From: Keeyan Date: Thu, 22 Feb 2024 22:50:58 -0500 Subject: [PATCH 4/4] Update env readme (#133) * add descriptions * Update README.md --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c3d138df..143a710e 100644 --- a/README.md +++ b/README.md @@ -20,20 +20,20 @@ a) `REACT_APP_LAUNCH_URL=http://example.com PORT=6000 npm start` or b) by specif Following are a list of modifiable paths: -| URI Name | Default | -| --------------- | ------------------------------------------ | -| AUTH_SERVER_URI | `http://localhost:8090` | -| HTTPS_CERT_PATH | `server.cert` | -| HTTPS_KEY_PATH | `server.key` | -| LOGGING_LEVEL | `debug` | -| MONGO_DB_NAME | `remsadmin` | -| MONGO_URL | `mongodb://rems-user:pass@127.0.0.1:27017` | -| PORT | `8090` | -| RESOURCE_SERVER | `http://localhost:8090` | -| SMART_ENDPOINT | `http://localhost:4040/launch` | -| USE_HTTPS | `false` | -| VSAC_API_KEY | `changeMe` | -| WHITELIST | `http://localhost, http://localhost:3005` | +| URI Name | Default | Description | +| --------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------| +| AUTH_SERVER_URI | `http://localhost:8090` | The base url of the auth server, currently set to the base url of this app. | +| HTTPS_CERT_PATH | `server.cert` | Path to a certificate for encryption, allowing HTTPS. Unnecessary if using HTTP. | +| HTTPS_KEY_PATH | `server.key` | Path to a key for encryption, allowing HTTPS. Unnecessary if using HTTP. | +| LOGGING_LEVEL | `debug` | Amount to output in the log, can be changed to verbose, info, warn, or error. | +| MONGO_DB_NAME | `remsadmin` | Name of the database table being used. Should be changed if not using the Mongo instructions below. | +| MONGO_URL | `mongodb://rems-user:pass@127.0.0.1:27017` | URL for the connection to the database, should be changed if not using the Mongo instructions below. | +| PORT | `8090` | Port that this server should run on, change if there are conflicts with port usage. | +| RESOURCE_SERVER | `http://localhost:8090` | Base URL of this server, should match with port. | +| SMART_ENDPOINT | `http://localhost:4040/launch` | Launch URL of associated SMART app, should be changed if not using the REMS Smart App. | +| USE_HTTPS | `false` | Change to true to enable HTTPS. Ensure that HTTPS_CERT_PATH and HTTPS_KEY_PATH are valid. | +| VSAC_API_KEY | `changeMe` | Replace with VSAC API key for pulling down ValueSets. Request an API Key from the [VSAC website](https://vsac.nlm.nih.gov/) | +| WHITELIST | `http://localhost, http://localhost:3005` | List of valid URLs for CORS. Should include any URLs the server accesses for resources. | ## Running the Mongo DB instance