Skip to content

Commit

Permalink
Merge pull request #137 from mcode/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
smalho01 authored Sep 30, 2024
2 parents 88a4aba + aeff419 commit 90e1f8e
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 193 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ VITE_GH_PAGES=false
VITE_LAUNCH_URL = http://localhost:4040/launch
VITE_PASSWORD = alice
VITE_PATIENT_FHIR_QUERY = Patient?_sort=identifier&_count=12
VITE_PIMS_SERVER = http://localhost:5051/doctorOrders/api/addRx
VITE_PIMS_SERVER = http://localhost:5051/ncpdp/script
VITE_PUBLIC_KEYS = http://localhost:3000/request-generator/.well-known/jwks.json
VITE_REALM = ClientFhirServer
VITE_RESPONSE_EXPIRATION_DAYS = 30
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ Following are a list of modifiable paths:
| VITE_LAUNCH_URL | `http://localhost:4040/launch` | The launch URL of the SMART app the request generator should use for standalone launches. Note that this URL is only used outside of the context of the CDS Hooks workflow. Normally, the SMART app launch URL will come from a link inside a card that is returned by the REMS Admin. |
| VITE_PASSWORD | `alice` | The default password for logging in as the default user, defined by VITE_USER. This should be changed if using a different default user. |
| VITE_PATIENT_FHIR_QUERY | `Patient?_sort=identifier&_count=12` | The FHIR query the app makes when searching for patients in the EHR. This should be modified if a different behavior is desired by the apps patient selection popup. This can also be modified directly in the app's settings. |
| VITE_PIMS_SERVER | `http://localhost:5051/doctorOrders/api/addRx` | The Pharmacy System endpoint for submitting medications. This should be changed depending on which pharmacy system you want to connect with. |
| VITE_PIMS_SERVER | `http://localhost:5051/ncpdp/script` | The Pharmacy System endpoint for submitting medications. This should be changed depending on which pharmacy system you want to connect with. |
| 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. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { createMedicationFromMedicationRequest } from '../../../util/fhir';
import { standardsBasedGetEtasu, getMedicationSpecificEtasuUrl } from '../../../util/util';

const NotificationsSection = () => {
const [globalState, _] = useContext(SettingsContext);
const [globalState] = useContext(SettingsContext);
const classes = useStyles();
const [etasu, setEtasu] = useState([]);
const [medications, setMedications] = useState([]);
Expand Down
2 changes: 1 addition & 1 deletion src/components/EtasuStatus/EtasuStatus.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { createMedicationFromMedicationRequest } from '../../util/fhir.js';
// converts code into etasu for the component to render
// simplifies usage for applications that only know the code, not the case they want to display
export const EtasuStatus = props => {
const [globalState, _] = useContext(SettingsContext);
const [globalState] = useContext(SettingsContext);

const { code, request } = props;
const [remsAdminResponse, setRemsAdminResponse] = useState({});
Expand Down
2 changes: 1 addition & 1 deletion src/components/EtasuStatus/EtasuStatusComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SettingsContext } from '../../containers/ContextProvider/SettingsProvid
import { standardsBasedGetEtasu, getMedicationSpecificEtasuUrl } from '../../util/util.js';

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

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

Expand Down
10 changes: 2 additions & 8 deletions src/components/RequestBox/PatientSearchBar/PatientSearchBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { defaultValues } from '../../../util/data';

import PatientBox from '../../SMARTBox/PatientBox';
import './PatientSearchBarStyle.css';
import { getPatientFirstAndLastName } from '../../../util/util';

const PatientSearchBar = props => {
const [options] = useState(defaultValues);
Expand All @@ -14,18 +15,11 @@ const PatientSearchBar = props => {
useEffect(() => {
const newList = props.searchablePatients.map(patient => ({
id: patient.id,
name: getName(patient)
name: getPatientFirstAndLastName(patient)
}));
setListOfPatients([newList]);
}, [props.searchablePatients]);

function getName(patient) {
if (patient.name) {
return patient.name[0].given[0] + ' ' + patient.name[0].family;
}
return '';
}

function getFilteredLength(searchString, listOfPatients) {
const filteredListOfPatients = listOfPatients[0].filter(element => {
if (searchString === '') {
Expand Down
5 changes: 3 additions & 2 deletions src/components/RequestBox/RequestBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
import {
retrieveLaunchContext,
prepPrefetch,
getMedicationSpecificEtasuUrl
getMedicationSpecificEtasuUrl,
getPatientFirstAndLastName
} from '../../util/util.js';
import './request.css';
import axios from 'axios';
Expand Down Expand Up @@ -71,7 +72,7 @@ const RequestBox = props => {
}
let name;
if (patient.name) {
name = <span> {`${patient.name[0].given[0]} ${patient.name[0].family}`} </span>;
name = <span>{getPatientFirstAndLastName(patient)}</span>;
} else {
name = emptyField;
}
Expand Down
265 changes: 136 additions & 129 deletions src/components/RequestDashboard/SettingsSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@ 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, REMS_ETASU } from '../../util/data';
import { actionTypes, initialState } from '../../containers/ContextProvider/reducer';
import {
headerDefinitions,
ORDER_SIGN,
ORDER_SELECT,
PATIENT_VIEW,
ENCOUNTER_START,
REMS_ETASU
} from '../../util/data';
import { actionTypes } from '../../containers/ContextProvider/reducer';
import { SettingsContext } from '../../containers/ContextProvider/SettingsProvider';

const ENDPOINT = [ORDER_SIGN, ORDER_SELECT, PATIENT_VIEW, ENCOUNTER_START, REMS_ETASU];
Expand Down Expand Up @@ -255,30 +262,30 @@ const SettingsSection = props => {
case 'dropdown':
return (
<React.Fragment key={key}>
<Grid key={key} item xs={6}>
<FormControl fullWidth>
<InputLabel id="dropdown-label">Hook to send when selecting a patient</InputLabel>
<Select
labelId="dropdown-label"
id="dropdown"
value={state[key]}
label="Hook to send when selecting a patient"
onChange={event => updateSetting(key, event.target.value)}
sx={{ width: '100%' }}
>
<MenuItem key={PATIENT_VIEW} value={PATIENT_VIEW}>
{PATIENT_VIEW}
</MenuItem>
<MenuItem key={ENCOUNTER_START} value={ENCOUNTER_START}>
{ENCOUNTER_START}
</MenuItem>
</Select>
</FormControl>

</Grid>
<Grid key={key} item xs={6}>
<FormControl fullWidth>
<InputLabel id="dropdown-label">
Hook to send when selecting a patient
</InputLabel>
<Select
labelId="dropdown-label"
id="dropdown"
value={state[key]}
label="Hook to send when selecting a patient"
onChange={event => updateSetting(key, event.target.value)}
sx={{ width: '100%' }}
>
<MenuItem key={PATIENT_VIEW} value={PATIENT_VIEW}>
{PATIENT_VIEW}
</MenuItem>
<MenuItem key={ENCOUNTER_START} value={ENCOUNTER_START}>
{ENCOUNTER_START}
</MenuItem>
</Select>
</FormControl>
</Grid>
</React.Fragment>

)
);
default:
return (
<div key={key}>
Expand All @@ -300,115 +307,115 @@ const SettingsSection = props => {
}}
>
{!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}>Hook / Endpoint</TableCell>
<TableCell width={500}>REMS Admin URL</TableCell>
{/* This empty TableCell corresponds to the add and delete
<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}>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. */}
<TableCell width={150} />
</TableRow>
</TableHead>
<TableBody>
{Object.entries(state.medicationRequestToRemsAdmins).map(([key, row]) => {
return (
<TableRow key={key}>
<TableCell>
<TextField
variant="outlined"
value={row.display}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { display: event.target.value }
})
}
sx={{ width: '100%' }}
/>
</TableCell>
<TableCell>
<TextField
variant="outlined"
value={row.rxnorm}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { rxnorm: event.target.value }
})
}
sx={{ width: '100%' }}
/>
</TableCell>
<TableCell>
<Select
labelId="dropdown-label"
id="dropdown"
value={row.endpointType}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { endpointType: event.target.value }
})
}
sx={{ width: '100%' }}
>
{ENDPOINT.map(endpointType => (
<MenuItem key={endpointType} value={endpointType}>
{endpointType}
</MenuItem>
))}
</Select>
</TableCell>
<TableCell>
<TextField
variant="outlined"
value={row.remsAdmin}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { remsAdmin: event.target.value }
})
}
sx={{ width: '100%' }}
/>
</TableCell>
<TableCell align="right">
<Tooltip title="Add a new row below">
<IconButton
color="primary"
onClick={() =>
dispatch({ type: actionTypes.addCdsHookSetting, settingId: key })
<TableCell width={150} />
</TableRow>
</TableHead>
<TableBody>
{Object.entries(state.medicationRequestToRemsAdmins).map(([key, row]) => {
return (
<TableRow key={key}>
<TableCell>
<TextField
variant="outlined"
value={row.display}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { display: event.target.value }
})
}
size="large"
>
<AddIcon fontSize="large" />
</IconButton>
</Tooltip>
<Tooltip title="Delete this row">
<IconButton
color="primary"
onClick={() =>
dispatch({ type: actionTypes.deleteCdsHookSetting, settingId: key })
sx={{ width: '100%' }}
/>
</TableCell>
<TableCell>
<TextField
variant="outlined"
value={row.rxnorm}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { rxnorm: event.target.value }
})
}
size="large"
sx={{ width: '100%' }}
/>
</TableCell>
<TableCell>
<Select
labelId="dropdown-label"
id="dropdown"
value={row.endpointType}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { endpointType: event.target.value }
})
}
sx={{ width: '100%' }}
>
<DeleteIcon fontSize="large" />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
{ENDPOINT.map(endpointType => (
<MenuItem key={endpointType} value={endpointType}>
{endpointType}
</MenuItem>
))}
</Select>
</TableCell>
<TableCell>
<TextField
variant="outlined"
value={row.remsAdmin}
onChange={event =>
dispatch({
type: actionTypes.updateCdsHookSetting,
settingId: key,
value: { remsAdmin: event.target.value }
})
}
sx={{ width: '100%' }}
/>
</TableCell>
<TableCell align="right">
<Tooltip title="Add a new row below">
<IconButton
color="primary"
onClick={() =>
dispatch({ type: actionTypes.addCdsHookSetting, settingId: key })
}
size="large"
>
<AddIcon fontSize="large" />
</IconButton>
</Tooltip>
<Tooltip title="Delete this row">
<IconButton
color="primary"
onClick={() =>
dispatch({ type: actionTypes.deleteCdsHookSetting, settingId: key })
}
size="large"
>
<DeleteIcon fontSize="large" />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
)}
</TableContainer>
</Grid>
Expand Down
Loading

0 comments on commit 90e1f8e

Please sign in to comment.