Skip to content

Commit 20c9549

Browse files
authored
Merge pull request #175 from mcode/communication-display
Display FHIR Communications resources from the FHIR server
2 parents 64cf242 + 9428633 commit 20c9549

9 files changed

Lines changed: 585 additions & 42 deletions

File tree

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ VITE_USE_PHARMACY_IN_PREFETCH = true
3030
VITE_INTERMEDIARY = http://localhost:3003
3131
VITE_DISABLE_MEDICATION_STATUS = false
3232
VITE_PHARMACY_ID = pharm0111
33+
VITE_PACIO_EHR_URL = https://gw.interop.community/paciosandbox2/open/Bundle
34+
VITE_PACIO_NEW_PRESCRIBER_ID=pra1234

src/PrefetchTemplate.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
export class PrefetchTemplate {
44
static generatePrefetchMap(settings = null) {
55
// If no settings provided, use defaults from data.js
6-
const includePharmacy = settings?.includePharmacyInPreFetch ??
7-
headerDefinitions.includePharmacyInPreFetch.default;
8-
const pharmacyId = settings?.pharmacyId ??
9-
headerDefinitions.pharmacyId.default;
6+
const includePharmacy =
7+
settings?.includePharmacyInPreFetch ?? headerDefinitions.includePharmacyInPreFetch.default;
8+
const pharmacyId = settings?.pharmacyId ?? headerDefinitions.pharmacyId.default;
109

1110
const prefetchMap = new Map();
1211

@@ -64,7 +63,7 @@ export class PrefetchTemplate {
6463
) {
6564
const prefetchMap = PrefetchTemplate.generatePrefetchMap(settings);
6665
const paramElementMap = PrefetchTemplate.generateParamElementMap();
67-
66+
6867
var resolvedQueries = new Map();
6968
for (var i = 0; i < prefetchKeys.length; i++) {
7069
var prefetchKey = prefetchKeys[i];
@@ -73,7 +72,7 @@ export class PrefetchTemplate {
7372
// Regex source: https://regexland.com/all-between-specified-characters/
7473
var parametersToFill = query.match(/(?<={{).*?(?=}})/gs);
7574
var resolvedQuery = query.slice();
76-
75+
7776
if (parametersToFill) {
7877
for (var j = 0; j < parametersToFill.length; j++) {
7978
var unresolvedParameter = parametersToFill[j];
@@ -135,4 +134,4 @@ export class PrefetchTemplate {
135134
getQuery() {
136135
return this.query;
137136
}
138-
}
137+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Button, Grid } from '@mui/material';
2+
import DeleteIcon from '@mui/icons-material/Delete';
3+
import useStyles from './styles';
4+
5+
const Communication = props => {
6+
const classes = useStyles();
7+
const { communication, deleteCommunication } = props;
8+
9+
const convertTimeStamp = timeStamp => {
10+
const date = new Date(timeStamp);
11+
return date.toLocaleString();
12+
};
13+
14+
return (
15+
<div>
16+
<Grid container>
17+
<Grid className={classes.communicationHeader} item xs={2}>
18+
{`ID: ${communication.id}`}
19+
</Grid>
20+
<Grid className={classes.communicationHeader} item xs={8.7}>
21+
{`Received: ${convertTimeStamp(communication.received)}`}
22+
</Grid>
23+
<Grid className={classes.communicationHeaderButton} item xs={1.3}>
24+
<Button
25+
fullWidth
26+
variant="contained"
27+
color="error"
28+
startIcon={<DeleteIcon />}
29+
onClick={() => {
30+
deleteCommunication(communication.id);
31+
}}
32+
>
33+
Clear
34+
</Button>
35+
</Grid>
36+
<Grid className={classes.communicationDescription} item xs={12}>
37+
{communication.payload[0].contentString}
38+
</Grid>
39+
</Grid>
40+
</div>
41+
);
42+
};
43+
44+
export default Communication;
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { useEffect, useState } from 'react';
2+
3+
import { Button, Grid } from '@mui/material';
4+
import NotificationsIcon from '@mui/icons-material/Notifications';
5+
import Badge from '@mui/material/Badge';
6+
import Dialog from '@mui/material/Dialog';
7+
import DialogTitle from '@mui/material/DialogTitle';
8+
import DialogContent from '@mui/material/DialogContent';
9+
import { Refresh } from '@mui/icons-material';
10+
11+
import { styled } from '@mui/material/styles';
12+
import Paper from '@mui/material/Paper';
13+
import Communication from './Communication';
14+
15+
const CommunicationsDialog = props => {
16+
const { client, token } = props;
17+
const [state, setState] = useState({
18+
client: client,
19+
token: token,
20+
initialLoad: true,
21+
communicationCount: 0,
22+
communications: [],
23+
open: false
24+
});
25+
26+
const debugLog = message => {
27+
console.log('CommunicationsDialog: ' + message);
28+
};
29+
30+
useEffect(() => {
31+
// reload on page load and dialog open
32+
if (state.initialLoad) {
33+
setState(prevState => ({ ...prevState, initialLoad: false }));
34+
getCommunications();
35+
}
36+
37+
const interval = setInterval(() => {
38+
// page load...
39+
getCommunications();
40+
}, 1000 * 5); // reload every 5 seconds
41+
42+
return () => clearInterval(interval);
43+
});
44+
45+
const getCommunications = () => {
46+
if (state.client) {
47+
// try to read communications from FHIR server
48+
state.client
49+
.request(`Communication?recipient=${props.token?.userId}`, {
50+
graph: false,
51+
flat: true
52+
})
53+
.then(bundle => {
54+
loadCommunications(bundle);
55+
});
56+
}
57+
};
58+
59+
const deleteCommunication = id => {
60+
debugLog('deleteCommunication: ' + id);
61+
if (id) {
62+
state.client.delete(`Communication/${id}`).then(() => {
63+
debugLog(`Deleted communication: ${id}`);
64+
getCommunications();
65+
});
66+
}
67+
};
68+
69+
const loadCommunications = bundle => {
70+
let count = bundle.length;
71+
setState(prevState => ({ ...prevState, communicationCount: count, communications: bundle }));
72+
};
73+
74+
const handleClose = () => {
75+
setState(prevState => ({ ...prevState, open: false }));
76+
};
77+
78+
const Item = styled(Paper)(({ theme }) => ({
79+
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#EDF6FF',
80+
...theme.typography.body2,
81+
padding: theme.spacing(1),
82+
textAlign: 'left',
83+
color: theme.palette.text.secondary
84+
}));
85+
86+
const renderCommunications = () => {
87+
return (
88+
<Grid container spacing={2} sx={{ mt: 2 }}>
89+
{state.communications.map(communication => {
90+
return (
91+
<Grid item xs={12} sm={12}>
92+
<Item>
93+
<Communication
94+
communication={communication}
95+
deleteCommunication={deleteCommunication}
96+
/>
97+
</Item>
98+
</Grid>
99+
);
100+
})}
101+
</Grid>
102+
);
103+
};
104+
105+
return (
106+
<span>
107+
<span
108+
onClick={() => {
109+
setState(prevState => ({ ...prevState, open: true, initialLoad: true }));
110+
}}
111+
>
112+
<Badge badgeContent={state.communicationCount} color="primary">
113+
<NotificationsIcon sx={{ fontSize: 26, verticalAlign: 'middle' }} />
114+
</Badge>
115+
</span>
116+
<Dialog fullWidth maxWidth="md" onClose={handleClose} open={state.open}>
117+
<DialogTitle>
118+
<Grid container>
119+
<Grid item xs={10}>
120+
<NotificationsIcon sx={{ fontSize: 26, verticalAlign: 'middle' }} />
121+
Communications ({state.communicationCount})
122+
</Grid>
123+
<Grid item xs={2}>
124+
<Button
125+
variant="contained"
126+
startIcon={<Refresh />}
127+
onClick={() => {
128+
getCommunications();
129+
}}
130+
>
131+
Refresh
132+
</Button>
133+
</Grid>
134+
</Grid>
135+
</DialogTitle>
136+
137+
<DialogContent>{renderCommunications()}</DialogContent>
138+
</Dialog>
139+
</span>
140+
);
141+
};
142+
143+
export default CommunicationsDialog;

src/components/RequestDashboard/Home.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import SettingsIcon from '@mui/icons-material/Settings';
66
import AccountBoxIcon from '@mui/icons-material/AccountBox';
77
import MedicalServicesIcon from '@mui/icons-material/MedicalServices';
88

9+
import CommunicationsDialog from './CommunicationsDialog';
910
import useStyles from './styles';
1011
import PatientSection from './PatientSection';
1112
import SettingsSection from './SettingsSection';
@@ -82,8 +83,10 @@ const Home = props => {
8283
{/* spacer */}
8384
{/** */}
8485
{section ? (
85-
<Grid className={classes.spacer} item xs={4}>
86+
<Grid className={classes.spacer} item xs={5}>
8687
<span className={classes.loginIcon}>
88+
<CommunicationsDialog client={props.client} token={token} />
89+
&nbsp;&nbsp;
8790
<AccountBoxIcon sx={{ fontSize: 48, verticalAlign: 'middle' }} /> {token.name}
8891
<Button variant="outlined" className={classes.whiteButton} onClick={logout}>
8992
Logout
@@ -115,7 +118,7 @@ const Home = props => {
115118
<TasksSection client={props.client} userName={token.name} userId={token.userId} />
116119
</div>
117120
<div className={settingsRenderClass}>
118-
<SettingsSection client={props.client} />
121+
<SettingsSection client={props.client} userId={token.userId} />
119122
</div>
120123
</div>
121124
);

0 commit comments

Comments
 (0)