Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to select patient or user from a list #58

Closed
wants to merge 2 commits into from
Closed
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
"/jest-setup.js",
"/store.js"
],
"testEnvironment": "jest-environment-jsdom-global"
"testEnvironment": "jest-environment-jsdom-global",
"testURL": "http://localhost/"
}
}
3 changes: 3 additions & 0 deletions src/actions/action-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ export const UPDATE_FHIR_MEDICATION_ORDER = 'UPDATE_FHIR_MEDICATION_ORDER';

// Suggestions
export const TAKE_SUGGESTION = 'TAKE_SUGGESTION';

// User
export const SWITCH_USER = 'SWITCH_USER';
12 changes: 12 additions & 0 deletions src/actions/user-actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as types from './action-types';

/**
* Set the user in context of the application
* @param newUserId - id in the format resourceType/id (Practitioner/1234)
*/
export default function switchUser(newUserId) {
return {
type: types.SWITCH_USER,
userId: newUserId,
};
}
39 changes: 28 additions & 11 deletions src/components/BaseEntryBody/base-entry-body.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import Text from 'terra-text';
import Field from 'terra-form-field';
import Input from 'terra-form-input';
import SelectField from 'terra-form/lib/SelectField';

import styles from './base-entry-body.css';

Expand All @@ -24,17 +25,25 @@ const propTypes = {
*/
errorMessage: PropTypes.string,
/**
* If the Input component needs placeholder text (usually to help the user with example values), pass this prop in
* If the Input component needs placeholder text or the defaultValue of Select component (usually to help the user with example values), pass this prop in
*/
placeholderText: PropTypes.string,
/**
* If the value in the Input component changes (i.e user adds text), pass in a function callback to handle the text
* If the value in the Input/Select component changes (i.e user adds text or changes the selection), pass in a function callback to handle the text
*/
inputOnChange: PropTypes.func.isRequired,
/**
* The name attribute for the Input component
* The name attribute for the Input/Select component
*/
inputName: PropTypes.string,
/**
* Array of options to be displayed for selection. If this prop is not provided, a textfield input is displayed instead of a select component
*/
selectOptions: PropTypes.arrayOf(PropTypes.shape({
display: PropTypes.string.isRequired,
key: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
})),
};

/**
Expand All @@ -49,7 +58,7 @@ const propTypes = {
*/
const BaseEntryBody = ({
currentFhirServer, formFieldLabel, shouldDisplayError,
errorMessage, placeholderText, inputOnChange, inputName,
errorMessage, placeholderText, inputOnChange, inputName, selectOptions,
}) => {
let fhirServerDisplay;
if (currentFhirServer) {
Expand All @@ -70,13 +79,21 @@ const BaseEntryBody = ({
isInvalid={shouldDisplayError}
error={errorMessage}
required
>
<Input
name={inputName}
placeholder={placeholderText}
onChange={inputOnChange}
required
/>
> {selectOptions ?
(<SelectField
name={inputName}
defaultValue={placeholderText}
onChange={inputOnChange}
options={selectOptions}
required
/>) :
(<Input
name={inputName}
placeholder={placeholderText}
onChange={inputOnChange}
required
/>)
}
</Field>
</div>
</div>
Expand Down
25 changes: 22 additions & 3 deletions src/components/Header/header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import forIn from 'lodash/forIn';

import ConfigureServices from '../ConfigureServices/configure-services';
import ServicesEntry from '../ServicesEntry/services-entry';
import UserEntry from '../UserEntry/user-entry';
import PatientEntry from '../PatientEntry/patient-entry';
import FhirServerEntry from '../FhirServerEntry/fhir-server-entry';

Expand Down Expand Up @@ -64,7 +65,7 @@ const propTypes = {

/**
* This component represents the Header for the application, which encompasses the title, logo, and several configuration options. The header allows the user
* to select between different hook views (i.e. patient-view and medication-prescribe), and presents options to change the FHIR server and/or the patient in
* to select between different hook views (i.e. patient-view and medication-prescribe), and presents options to change the FHIR server and/or the patient in
* context, add CDS services, among other options.
*/
export class Header extends Component {
Expand All @@ -76,6 +77,10 @@ export class Header extends Component {
* Flag to determine if the settings menu is open
*/
settingsOpen: false,
/**
* Flag to determine if the Change User modal is open
*/
isChangeUserOpen: false,
/**
* Flag to determine if the Change Patient modal is open
*/
Expand Down Expand Up @@ -103,6 +108,8 @@ export class Header extends Component {
this.closeSettingsMenu = this.closeSettingsMenu.bind(this);
this.openAddServices = this.openAddServices.bind(this);
this.closeAddServices = this.closeAddServices.bind(this);
this.openChangeUser = this.openChangeUser.bind(this);
this.closeChangeUser = this.closeChangeUser.bind(this);
this.openChangePatient = this.openChangePatient.bind(this);
this.closeChangePatient = this.closeChangePatient.bind(this);
this.openChangeFhirServer = this.openChangeFhirServer.bind(this);
Expand All @@ -123,7 +130,7 @@ export class Header extends Component {

/**
* Determine how to make a hook tab display as the current or "active" tab or another tab
* @param {*} hook - the name of the hook
* @param {*} hook - the name of the hook
*/
getNavClasses(hook) {
return this.props.hook === hook ? cx(styles['nav-links'], styles['active-link']) : styles['nav-links'];
Expand Down Expand Up @@ -201,6 +208,12 @@ export class Header extends Component {
}
closeAddServices() { this.setState({ isAddServicesOpen: false }); }

async openChangeUser() {
this.setState({ isChangeUserOpen: true });
if (this.state.settingsOpen) { this.closeSettingsMenu(); }
}
closeChangeUser() { this.setState({ isChangeUserOpen: false }); }

/**
* Open the Change Patient modal to allow for changing the patient ID in context.
*
Expand Down Expand Up @@ -246,13 +259,15 @@ export class Header extends Component {
<Menu.Item className={styles['add-services']} text="Add CDS Services" key="add-services" onClick={this.openAddServices} />,
<Menu.Item className={styles['configure-services']} text="Configure CDS Services" key="configure-services" onClick={this.openConfigureServices} />,
<Menu.Divider className={styles['divider-1']} key="Divider1" />,
<Menu.Item className={styles['change-user']} text="Change User" key="change-user" onClick={this.openChangeUser} />,
<Menu.Divider className={styles['divider-2']} key="Divider2" />,
<Menu.Item className={styles['change-patient']} text="Change Patient" key="change-patient" onClick={this.openChangePatient} />,
];
if (!this.props.isSecuredSandbox) {
menuItems.push(<Menu.Item className={styles['change-fhir-server']} text="Change FHIR Server" key="change-fhir-server" onClick={this.openChangeFhirServer} />);
}
menuItems = menuItems.concat([
<Menu.Divider className={styles['divider-2']} key="Divider2" />,
<Menu.Divider className={styles['divider-3']} key="Divider3" />,
<Menu.Item className={styles['reset-configuration']} text="Reset Configuration" key="reset-configuration" onClick={this.resetConfiguration} />,
]);

Expand Down Expand Up @@ -314,6 +329,10 @@ export class Header extends Component {
isOpen={this.state.isConfigureServicesOpen}
closePrompt={this.closeConfigureServices}
/> : null}
{this.state.isChangeUserOpen ? <UserEntry
isOpen={this.state.isChangeUserOpen}
closePrompt={this.closeChangeUser}
/> : null}
{this.state.isChangePatientOpen ? <PatientEntry
isOpen={this.state.isChangePatientOpen}
closePrompt={this.closeChangePatient}
Expand Down
24 changes: 24 additions & 0 deletions src/components/PatientEntry/patient-entry.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import map from 'lodash/map';

import Modal from 'terra-modal';
import Button from 'terra-button';
Expand All @@ -11,6 +12,7 @@ import Text from 'terra-text';
import styles from './patient-entry.css';
import BaseEntryBody from '../BaseEntryBody/base-entry-body';
import retrievePatient from '../../retrieve-data-helpers/patient-retrieval';
import retrievePatientList from '../../retrieve-data-helpers/patientlist-retrieval';

const propTypes = {
/**
Expand Down Expand Up @@ -63,13 +65,31 @@ export class PatientEntry extends Component {
* Error message to display on the Field
*/
errorMessage: '',
patientList: [],
isLoading: true,
};

this.handleCloseModal = this.handleCloseModal.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}

async componentDidMount() {
try {
await retrievePatientList().then((entries) => {
const selectFieldOptions = map(entries, ({ resource: { id, name } }) => Object.assign({}, {
display: name[0].given.toString(),
key: id,
value: id,
}));
this.setState({ patientList: selectFieldOptions, isLoading: false });
}).catch(error => console.log('Error occured while trying to get the Patients list', error));
} catch (e) {
console.log('Error occured while trying to get the Patients list', e);
this.setState({ patientList: null, isLoading: false });
}
}

componentWillReceiveProps(nextProps) {
if (this.props.isOpen !== nextProps.isOpen) {
this.setState({ isOpen: nextProps.isOpen });
Expand Down Expand Up @@ -120,6 +140,7 @@ export class PatientEntry extends Component {

return (
<div>
{!this.state.isLoading &&
<Modal
ariaLabel="Patient"
isOpen={this.state.isOpen}
Expand All @@ -141,9 +162,12 @@ export class PatientEntry extends Component {
placeholderText={this.props.currentPatientId}
inputOnChange={this.handleChange}
inputName="patient-input"
selectOptions={this.state.patientList}
/>
</Dialog>
</Modal>
}
{this.state.isLoading && 'Its loading...'}
</div>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/components/PatientView/patient-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export class PatientView extends Component {
componentDidUpdate(prevProps) {
if (this.props.patient !== prevProps.patient ||
this.props.fhirServer !== prevProps.fhirServer ||
this.props.user !== prevProps.user ||
!isEqual(this.props.services, prevProps.services)) {
this.executeRequests();
}
Expand Down Expand Up @@ -95,6 +96,7 @@ const mapStateToProps = (store) => {
fhirServer: store.fhirServerState.currentFhirServer,
services: pickBy(store.cdsServicesState.configuredServices, isValidService),
hook: store.hookState.currentHook,
user: store.patientState.currentUser,
};
};

Expand Down
14 changes: 14 additions & 0 deletions src/components/UserEntry/user-entry.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.right-align {
text-align: right;
}

.left-aligned-text {
float: left;
}

@media screen and (min-width: 48em) {
.fixed-size {
height: 75%;
width: 100%;
}
}
Loading