Skip to content
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
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ VITE_PIMS_SERVER = http://localhost:5051/doctorOrders/api/addRx
VITE_PUBLIC_KEYS = http://localhost:3000/request-generator/.well-known/jwks.json
VITE_REALM = ClientFhirServer
VITE_RESPONSE_EXPIRATION_DAYS = 30
VITE_SERVER = http://localhost:8090
VITE_SMART_LAUNCH_URL = http://localhost:4040/
VITE_URL = http://localhost:3000
VITE_USER = alice
VITE_HOOK_TO_SEND = patient-view
VITE_URL_FILTER = http://localhost:3000/*
VITE_USE_INTERMEDIARY = false
VITE_INTERMEDIARY = http://localhost:3003
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ Following are a list of modifiable paths:
| VITE_PUBLIC_KEYS | `http://localhost:3000/request-generator/.well-known/jwks.json` | The endpoint which contains the public keys for authentication with the REMS admin. Should be changed if the keys are moved elsewhere. |
| VITE_REALM | `ClientFhirServer` | The Keycloak realm to use. Only relevant is using Keycloak as an authentication server. This only affects direct logins like through the Patient Portal, not SMART launches like opening the app normally. |
| VITE_RESPONSE_EXPIRATION_DAYS | `30` | The number of days old a Questionnaire Response can be before it is ignored and filtered out. This ensures the patient search excludes outdated or obsolete prior sessions from creating clutter. |
| VITE_SERVER | `http://localhost:8090` | The default base URL of the CDS service. Typically this will be the base url of the REMS Admin. |
| VITE_SMART_LAUNCH_URL | `http://localhost:4040/` | The base url of the SMART app. This is used for opening the app directly, rather than doing an EHR SMART launch. |
| VITE_URL | `http://localhost:3000` | The base url of this app. Should be modified if the port or domain change. |
| VITE_USER | `alice` | The default user to login as when opening the app. |
| VITE_USER | `alice` | The default user to login as when opening the app. |
| VITE_USE_INTERMEDIARY | false | When true, the app will send all CDS Hooks and REMS ETASU check calls to the intermediary defined in VITE_INTERMEDIARY. |
| VITE_INTERMEDIARY | `http://localhost:3030` | The base url of the intermediary. |
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SettingsContext } from '../../../containers/ContextProvider/SettingsPro
import { EtasuStatusComponent } from '../../EtasuStatus/EtasuStatusComponent';
import axios from 'axios';
import { createMedicationFromMedicationRequest } from '../../../util/fhir';
import { standardsBasedGetEtasu } from '../../../util/util';
import { standardsBasedGetEtasu, getMedicationSpecificEtasuUrl } from '../../../util/util';

const NotificationsSection = () => {
const [globalState, _] = useContext(SettingsContext);
Expand Down Expand Up @@ -49,7 +49,7 @@ const NotificationsSection = () => {
const getAllEtasu = () => {
medications.forEach(medication => {
const body = makeBody(medication);
const standardEtasuUrl = `${globalState.remsAdminServer}/4_0_0/GuidanceResponse/$rems-etasu`;
const standardEtasuUrl = getMedicationSpecificEtasuUrl(medication?.code, globalState);
standardsBasedGetEtasu(standardEtasuUrl, body, compileResponses);
});
};
Expand Down Expand Up @@ -81,6 +81,7 @@ const NotificationsSection = () => {
display={display}
remsAdminResponseInit={remsCase}
data={remsCase.body}
medication={remsCase.body.parameter[1]?.resource}
/>
);
})}
Expand Down
4 changes: 2 additions & 2 deletions src/components/DisplayBox/DisplayBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ const DisplayBox = props => {
card.links.map((link, ind) => {
if (link.type === 'smart') {
linksSection.push(
<ListItem sx={{ marginLeft: '-12px' }}>
<ListItem key={ind} sx={{ marginLeft: '-12px' }}>
<Button
key={ind}
variant="outlined"
Expand Down Expand Up @@ -318,7 +318,7 @@ const DisplayBox = props => {
card.links.map((link, ind) => {
if (link.type === 'absolute') {
documentationSection.push(
<ListItem>
<ListItem key={ind}>
<Box key={ind}>
<Button
variant="text"
Expand Down
7 changes: 5 additions & 2 deletions src/components/EtasuStatus/EtasuStatus.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useContext } from 'react';
import { SettingsContext } from '../../containers/ContextProvider/SettingsProvider.jsx';
import { EtasuStatusComponent } from './EtasuStatusComponent.jsx';
import { standardsBasedGetEtasu } from '../../util/util.js';
import { standardsBasedGetEtasu, getMedicationSpecificEtasuUrl } from '../../util/util.js';
import { createMedicationFromMedicationRequest, getDrugCodeableConceptFromMedicationRequest } from '../../util/fhir.js';

// converts code into etasu for the component to render
Expand All @@ -12,6 +12,7 @@ export const EtasuStatus = props => {
const { code, request } = props;
const [remsAdminResponse, setRemsAdminResponse] = useState({});
const [etasuData, setEtasuData] = useState({});
const [medication, setMedication] = useState({});
const [display, setDisplay] = useState('');

useEffect(() => {
Expand All @@ -22,9 +23,10 @@ export const EtasuStatus = props => {
const getEtasuStatus = medication => {
const body = makeBody(medication);
setEtasuData(body);
setMedication(medication);
const display = body.parameter[1]?.resource.code?.coding[0].display;
setDisplay(display);
const standardEtasuUrl = `${globalState.remsAdminServer}/4_0_0/GuidanceResponse/$rems-etasu`;
const standardEtasuUrl = getMedicationSpecificEtasuUrl(medication?.code, globalState);
standardsBasedGetEtasu(standardEtasuUrl, body, setRemsAdminResponse);
};

Expand Down Expand Up @@ -52,6 +54,7 @@ export const EtasuStatus = props => {
remsAdminResponseInit={remsAdminResponse}
data={etasuData}
display={display}
medication={medication}
/>
) : (
''
Expand Down
6 changes: 3 additions & 3 deletions src/components/EtasuStatus/EtasuStatusComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { EtasuStatusModal } from './EtasuStatusModal.jsx';
import { useState, useEffect, useContext } from 'react';
import { Card, Typography } from '@mui/material';
import { SettingsContext } from '../../containers/ContextProvider/SettingsProvider.jsx';
import { standardsBasedGetEtasu } from '../../util/util.js';
import { standardsBasedGetEtasu, getMedicationSpecificEtasuUrl } from '../../util/util.js';

export const EtasuStatusComponent = props => {
const [globalState, _] = useContext(SettingsContext);

const { remsAdminResponseInit, data, display } = props;
const { remsAdminResponseInit, data, display, medication } = props;

const [remsAdminResponse, setRemsAdminResponse] = useState(remsAdminResponseInit);
const [lastCheckedEtasuTime, setLastCheckedEtasuTime] = useState(0);
Expand All @@ -28,7 +28,7 @@ export const EtasuStatusComponent = props => {

const refreshEtasu = () => {
if (remsAdminResponse) {
const standardEtasuUrl = `${globalState.remsAdminServer}/4_0_0/GuidanceResponse/$rems-etasu`;
const standardEtasuUrl = getMedicationSpecificEtasuUrl(medication?.code, globalState);
standardsBasedGetEtasu(standardEtasuUrl, data, setRemsAdminResponse);
setLastCheckedEtasuTime(Date.now());
}
Expand Down
10 changes: 5 additions & 5 deletions src/components/RequestBox/RequestBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import buildNewRxRequest from '../../util/buildScript.2017071.js';
import MuiAlert from '@mui/material/Alert';
import Snackbar from '@mui/material/Snackbar';
import { shortNameMap, ORDER_SIGN, PATIENT_VIEW } from '../../util/data.js';
import { getAge, createMedicationDispenseFromMedicationRequest, createMedicationFromMedicationRequest } from '../../util/fhir.js';
import { retrieveLaunchContext, prepPrefetch } from '../../util/util.js';
import { getAge, createMedicationDispenseFromMedicationRequest, createMedicationFromMedicationRequest, getDrugCodeableConceptFromMedicationRequest } from '../../util/fhir.js';
import { retrieveLaunchContext, prepPrefetch, getMedicationSpecificEtasuUrl } from '../../util/util.js';
import './request.css';
import axios from 'axios';

Expand Down Expand Up @@ -217,16 +217,16 @@ const RequestBox = props => {
console.log('Getting auth number ')
const medication = createMedicationFromMedicationRequest(request);
const body = makeBody(medication);
const standardEtasuUrl = `${globalState.remsAdminServer}/4_0_0/GuidanceResponse/$rems-etasu`;
const standardEtasuUrl = getMedicationSpecificEtasuUrl(getDrugCodeableConceptFromMedicationRequest(request), globalState);
let authNumber = '';
await axios({
method: 'post',
url: standardEtasuUrl,
data: body
}).then(
response => {
if (response.data.parameter[0].resource && response.data.parameter[0].resource.contained) {
response.data.parameter[0].resource?.contained[0]?.parameter.map(metRequirements => {
if (response.data.parameter[0].resource && response.data.parameter?.[0].resource.contained) {
response.data.parameter?.[0].resource?.contained[0]?.parameter.map(metRequirements => {
if (metRequirements.name === 'auth_number') {
authNumber = metRequirements.valueString;
}
Expand Down
20 changes: 11 additions & 9 deletions src/components/RequestDashboard/SettingsSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import AddIcon from '@mui/icons-material/Add';
import env from 'env-var';
import FHIR from 'fhirclient';

import { headerDefinitions, medicationRequestToRemsAdmins, ORDER_SIGN, ORDER_SELECT, PATIENT_VIEW, ENCOUNTER_START } from '../../util/data';
import { headerDefinitions, medicationRequestToRemsAdmins, ORDER_SIGN, ORDER_SELECT, PATIENT_VIEW, ENCOUNTER_START, REMS_ETASU } from '../../util/data';
import { actionTypes, initialState } from '../../containers/ContextProvider/reducer';
import { SettingsContext } from '../../containers/ContextProvider/SettingsProvider';

const CDS_HOOKS = [ORDER_SIGN, ORDER_SELECT, PATIENT_VIEW, ENCOUNTER_START];
const ENDPOINT = [ORDER_SIGN, ORDER_SELECT, PATIENT_VIEW, ENCOUNTER_START, REMS_ETASU];

const SettingsSection = props => {
const [state, dispatch] = React.useContext(SettingsContext);
Expand Down Expand Up @@ -299,13 +299,14 @@ const SettingsSection = props => {
maxHeight: 440
}}
>
{!state['useIntermediary'] && (
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow sx={{ th: { fontWeight: 'bold' } }}>
<TableCell width={500}>Medication Display</TableCell>
<TableCell width={200}>Medication RxNorm Code</TableCell>
<TableCell width={200}>CDS Hook</TableCell>
<TableCell width={500}>REMS Admin Endpoint</TableCell>
<TableCell width={200}>Hook / Endpoint</TableCell>
<TableCell width={500}>REMS Admin URL</TableCell>
{/* This empty TableCell corresponds to the add and delete
buttons. It is used to fill up the sticky header which
will appear over the gray/white table rows. */}
Expand Down Expand Up @@ -348,19 +349,19 @@ const SettingsSection = props => {
<Select
labelId="dropdown-label"
id="dropdown"
value={row.hook}
value={row.endpointType}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { hook: event.target.value }
value: { endpointType: event.target.value }
})
}
sx={{ width: '100%' }}
>
{CDS_HOOKS.map(hook => (
<MenuItem key={hook} value={hook}>
{hook}
{ENDPOINT.map(endpointType => (
<MenuItem key={endpointType} value={endpointType}>
{endpointType}
</MenuItem>
))}
</Select>
Expand Down Expand Up @@ -408,6 +409,7 @@ const SettingsSection = props => {
})}
</TableBody>
</Table>
)}
</TableContainer>
</Grid>

Expand Down
10 changes: 5 additions & 5 deletions src/containers/ContextProvider/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const getNewStateWithNewCdsHookSetting = (state, settingId) => {
newState.medicationRequestToRemsAdmins[uuidv4()] = {
rxnorm: 'Fill out Medication RxNorm Code',
display: 'Fill out Medication Display Name',
hook: ORDER_SIGN,
endpointType: ORDER_SIGN,
remsAdmin: 'REMS Admin URL for CDS Hook'
};

Expand Down Expand Up @@ -108,10 +108,10 @@ export const initialState = (() => {
});

medicationRequestToRemsAdmins.forEach(row => {
const { rxnorm, display, hookEndpoints } = row;
hookEndpoints.forEach(({ hook, remsAdmin }) => {
const key = `${rxnorm}_${hook}`;
state.medicationRequestToRemsAdmins[key] = { rxnorm, display, hook, remsAdmin };
const { rxnorm, display, endpoints } = row;
endpoints.forEach(({ endpointType, remsAdmin }) => {
const key = `${rxnorm}_${endpointType}`;
state.medicationRequestToRemsAdmins[key] = { rxnorm, display, endpointType, remsAdmin };
});
});
return state;
Expand Down
6 changes: 3 additions & 3 deletions src/containers/RequestBuilder.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import RequestBox from '../components/RequestBox/RequestBox.jsx';
import buildRequest from '../util/buildRequest.js';
import { types, PATIENT_VIEW } from '../util/data.js';
import { createJwt } from '../util/auth.js';
import { getMedicationSpecificRemsAdminUrl, prepPrefetch } from '../util/util.js';
import { getMedicationSpecificCdsHooksUrl, prepPrefetch } from '../util/util.js';

import Accordion from '@mui/material/Accordion';
import AccordionSummary from '@mui/material/AccordionSummary';
Expand Down Expand Up @@ -121,7 +121,7 @@ const RequestBuilder = props => {
let remsAdminUrls = [];
// get all the remsAdminUrl for each MedicationRequest
state.medicationRequests?.data?.forEach(request => {
const remsAdminUrl = getMedicationSpecificRemsAdminUrl(request, globalState, hook);
const remsAdminUrl = getMedicationSpecificCdsHooksUrl(request, globalState, hook);
if (remsAdminUrl) {
remsAdminUrls.push(remsAdminUrl);
}
Expand All @@ -138,7 +138,7 @@ const RequestBuilder = props => {
console.log('Initiating form submission ', types.info);
let remsAdminUrl = null;
if (request) {
remsAdminUrl = getMedicationSpecificRemsAdminUrl(request, globalState, hook);
remsAdminUrl = getMedicationSpecificCdsHooksUrl(request, globalState, hook);
sendHook(prefetch, request, patient, hook, remsAdminUrl);
} else {
// get all MedicationRequests for the patient, then continue
Expand Down
Loading