Material-FHIR UI is a set of React components that implement HL7 FHIR Resources using Google's Material Design specification. It is intended as an extension to the Material UI component library.
We intend to track normative level resources only; which as of R4 are primarily the Patient and Observation tables and detail cards. Stay tuned for R5 though!
If you're interested in non-normative resources, feel free to peruse the /client/react
directories of any of the hl7-resource-*
repositories in the clinical-meteor organization.
Fast Healthcare Interoperatbility Resources
Material - User Interface
Semantically Awesome Style Sheets
React - Component Rendering
fhir-starter is available as an npm package.
npm install fhir-starter
To save the package to your Meteor app's package.json
file, run the following:
meteor npm install --save fhir-starter winston
Material-UI was designed with the Roboto font in mind. So be sure to include it in your project. Here are some instructions on how to do so.
fhir-starter components require a theme to be provided. The quickest way to get up and running is by using the MuiThemeProvider
to inject the theme into your application context. Following that, you can to use any of the components as demonstrated in the documentation. Here is a quick example to get you started:
import React from 'react';
import ReactDOM from 'react-dom';
import * as ReactDOMClient from 'react-dom/client';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import MyAwesomeReactComponent from './MyAwesomeReactComponent';
import { PatientCard } from 'fhir-starter';
import {
MuiThemeProvider,
makeStyles,
createMuiTheme,
} from '@material-ui/core/styles';
const App = () => (
<MuiThemeProvider>
<PatientCard />
</MuiThemeProvider>
);
// ReactDReactDOM
OM.render(
ReactDOMClient.createRoot(
<App />,
document.getElementById('app')
);
Patient Table Example
import React from 'react';
import { PatientsTable } from 'fhir-starter';
const MyFhirWorkflowComponent = () => (
<div>
<PatientsTable
noDataMessagePadding={100}
patients={ Patients.find().fetch() }
paginationLimit={ t100 }
appWidth={ Session.get('appWidth') }
actionButtonLabel="Send"
onRowClick={ function(patientId){
Session.set('selectedPatientId', patientId);
}}
/>
<hr />
<PatientDetail
id='patientDetails'
fhirVersion="3.0.1"
patient={ Patients.findOne("").fetch() }
patientId={ this.data.selectedPatientId }
onDelete={ function(patientId){
Patients.remove({_id: patientId})
}}
onUpsert={ function(context){
let newPatient = context.state.patient;
newPatient.resourceType = "Patient";
Patients.insert(newPatient)
}}
onCancel={ this.onCancelUpsertPatient }
/>
</div>
);
export default MyFhirWorkflowComponent;
Please refer to each component's documentation page to see how they should be imported.
PatientCard
PatientsTable
PatientDetail
Material FHIR UI has a peer dependency on the winston
library. The idea is that we wanted to slowly migrate away from using console.log
messages. While widely supported, they cause security and performance problems. Our general approach in this refactor has been to attach the winston logger
object on the global window scope, in essentially the same place that console
is located. The idea is that if the code could do a console.log
it will also be able to do a logger.log
. Which begins our refactor. Eventually, we plan on passing the logger
object down through the render tree via the props
object.
// if you don't use winston, or otherwise wish to simply disable logging,
// attach the following to the global scope
window.logger = {
error: function(){},
warn: function(){},
info: function(){},
verbose: function(){},
debug: function(){},
trace: function(){},
data: function(){},
log: function(){}
}
// otherwise, we import the necessary objects form winston
import { createLogger, addColors, format, transports, config } from 'winston';
// lets create a global logger
const logger = createLogger({
level: get(Meteor, 'settings.public.loggingThreshold') ,
levels: {
error: 0,
warn: 1,
info: 2,
verbose: 3,
debug: 4,
trace: 5,
data: 6
},
transports: [
new transports.Console({
colorize: true,
format: format.combine(
hideDataLogLevel(),
format.colorize(),
format.simple(),
format.splat(),
format.timestamp()
)
})
],
exitOnError: false
});
// introspection for the win
logger.info('Starting the Winston Logging Service');
logger.data('Winston Logging Service', {data: logger}, {source: "AppContainer.jsx"});
// attaching to the global scope is not generally recommended
// logging is one debatable exception to the general rule, however
window.logger = global.logger = logger;
This project is licensed under the terms of the MIT license
If you would like to develop more FHIR components using this pattern, please take a look at the [material-fhir-demo], which is the minimalist Meteor rig we use to build these components. We intend to move towards Chromatic and Storybook in the future.
https://github.com/meteor/chromatic/
https://storybook.js.org/
https://github.com/clinical-meteor/material-fhir-demo
// LOCAL DEVELOPMENT
git clone https://github.com/clinical-meteor/fhir-starter packages/fhir-starter
meteor npm link packages/fhir-starter
cd packages/fhir-starter
yarn add rollup rollup-plugin-terser rollup-plugin-typescript2 typescript rollup-plugin-babel rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-replace rollup-plugin-progress @babel/core @babel/preset-env --only=dev
// bump the fhir-starter/package.json version number
nano package.json
// bump the application's dependency on fhir-starter
nano ../../package.json
// get rollup working
yarn rollup --config rollup.config.js
// once you get the above working, use --watch to automatically recompile on file change
yarn rollup --config --watch
// resync
// sometimes you need to resync the package
yarn rollup --config
meteor reset
rm -rf node_modules
meteor npm install
meteor npm link packages/fhir-starter
- How I set-up a React component library with Rollup- Building and publishing a module with typescript and rollup.js
- Publishing an NPM package with rollup and babel
- How to publish a JS library to NPM with rollup and typescript
- The crucial tool for modern frontend engineers
cd packages/fhir-starter
rm -rf node_modules
npm update --force
// typical rollup
yarn rollup --config
npm login
npm publish