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
13 changes: 7 additions & 6 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ThemeProvider } from '@mui/styles';
import React from 'react';
import { BrowserRouter, HashRouter, Routes, Route } from 'react-router-dom';
import RequestBuilder from '../containers/RequestBuilder';
import { BrowserRouter, HashRouter, Route, Routes } from 'react-router-dom';
import Gateway from '../containers/Gateway/Gateway';
import Index from '../containers/Index';
import Launch from '../containers/Launch';
import PatientPortal from '../containers/PatientPortal';
import RegisterPage from '../containers/register/RegisterPage';
import theme from '../containers/styles/theme';
import { ThemeProvider } from '@mui/styles';
import Launch from '../containers/Launch';
import Index from '../containers/Index';
import Gateway from '../containers/Gateway/Gateway';
const isGhPages = process.env.REACT_APP_GH_PAGES === 'true';
const Router = isGhPages ? HashRouter : BrowserRouter;
const redirect = isGhPages ? '/#/index' : '/index';
Expand All @@ -16,6 +16,7 @@ const App = () => {
<Routes>
<Route path="/launch" element={<Launch redirect={redirect} />} />
<Route path="/index" element={<Index />} />
<Route path="/register" element={<RegisterPage />} />
<Route
path="/patient-portal"
element={
Expand Down
71 changes: 48 additions & 23 deletions src/containers/Launch.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,58 @@
import React, { memo, useState, useEffect } from 'react';
import FHIR from 'fhirclient';
import env from 'env-var';
import queryString from 'querystring';
import FHIR from 'fhirclient';
import React, { memo, useEffect, useState } from 'react';
import RegisterPage from './register/RegisterPage';

const Launch = props => {
useEffect(() => {
// this is a workaround for the fhir client not being able to pull values out of the
// hash. Regex will look for different permutations of a hashrouter url /#/launch /#launch #launch /#launch
const params = queryString.parse((window.location.hash || '').replace(/\/?#\/?launch\?/, ''));

// if these are null then the client will pull them out of the browsers query string
// so we don't need to do that here.
const iss = params.iss;
const launch = params.launch;

FHIR.oauth2.authorize({
clientId: env.get('REACT_APP_CLIENT').asString(),
scope: env.get('REACT_APP_CLIENT_SCOPES').asString(),
redirectUri: props.redirect,
iss: iss,
launch: launch
});
}, []);

return (
const [content, setContent] = useState(
<div className="loading">
<h1>Launching...</h1>
</div>
);

useEffect(() => {
smartLaunch();
}, []);

const smartLaunch = () => {
let clients = JSON.parse(localStorage.getItem('clients') || '[]');
if (clients.length === 0) {
const defaultClient = env.get('REACT_APP_CLIENT').asString();
const defaultIss = env.get('REACT_APP_EHR_BASE').asString();
if (defaultClient && defaultIss) {
clients = [{ client: defaultClient, name: defaultIss }];
localStorage.setItem('clients', JSON.stringify(clients));
}
}
const urlSearchString = window.location.search;
const params = new URLSearchParams(urlSearchString);
const iss = params.get('iss');
if (iss) {
const storedClient = clients.find(e => {
return e.name == iss;
});

if (storedClient) {
// found matching iss
const clientId = storedClient.client;
FHIR.oauth2
.authorize({
clientId: clientId,
scope: env.get('REACT_APP_CLIENT_SCOPES').asString(),
redirectUri: '/index'
})
.catch(e => {
console.log(e);
});
} else {
setContent(<RegisterPage callback={smartLaunch} fhirUrl={iss} />);
}
} else {
setContent(<div>iss not found</div>);
}
};

return <div>{content}</div>;
};

export default memo(Launch);
122 changes: 122 additions & 0 deletions src/containers/register/RegisterPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import CloseIcon from '@mui/icons-material/Close';
import {
Box,
Button,
Card,
CardContent,
FormControl,
FormHelperText,
IconButton,
TextField,
Typography
} from '@mui/material';
import React, { useState } from 'react';
import './RegisterPageStyle.css';

export default function RegisterPage(props) {
const [clientId, setClientId] = useState('');
const [fhirUrl, setFhirUrl] = useState(props.fhirUrl || '');

const [currentClients, setCurrentClients] = useState(
JSON.parse(localStorage.getItem('clients') || '[]')
);

function deleteClient(client) {
const newClients = currentClients.filter(
c => !(c.name === client.name && c.client === client.client)
);
localStorage.setItem('clients', JSON.stringify(newClients));
setCurrentClients(newClients);
}

function submit(event) {
console.log('new selection add to LS');
const newClients = [...currentClients, { name: fhirUrl, client: clientId }];
setCurrentClients(newClients);
localStorage.setItem('clients', JSON.stringify(newClients));
if (props.callback) {
event.preventDefault();
props.callback(); // try launching again
}
return false;
}

return (
<>
<Box className={'registerContainer'}>
<Card sx={{ minWidth: 275 }}>
<CardContent>
<h1>Client ID Registration</h1>
{props.callback ? <h6>Client ID not found. Please register the client ID.</h6> : ''}
<Typography variant="h5" component="div" color="text.secondary">
Request Generator
</Typography>
<br></br>
<br></br>
<form onSubmit={submit} autoComplete="off">
<FormControl fullWidth={true} required={true} margin="normal">
<TextField
id="clientId"
label="Client ID"
aria-describedby="clientIdHelp"
value={clientId}
onChange={e => {
setClientId(e.target.value);
}}
/>
<FormHelperText id="clientIdHelp">
Clients must be registered with the FHIR server out of band.
</FormHelperText>
</FormControl>
<FormControl fullWidth={true} required={true} margin="normal">
<TextField
id="fhirIss"
label="ISS"
aria-describedby="fhirIssHelp"
value={fhirUrl}
onChange={e => {
setFhirUrl(e.target.value);
}}
/>
<FormHelperText id="fhirIssHelp">
The ISS is the base url of the FHIR server.
</FormHelperText>
</FormControl>
<Button
type="submit"
variant="contained"
disabled={clientId === '' || fhirUrl === ''}
>
{props.callback ? 'Submit and Retry' : 'Submit'}
</Button>
</form>
</CardContent>
</Card>
<br></br>
<Box className="clientIds">
<Typography variant="h5" component="div" color="text.secondary">
Existing Client Ids:
</Typography>

{currentClients.map((client, index) => {
return (
<div key={index} className="clientIdList">
<span style={{ marginRight: '35px' }}>
<b>{client.name}</b>: {client.client}
</span>
<IconButton
style={{ marginRight: '5px' }}
onClick={() => {
deleteClient(client);
}}
>
<CloseIcon />
</IconButton>
</div>
);
})}
</Box>
</Box>
</>
);
}
19 changes: 19 additions & 0 deletions src/containers/register/RegisterPageStyle.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
body {
background-color: #F5F5F7;
}

.registerContainer {
max-width:800px;
margin: 0;
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -40%);
}

.clientIds {
text-align: center;
}
.clientIdList {
text-align: center;
}