diff --git a/.env b/.env index c6757a9..d4b9e1e 100644 --- a/.env +++ b/.env @@ -26,5 +26,7 @@ VITE_USER = alice VITE_HOOK_TO_SEND = patient-view VITE_URL_FILTER = http://localhost:3000/* VITE_USE_INTERMEDIARY = false +VITE_USE_PHARMACY_IN_PREFETCH = true VITE_INTERMEDIARY = http://localhost:3003 VITE_DISABLE_MEDICATION_STATUS = false +VITE_PHARMACY_ID = pharm0111 diff --git a/README.md b/README.md index 7604fe7..3608494 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,9 @@ Following are a list of modifiable paths: | 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_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. | +| VITE_INTERMEDIARY | `http:/localhost:3030` | The base url of the intermediary. | +| VITE_USE_PHARMACY_IN_PREFETCH | true | When true, the app will send pharmacy information to the rems admin in the CDS Hooks prefetch | +| VITE_PHARMACY_ID | `pharm0111` | The pharmacy ID to use in the CDS Hooks Prefetch | # Data Rights This repository has been forked from the [HL7-DaVinci/crd-request-generator](https://github.com/HL7-DaVinci/crd-request-generator) repository. As such, the following data rights apply to all changes made on this fork of the repository, starting with release 0.1 and onward. diff --git a/src/PrefetchTemplate.js b/src/PrefetchTemplate.js index 50b8e9e..573a880 100644 --- a/src/PrefetchTemplate.js +++ b/src/PrefetchTemplate.js @@ -1,27 +1,35 @@ // Prefetch Template Source: // https://build.fhir.org/ig/HL7/davinci-crd/hooks.html#prefetch export class PrefetchTemplate { - static generatePrefetchMap() { + static generatePrefetchMap(settings = null) { + // If no settings provided, use defaults from data.js + const includePharmacy = settings?.includePharmacyInPreFetch ?? + headerDefinitions.includePharmacyInPreFetch.default; + const pharmacyId = settings?.pharmacyId ?? + headerDefinitions.pharmacyId.default; + const prefetchMap = new Map(); const PRACTITIONER_PREFETCH = new PrefetchTemplate('{{context.userId}}'); - const REQUEST_PREFETCH = new PrefetchTemplate( 'MedicationRequest/{{context.medications.MedicationRequest.id}}' ); const PATIENT_PREFETCH = new PrefetchTemplate('{{context.patientId}}'); - const ALL_REQUESTS_PREFETCH = new PrefetchTemplate( 'MedicationRequest?subject={{context.patientId}}&_include=MedicationRequest:medication' ); - // prefetchMap.set("Coverage", COVERAGE_PREFETCH_QUERY); + // Core prefetch items (always included) prefetchMap.set('request', REQUEST_PREFETCH); prefetchMap.set('practitioner', PRACTITIONER_PREFETCH); prefetchMap.set('patient', PATIENT_PREFETCH); prefetchMap.set('medicationRequests', ALL_REQUESTS_PREFETCH); - // prefetchMap.set("ServiceRequest", SERVICE_REQUEST_BUNDLE); - // prefetchMap.set("Encounter", ENCOUNTER_BUNDLE); + + // Optional pharmacy prefetch based on settings + if (includePharmacy && pharmacyId) { + const PHARMACY_PREFETCH = new PrefetchTemplate(`HealthcareService/${pharmacyId}`); + prefetchMap.set('pharmacy', PHARMACY_PREFETCH); + } return prefetchMap; } @@ -47,27 +55,49 @@ export class PrefetchTemplate { return paramElementMap; } - static generateQueries(requestBundle, patientReference, userReference, ...prefetchKeys) { + static generateQueries( + requestBundle, + patientReference, + userReference, + settings = null, + ...prefetchKeys + ) { + const prefetchMap = PrefetchTemplate.generatePrefetchMap(settings); + const paramElementMap = PrefetchTemplate.generateParamElementMap(); + var resolvedQueries = new Map(); for (var i = 0; i < prefetchKeys.length; i++) { var prefetchKey = prefetchKeys[i]; + if (!prefetchKey || !prefetchMap.has(prefetchKey)) continue; var query = prefetchMap.get(prefetchKey).getQuery(); // Regex source: https://regexland.com/all-between-specified-characters/ var parametersToFill = query.match(/(?<={{).*?(?=}})/gs); var resolvedQuery = query.slice(); - for (var j = 0; j < parametersToFill.length; j++) { - var unresolvedParameter = parametersToFill[j]; - var resolvedParameter; - if (requestBundle) { - resolvedParameter = PrefetchTemplate.resolveParameter(unresolvedParameter, requestBundle); - } else { - if (unresolvedParameter === 'context.patientId') { - resolvedParameter = patientReference; - } else if (unresolvedParameter === 'context.userId') { - resolvedParameter = userReference; + + if (parametersToFill) { + for (var j = 0; j < parametersToFill.length; j++) { + var unresolvedParameter = parametersToFill[j]; + var resolvedParameter; + if (requestBundle) { + resolvedParameter = PrefetchTemplate.resolveParameter( + unresolvedParameter, + requestBundle, + paramElementMap + ); + } else { + if (unresolvedParameter === 'context.patientId') { + resolvedParameter = patientReference; + } else if (unresolvedParameter === 'context.userId') { + resolvedParameter = userReference; + } + } + if (resolvedParameter) { + resolvedQuery = resolvedQuery.replace( + '{{' + unresolvedParameter + '}}', + resolvedParameter + ); } } - resolvedQuery = resolvedQuery.replace('{{' + unresolvedParameter + '}}', resolvedParameter); } resolvedQueries.set(prefetchKey, resolvedQuery); } @@ -89,8 +119,9 @@ export class PrefetchTemplate { } } - static resolveParameter(unresolvedParameter, requestBundle) { + static resolveParameter(unresolvedParameter, requestBundle, paramElementMap) { const paramField = paramElementMap.get(unresolvedParameter); + if (!paramField) return null; const resolvedParameter = PrefetchTemplate.getProp(requestBundle, paramField); return resolvedParameter; } @@ -104,7 +135,4 @@ export class PrefetchTemplate { getQuery() { return this.query; } -} - -const prefetchMap = PrefetchTemplate.generatePrefetchMap(); -const paramElementMap = PrefetchTemplate.generateParamElementMap(); +} \ No newline at end of file diff --git a/src/components/App.jsx b/src/components/App.jsx index de99d55..f24fc4b 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -28,10 +28,24 @@ const App = () => { } /> - } /> + + + + } + /> } /> {/* forcibly enter backoffice workflow */} - } /> + + + + } + /> { - -

Filter patient list

- { - setInput(newInputValue.toLowerCase()); - }} - options={listOfPatients[0].map(item => item.name)} - renderInput={params => } - /> -

- Showing {getFilteredLength(input, listOfPatients)} of {props.searchablePatients.length}{' '} - records -

-
+ +

Filter patient list

+ { + setInput(newInputValue.toLowerCase()); + }} + options={listOfPatients[0].map(item => item.name)} + renderInput={params => } + /> +

+ Showing {getFilteredLength(input, listOfPatients)} of{' '} + {props.searchablePatients.length} records +

+
- diff --git a/src/components/RequestBox/RequestBox.jsx b/src/components/RequestBox/RequestBox.jsx index f982324..c402427 100644 --- a/src/components/RequestBox/RequestBox.jsx +++ b/src/components/RequestBox/RequestBox.jsx @@ -182,9 +182,7 @@ const RequestBox = props => { let userId = prefetchedResources?.practitioner?.id; if (!userId) { - console.log( - 'Practitioner not populated from prefetch, using user: ' + user - ); + console.log('Practitioner not populated from prefetch, using user: ' + user); userId = user; } diff --git a/src/components/RequestDashboard/Home.jsx b/src/components/RequestDashboard/Home.jsx index 9ce8648..da8a9b0 100644 --- a/src/components/RequestDashboard/Home.jsx +++ b/src/components/RequestDashboard/Home.jsx @@ -64,36 +64,37 @@ const Home = props => { } return (
- - {section ? '' : } {/* spacer */} - {renderMainButton(patientButton, )} - {renderMainButton(taskButton, )} - {renderMainButton(settingsButton, )} - {section ? ( - - -   EHR Request Generator - - - ) : ( - - )} - {/* spacer */} - {/** */} - {section ? ( - - - {token.name} - - - - ) : ( - - )} - {/**/} - + + {section ? '' : } {/* spacer */} + {renderMainButton(patientButton, )} + {renderMainButton(taskButton, )} + {renderMainButton(settingsButton, )} + {section ? ( + + + +   EHR Request Generator + + + ) : ( + + )} + {/* spacer */} + {/** */} + {section ? ( + + + {token.name} + + + + ) : ( + + )} + {/**/} +
); }; diff --git a/src/components/RequestDashboard/PatientSection.jsx b/src/components/RequestDashboard/PatientSection.jsx index 0439e99..5eaeedf 100644 --- a/src/components/RequestDashboard/PatientSection.jsx +++ b/src/components/RequestDashboard/PatientSection.jsx @@ -8,7 +8,12 @@ const PatientSection = props => { return (
{state.startup ? ( - + ) : ( <>Loading... )} diff --git a/src/components/RequestDashboard/SettingsSection.jsx b/src/components/RequestDashboard/SettingsSection.jsx index 4bd6efd..e1a031e 100644 --- a/src/components/RequestDashboard/SettingsSection.jsx +++ b/src/components/RequestDashboard/SettingsSection.jsx @@ -39,7 +39,8 @@ import { SettingsContext } from '../../containers/ContextProvider/SettingsProvid const ENDPOINT = [ORDER_SIGN, ORDER_SELECT, PATIENT_VIEW, ENCOUNTER_START, REMS_ETASU]; const SettingsSection = props => { - const [state, dispatch, updateSetting, readSettings, saveSettings] = React.useContext(SettingsContext); + const [state, dispatch, updateSetting, readSettings, saveSettings] = + React.useContext(SettingsContext); const fieldHeaders = Object.keys(headerDefinitions) .map(key => ({ ...headerDefinitions[key], key })) @@ -94,7 +95,7 @@ const SettingsSection = props => { }); }; - const clearResource = + const clearResource = ({ ehrUrl, access_token }, type) => () => { console.log('Clear ' + type + 's from the EHR: ' + ehrUrl); @@ -151,19 +152,19 @@ const SettingsSection = props => { display: 'Clear EHR In-Progress Forms', key: 'clearQuestionnaireResponses', reset: clearResource, - parameter: 'QuestionnaireResponse' + parameter: 'QuestionnaireResponse' }, { display: 'Clear EHR Dispense Statuses', key: 'clearMedicationDispenses', reset: clearResource, - parameter: 'MedicationDispense' + parameter: 'MedicationDispense' }, { display: 'Clear EHR Tasks', key: 'clearTasks', reset: clearResource, - parameter: 'Task' + parameter: 'Task' }, { display: 'Reconnect EHR', @@ -184,17 +185,19 @@ const SettingsSection = props => { case 'input': return ( - { ( (state['useDefaultUser'] && key === 'defaultUser') || key != 'defaultUser' ) ? ( -
- updateSetting(key, event.target.value)} - sx={{ width: '100%' }} - /> -
- ) : ('') } + {(state['useDefaultUser'] && key === 'defaultUser') || key != 'defaultUser' ? ( +
+ updateSetting(key, event.target.value)} + sx={{ width: '100%' }} + /> +
+ ) : ( + '' + )}
); case 'check': diff --git a/src/components/RequestDashboard/TasksSection.jsx b/src/components/RequestDashboard/TasksSection.jsx index a342bf6..7bf0315 100644 --- a/src/components/RequestDashboard/TasksSection.jsx +++ b/src/components/RequestDashboard/TasksSection.jsx @@ -28,7 +28,7 @@ const taskStatus = Object.freeze({ }); const TasksSection = props => { const classes = useStyles(); - const {client, userName, userId} = props; + const { client, userName, userId } = props; const [tasks, setTasks] = useState([]); const [state] = React.useContext(SettingsContext); const [value, setValue] = useState(0); @@ -64,7 +64,8 @@ const TasksSection = props => { assignTaskToDefaultPractitioner(taskClone); } else if (val === 'patient') { assignTaskToPatient(taskClone); - } else { //'unassign' + } else { + //'unassign' unassignTask(taskClone); } handleAssignMenuClose(); @@ -120,7 +121,7 @@ const TasksSection = props => { fetchTasks(); }); } - } + }; const assignTaskToRequester = task => { if (task) { task = washTask(task); @@ -129,7 +130,7 @@ const TasksSection = props => { // assign to requester if available if (task?.requester) { - user = task.requester?.reference + user = task.requester?.reference; } task.owner = { reference: user @@ -139,7 +140,7 @@ const TasksSection = props => { fetchTasks(); }); } - };; + }; const assignTaskToDefaultPractitioner = task => { if (task) { task = washTask(task); @@ -190,14 +191,16 @@ const TasksSection = props => { if (state.patient && state.patient.id) { identifier = `Task?patient=${state.patient.id}`; } - client.request(identifier, { resolveReferences: ['for', 'owner', 'requester'] }).then(request => { - console.log(request); - if (request && request.entry) { - setTasks(request.entry.map(e => e.resource)); - } else { - setTasks([]); - } - }); + client + .request(identifier, { resolveReferences: ['for', 'owner', 'requester'] }) + .then(request => { + console.log(request); + if (request && request.entry) { + setTasks(request.entry.map(e => e.resource)); + } else { + setTasks([]); + } + }); }; useEffect(() => { fetchTasks(); @@ -291,18 +294,20 @@ const TasksSection = props => { {assignOptions.map(({ id, display }) => { // only give the 'Assign to requester if the requester is available' - if (((id === 'me') && userId && userName) - || ((id === 'requester') && (anchorAssign?.task?.requester)) - || ((id === 'defaultPractitioner') && (!anchorAssign?.task?.requester)) - || (id != 'me') && (id != 'requester') && (id != 'defaultPractitioner')) { - return ( - { - handleChangeAssign(anchorAssign?.task, id); - }} - >{`${display}`} - ); + if ( + (id === 'me' && userId && userName) || + (id === 'requester' && anchorAssign?.task?.requester) || + (id === 'defaultPractitioner' && !anchorAssign?.task?.requester) || + (id != 'me' && id != 'requester' && id != 'defaultPractitioner') + ) { + return ( + { + handleChangeAssign(anchorAssign?.task, id); + }} + >{`${display}`} + ); } })} diff --git a/src/components/RequestDashboard/styles.jsx b/src/components/RequestDashboard/styles.jsx index 2eab437..cc74b42 100644 --- a/src/components/RequestDashboard/styles.jsx +++ b/src/components/RequestDashboard/styles.jsx @@ -157,7 +157,7 @@ export default makeStyles( color: 'white !important', borderColor: 'white !important', marginRight: '5px !important', - marginLeft: '20px !important', + marginLeft: '20px !important' } }), diff --git a/src/components/SMARTBox/PatientBox.jsx b/src/components/SMARTBox/PatientBox.jsx index 9b4e4ed..a0d2358 100644 --- a/src/components/SMARTBox/PatientBox.jsx +++ b/src/components/SMARTBox/PatientBox.jsx @@ -1,5 +1,6 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState, useContext } from 'react'; import { getAge, getDrugCodeFromMedicationRequest } from '../../util/fhir'; +import { SettingsContext } from '../../containers/ContextProvider/SettingsProvider'; import './smart.css'; import { Button } from '@mui/material'; import Tooltip from '@mui/material/Tooltip'; @@ -18,6 +19,8 @@ import { } from '../../util/util'; const PatientBox = props => { + const [globalState] = useContext(SettingsContext); + const [state, setState] = useState({ request: '', deviceRequests: {}, @@ -50,7 +53,7 @@ const PatientBox = props => { responseExpirationDays, request, launchUrl, - showButtons, + showButtons } = props; const medicationColumns = [ @@ -173,7 +176,6 @@ const PatientBox = props => { client .request(urlQuery) .then(response => { - console.log(response); return response; }) .then(resource => { @@ -202,9 +204,11 @@ const PatientBox = props => { request, patientReference, userReference, + globalState, 'request', 'patient', - 'practitioner' + 'practitioner', + globalState.includePharmacyInPreFetch ? 'pharmacy' : undefined ); fetchResources(queries); @@ -218,9 +222,11 @@ const PatientBox = props => { request, patientReference, userReference, + globalState, 'patient', 'practitioner', - 'medicationRequests' + 'medicationRequests', + globalState.includePharmacyInPreFetch ? 'pharmacy' : undefined ); fetchResources(queries); } @@ -613,7 +619,9 @@ const PatientBox = props => { ) - ) : ""} + ) : ( + '' + )} {props.showButtons ? ( state.showQuestionnaires ? ( diff --git a/src/containers/BackOffice/BackOffice.jsx b/src/containers/BackOffice/BackOffice.jsx index facd8b3..0d3da7b 100644 --- a/src/containers/BackOffice/BackOffice.jsx +++ b/src/containers/BackOffice/BackOffice.jsx @@ -10,7 +10,7 @@ import useStyles from './styles'; import { logout } from '../../util/auth'; -const BackOffice = (props) => { +const BackOffice = props => { const classes = useStyles(); const { client, token } = props; @@ -19,39 +19,35 @@ const BackOffice = (props) => { }, []); return ( - - { token && client ? ( - - -
- -
-
- -

EHR Back Office

+ {token && client ? ( + +
+ +
+
+ +

+ EHR Back Office{' '} +

+
+ + {token.name} + +
- - {token.name} - - -
- -
- - - + +
+ + ) : ( - ) } - + )} - - ); }; diff --git a/src/containers/BackOffice/Dashboard.jsx b/src/containers/BackOffice/Dashboard.jsx index 86cb9da..a479250 100644 --- a/src/containers/BackOffice/Dashboard.jsx +++ b/src/containers/BackOffice/Dashboard.jsx @@ -7,75 +7,74 @@ import { SettingsContext } from '../ContextProvider/SettingsProvider'; import TaskTab from './TaskTab'; function a11yProps(index) { - return { - id: `simple-tab-${index}`, - 'aria-controls': `simple-tabpanel-${index}` - }; - } + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}` + }; +} export default function Dashboard(props) { - const { client, token } = props; - const [headerStyle, setHeaderStyle] = useState(undefined); - const [globalState, dispatch, updateSetting, readSettings] = React.useContext(SettingsContext); - console.log('global state patient -- > ', globalState.patient); + const { client, token } = props; + const [headerStyle, setHeaderStyle] = useState(undefined); + const [globalState, dispatch, updateSetting, readSettings] = React.useContext(SettingsContext); + console.log('global state patient -- > ', globalState.patient); + useEffect(() => { + readSettings(); + const updateScrollState = () => { + var threshold = 10; + if (window.scrollY > threshold) { + setHeaderStyle('true'); + } else { + setHeaderStyle(undefined); + } + }; + document.addEventListener('scroll', updateScrollState); + return () => document.removeEventListener('scroll', updateScrollState); + }, []); - useEffect(() => { - readSettings(); - const updateScrollState = () => { - var threshold = 10; - if (window.scrollY > threshold) { - setHeaderStyle("true"); - } else { - setHeaderStyle(undefined); - } - } - document.addEventListener("scroll", updateScrollState); - return () => document.removeEventListener("scroll", updateScrollState); - }, []); + const [tabIndex, setValue] = useState(0); - const [tabIndex, setValue] = useState(0); + const handleChange = (event, newValue) => { + setValue(newValue); + }; - const handleChange = (event, newValue) => { - setValue(newValue); - }; + return ( +
+ + + + + + + + - return ( -
- - - - - - - - - - - - {tabIndex === 0 && ( - - - - )} - {tabIndex === 1 && ( - - - - )} - - + + + {tabIndex === 0 && ( + + + + )} + {tabIndex === 1 && ( + + - -
- ); -} \ No newline at end of file + )} +
+ + +
+
+ ); +} diff --git a/src/containers/BackOffice/TaskTab.jsx b/src/containers/BackOffice/TaskTab.jsx index 5b8ef19..4db81f2 100644 --- a/src/containers/BackOffice/TaskTab.jsx +++ b/src/containers/BackOffice/TaskTab.jsx @@ -60,10 +60,14 @@ const TaskTab = props => { getPatients(); } // if use default user is set, use default user otherwise use logged in user if set - let currentUser = globalState.useDefaultUser ? globalState.defaultUser : (token.userId ? token.userId : globalState.defaultUser); - setState(prevState => ({...prevState, user: currentUser})); + let currentUser = globalState.useDefaultUser + ? globalState.defaultUser + : token.userId + ? token.userId + : globalState.defaultUser; + setState(prevState => ({ ...prevState, user: currentUser })); }, []); - + const updateStateElement = (elementName, text) => { if (elementName === 'patient') { setState(prevState => ({ ...prevState, patient: text })); @@ -78,47 +82,57 @@ const TaskTab = props => { })); } }; - + const updateStateMap = (elementName, key, text) => { setState(prevState => ({ ...prevState, [elementName]: { ...prevState[elementName], [key]: text } })); }; - + const clearState = () => { setState(prevState => ({ ...prevState, response: {} })); }; - + const handleChange = () => (event, isExpanded) => { setState(prevState => ({ ...prevState, expanded: isExpanded ? true : false })); }; - + return ( - - + + } aria-controls="panel1a-content" id="panel1a-header" > - - + {state.patient?.name ? ( // Display the first name -

{state.patient?.name?.[0]?.given?.[0] + ' ' + state.patient?.name?.[0]?.family}

+ +

+ {state.patient?.name?.[0]?.given?.[0] + ' ' + state.patient?.name?.[0]?.family} +

+
) : ( -

All Patients

+ +

All Patients

+
)}
@@ -147,18 +161,17 @@ const TaskTab = props => { )}
-
- - getPatients()} size="large"> - - - -
- - +
+ + getPatients()} size="large"> + + + +
+
); -} +}; export default TaskTab; diff --git a/src/containers/BackOffice/styles.jsx b/src/containers/BackOffice/styles.jsx index 558b986..7cbd6d7 100644 --- a/src/containers/BackOffice/styles.jsx +++ b/src/containers/BackOffice/styles.jsx @@ -1,35 +1,33 @@ -import {styled} from '@mui/system'; -import { AppBar, Stack } from '@mui/material' +import { styled } from '@mui/system'; +import { AppBar, Stack } from '@mui/material'; import { makeStyles } from '@mui/styles'; -export default makeStyles( - theme => ({ - loginIcon: { - color: theme.palette.common.white, - fontSize: '19px', - marginLeft: 'auto', - fontFamily: 'Verdana', - float: 'right', - marginRight: '20px', - verticalAlign: 'middle' - }, - whiteButton: { - color: 'white !important', - borderColor: 'white !important', - marginRight: '5px !important', - marginLeft: '20px !important', - }, - patientButton: { - padding: '10px', - 'padding-left': '20px', - 'padding-right': '20px' - } - }) -); - +export default makeStyles(theme => ({ + loginIcon: { + color: theme.palette.common.white, + fontSize: '19px', + marginLeft: 'auto', + fontFamily: 'Verdana', + float: 'right', + marginRight: '20px', + verticalAlign: 'middle' + }, + whiteButton: { + color: 'white !important', + borderColor: 'white !important', + marginRight: '5px !important', + marginLeft: '20px !important' + }, + patientButton: { + padding: '10px', + 'padding-left': '20px', + 'padding-right': '20px' + } +})); -export const StyledStack = styled(Stack)(({ theme, selected, disabled, isscrolled, highlight }) => ({ - position: 'relative', +export const StyledStack = styled(Stack)( + ({ theme, selected, disabled, isscrolled, highlight }) => ({ + position: 'relative', // width: '200px', margin: '0 5px', padding: '8px 20px 8px 20px', @@ -37,28 +35,33 @@ export const StyledStack = styled(Stack)(({ theme, selected, disabled, isscrolle borderRadius: '8px', cursor: disabled ? 'default' : 'pointer', color: disabled ? theme.palette.text.gray : theme.palette.text.primary, - backgroundColor: highlight ? theme.palette.background.primary : (selected && !isscrolled) ? theme.palette.common.offWhite : 'inherit', - transition: `border 0.5s ease`, + backgroundColor: highlight + ? theme.palette.background.primary + : selected && !isscrolled + ? theme.palette.common.offWhite + : 'inherit', + transition: 'border 0.5s ease', border: '1px solid transparent', - borderBottomColor: (selected && isscrolled) ? theme.palette.primary.main : 'transparent', - boxShadow: (selected && !isscrolled) ? 'rgba(0,0,0,0.2) 8px -2px 12px 2px' : 'none', + borderBottomColor: selected && isscrolled ? theme.palette.primary.main : 'transparent', + boxShadow: selected && !isscrolled ? 'rgba(0,0,0,0.2) 8px -2px 12px 2px' : 'none', '&:hover': { - border: disabled ? '' : `1px solid ${theme.palette.common.gray}` + border: disabled ? '' : `1px solid ${theme.palette.common.gray}` } -})); + }) +); export const GlossaryDiv = styled('div')(({ theme, isscrolled }) => ({ - backgroundColor: 'white', - zIndex: 1200, - padding: '30px', + backgroundColor: 'white', + zIndex: 1200, + padding: '30px' })); export const StyledAppBarAlt = styled(AppBar, { - shouldForwardProp: (prop) => prop !== 'open', + shouldForwardProp: prop => prop !== 'open' })(({ theme, open, isscrolled, drawerwidth }) => { - console.log(theme); - console.log(theme.palette); - return { + console.log(theme); + console.log(theme.palette); + return { marginTop: '15px', marginBottom: '15px', marginLeft: '2%', @@ -70,10 +73,10 @@ export const StyledAppBarAlt = styled(AppBar, { color: theme.palette.common.black, boxShadow: isscrolled ? 'rgba(0,0,0,0.2)' : 'none', borderRadius: '8px', - border: isscrolled ? '1px solid #c1c1c1' : 'none', + border: isscrolled ? '1px solid #c1c1c1' : 'none', ...(open && { - marginRight: `calc(2% + ${drawerwidth})`, - width: `calc(96% - ${drawerwidth}px)`, - - }), -}}); \ No newline at end of file + marginRight: `calc(2% + ${drawerwidth})`, + width: `calc(96% - ${drawerwidth}px)` + }) + }; +}); diff --git a/src/containers/ContextProvider/SettingsProvider.jsx b/src/containers/ContextProvider/SettingsProvider.jsx index caaa2be..3cf836d 100644 --- a/src/containers/ContextProvider/SettingsProvider.jsx +++ b/src/containers/ContextProvider/SettingsProvider.jsx @@ -7,10 +7,9 @@ export const SettingsContext = React.createContext({ dispatch: () => null, updateSetting: () => null, readSettings: () => null, - saveSettings: () => null, + saveSettings: () => null }); - export const SettingsProvider = ({ children }) => { const [state, dispatch] = React.useReducer(reducer, initialState); @@ -44,5 +43,9 @@ export const SettingsProvider = ({ children }) => { localStorage.setItem('reqgenSettings', JSON.stringify(headers)); }; - return {children}; + return ( + + {children} + + ); }; diff --git a/src/containers/Gateway/Gateway.jsx b/src/containers/Gateway/Gateway.jsx index 16f3e09..4b9f54c 100644 --- a/src/containers/Gateway/Gateway.jsx +++ b/src/containers/Gateway/Gateway.jsx @@ -31,7 +31,7 @@ const Gateway = props => { FHIR.oauth2.authorize({ clientId: clientId, scope: scope.join(' '), - redirectUri: props.redirect + (backOffice ? "/backoffice": ""), + redirectUri: props.redirect + (backOffice ? '/backoffice' : ''), iss: fhirUrl }); }; @@ -102,7 +102,17 @@ const Gateway = props => { )} /> - {setBackOffice(!backOffice)}} />} label="Back Office" /> + { + setBackOffice(!backOffice); + }} + /> + } + label="Back Office" + /> - + {state.patient?.name ? ( // Display the first name -

{state.patient?.name?.[0]?.given?.[0] + ' ' + state.patient?.name?.[0]?.family}

+ +

+ {state.patient?.name?.[0]?.given?.[0] + ' ' + state.patient?.name?.[0]?.family} +

+
) : ( -

All Patients

+ +

All Patients

+
)} diff --git a/src/util/auth.js b/src/util/auth.js index 5465731..74e4a99 100644 --- a/src/util/auth.js +++ b/src/util/auth.js @@ -34,9 +34,11 @@ function login() { } function logout() { - window.location.replace(`${env.get('VITE_AUTH').asString()}/realms/${env - .get('VITE_REALM') - .asString()}/protocol/openid-connect/logout`); + window.location.replace( + `${env.get('VITE_AUTH').asString()}/realms/${env + .get('VITE_REALM') + .asString()}/protocol/openid-connect/logout` + ); } /** diff --git a/src/util/data.js b/src/util/data.js index 819f044..910383c 100644 --- a/src/util/data.js +++ b/src/util/data.js @@ -1,6 +1,16 @@ import env from 'env-var'; const headerDefinitions = { + includePharmacyInPreFetch: { + display: 'Include Pharmacy in Prefetch', + type: 'check', + default: env.get('VITE_USE_PHARMACY_IN_PREFETCH').asBool() + }, + pharmacyId: { + display: 'Pharmacy ID', + type: 'input', + default: env.get('VITE_PHARMACY_ID').asString() || 'pharm0111' + }, useIntermediary: { display: 'Use Intermediary', type: 'check', @@ -109,24 +119,32 @@ const CDS_SERVICE = 'cds-services'; const ETASU_ENDPOINT = 'GuidanceResponse/$rems-etasu'; const serviceEndpoints = { - 'order-sign': CDS_SERVICE+'/rems-'+ORDER_SIGN, - 'order-select': CDS_SERVICE+'/rems-'+ORDER_SELECT, - 'patient-view': CDS_SERVICE+'/rems-'+PATIENT_VIEW, - 'encounter-start': CDS_SERVICE+'/rems-'+ENCOUNTER_START, - '$rems-etasu': '4_0_0/'+ETASU_ENDPOINT + 'order-sign': CDS_SERVICE + '/rems-' + ORDER_SIGN, + 'order-select': CDS_SERVICE + '/rems-' + ORDER_SELECT, + 'patient-view': CDS_SERVICE + '/rems-' + PATIENT_VIEW, + 'encounter-start': CDS_SERVICE + '/rems-' + ENCOUNTER_START, + '$rems-etasu': '4_0_0/' + ETASU_ENDPOINT }; - const medicationRequestToRemsAdmins = Object.freeze([ { rxnorm: 2183126, display: 'Turalio 200 MG Oral Capsule', endpoints: [ { endpointType: ORDER_SIGN, remsAdmin: 'http://localhost:8090/cds-services/rems-order-sign' }, - { endpointType: ORDER_SELECT, remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' }, - { endpointType: PATIENT_VIEW, remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' }, - { endpointType: ENCOUNTER_START, remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' }, - { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/'+ETASU_ENDPOINT } + { + endpointType: ORDER_SELECT, + remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' + }, + { + endpointType: PATIENT_VIEW, + remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' + }, + { + endpointType: ENCOUNTER_START, + remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' + }, + { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/' + ETASU_ENDPOINT } ] }, { @@ -134,10 +152,19 @@ const medicationRequestToRemsAdmins = Object.freeze([ display: 'Isotretinoin 20 MG Oral Capsule', endpoints: [ { endpointType: ORDER_SIGN, remsAdmin: 'http://localhost:8090/cds-services/rems-order-sign' }, - { endpointType: ORDER_SELECT, remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' }, - { endpointType: PATIENT_VIEW, remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' }, - { endpointType: ENCOUNTER_START, remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' }, - { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/'+ETASU_ENDPOINT } + { + endpointType: ORDER_SELECT, + remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' + }, + { + endpointType: PATIENT_VIEW, + remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' + }, + { + endpointType: ENCOUNTER_START, + remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' + }, + { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/' + ETASU_ENDPOINT } ] }, { @@ -145,10 +172,19 @@ const medicationRequestToRemsAdmins = Object.freeze([ display: 'TIRF 200 UG Oral Transmucosal Lozenge', endpoints: [ { endpointType: ORDER_SIGN, remsAdmin: 'http://localhost:8090/cds-services/rems-order-sign' }, - { endpointType: ORDER_SELECT, remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' }, - { endpointType: PATIENT_VIEW, remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' }, - { endpointType: ENCOUNTER_START, remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' }, - { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/'+ETASU_ENDPOINT } + { + endpointType: ORDER_SELECT, + remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' + }, + { + endpointType: PATIENT_VIEW, + remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' + }, + { + endpointType: ENCOUNTER_START, + remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' + }, + { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/' + ETASU_ENDPOINT } ] }, { @@ -156,10 +192,19 @@ const medicationRequestToRemsAdmins = Object.freeze([ display: 'Addyi 100 MG Oral Tablet', endpoints: [ { endpointType: ORDER_SIGN, remsAdmin: 'http://localhost:8090/cds-services/rems-order-sign' }, - { endpointType: ORDER_SELECT, remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' }, - { endpointType: PATIENT_VIEW, remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' }, - { endpointType: ENCOUNTER_START, remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' }, - { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/'+ETASU_ENDPOINT } + { + endpointType: ORDER_SELECT, + remsAdmin: 'http://localhost:8090/cds-services/rems-order-select' + }, + { + endpointType: PATIENT_VIEW, + remsAdmin: 'http://localhost:8090/cds-services/rems-patient-view' + }, + { + endpointType: ENCOUNTER_START, + remsAdmin: 'http://localhost:8090/cds-services/rems-encounter-start' + }, + { endpointType: REMS_ETASU, remsAdmin: 'http://localhost:8090/4_0_0/' + ETASU_ENDPOINT } ] } ]); diff --git a/src/util/fhir.js b/src/util/fhir.js index 69f751f..7ad5bd3 100644 --- a/src/util/fhir.js +++ b/src/util/fhir.js @@ -68,7 +68,7 @@ function createMedicationFromMedicationRequest(medicationRequest) { medication.id = medicationRequest?.id + '-med'; if (medicationRequest.medicationCodeableConcept) { medication.code = medicationRequest.medicationCodeableConcept; - } else if (medicationRequest.medicationReference) { + } else if (medicationRequest.medicationReference) { const reference = medicationRequest?.medicationReference; medication.code = undefined; medicationRequest?.contained?.every(e => {