UNPKG

ng-smart-on-fhir

Version:

[![SRDC](https://www.srdc.com.tr/wp-content/uploads/2014/12/srdc-wp.png)](https://srdc.com.tr/en)

408 lines (318 loc) 16.4 kB
[![SRDC](https://www.srdc.com.tr/wp-content/uploads/2014/12/srdc-wp.png)](https://srdc.com.tr/en) # NgSmartOnFhir - 🔥HL7 SMART-on-FHIR Library for Angular [![Angular v17](https://img.shields.io/badge/Angular-v17.3.0-blue.svg)](https://v17.angular.io/docs) [![NPM](https://img.shields.io/npm/v/ng-smart-on-fhir.svg)](https://www.npmjs.com/package/ng-smart-on-fhir) [![HL7 FHIR](https://img.shields.io/badge/HL7-FHIR-red.svg)](https://hl7.org/fhir/) An Angular library to provide SMART-on-FHIR authorization with: - Login, Callback, Launch pages - Routing wrapper - Routing Guard - SMART-on-FHIR authentication service - Authenticated FHIR client service - SMART Health Card QR reader and parser components This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.0. ## Build Run `ng build ng-smart-on-fhir` to build the project. The build artifacts will be stored in the `dist/` directory. ## Installation ### 1. Library and FHIR typings ``` npm install @types/fhir --save-dev npm install ng-smart-on-fhir --save ``` ### 2. Bootstrap (Optional) The `ng-smart-on-fhir` library has visual components such as the Login page. If you prefer to use the library's predefined bootstrap theme, you need to install Bootstrap as well. ``` npm install bootstrap --save ``` ## Usage ### 1. Importing the Module Import the `SmartOnFhirModule` to your app module with the necessary [configurations](smartonfhirconfig). ***app.module.ts*** ```{ts} import { SmartOnFhirModule } from '@srdc/smart-on-fhir'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, SmartOnFhirModule.forRoot(environment.smartConfig) // import module with configurations ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ``` ***environment.ts*** ```{ts} export const environment = { smartConfig: { clientIds: { // Client IDs to be used in Launch flow 'https://lforms-smart-fhir.nlm.nih.gov/v/r4/fhir': 'srdc-qrisk' }, redirectUrl: appBaseUrl + '/callback', loginClients: [ // buttons for initiating SMART Login flow { label: 'EPIC', image: 'asset/epic.png', // image to be displayed in login page // if image is not provided, a button with the label will be shown // you can set background, color, etc. to customize the button iss: 'https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4/', redirectUri: appBaseUrl + '/callback', clientId: '<epic-client-id>', scope: 'launch launch/patient patient/*.*' } ], launchClients: [ // links to the providers with SMART Launch flow { label: 'NIH - Smart Launch', background: '#326295', color: 'white', url: 'https://lforms-smart-fhir.nlm.nih.gov/' } ] } } ``` Configuration model is described below: #### SmartOnFhirConfig | Field | Optional | Type | Description | |-------------------------------|-------------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------| | logo | true | string | Logo image url to be used in Login page | | title | true | string | Title string to be used in Login page | | shcLoginEnabled<sup>[1]</sup> | true | boolean | Enable login with Smart Health Cards (SHC) | | shcCallbackUrl<sup>[1]</sup> | true | string | Callback url to handle SHC Logins | | clientIds<sup>[2]</sup> | conditional | object | { Issuer -> clientId } mappings for launch clients | | clientId<sup>[2]</sup> | conditional | string | Client ID if there is single client ID for any client or to use when the issuer is not matched during launch | | redirectUrl<sup>[2]</sup> | conditional | string | Redirect Url for Launch clients | | launchClients<sup>[2]</sup> | true | Array<[LaunchClientConfig](#launchclientconfig)> | List of clients using SMART App Launch flow | | loginClients<sup>[3]</sup> | true | Array<[LoginClientConfig](#loginclientconfig)> | List of clients using the SMART Login flow | *[1] The "SMART Health Cards" is a standard developed by HL7 and piloted during the COVID pandemic to allow citizens share their vaccination data as QR codes with trusted authorities. [Learn More]()* *[2] The SMART App Launch flow allows integration between FHIR based EHR systems and other applications by defining a standard to grant permissions to an application directly from the EHR's launcher application. [Learn More]()* *[3] The SMART Login flow is an authentication mechanism based on OAuth2 with the addition of SMART scopes that indicates the access rights for a patient's data in the EHR. [Learn More]()* #### LaunchClientConfig | Field | Optional | Type | Description | |-----------------------------|----------|--------|-----------------------------------------| | label | false | string | Label of the launcher EHR | | url | false | string | URL of the EHR that contains the launch | | image | true | string | Image of the EHR logo<sup>*</sup> | | icon | true | string | Icon class for the button | | background | true | string | Background color of the button | | color | true | string | Text color of the button | **If the `image` is provided, it will be shown in the login page. Otherwise, it will appear as a button with `label` as text.* #### LoginClientConfig export interface LoginClientConfig { promptLogin?: boolean; logoutUri?: string; isPublic?: boolean; } | Field | Optional | Type | Description | |-------------|----------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| | label | false | string | Label of the launcher EHR | | image | true | string | Image of the EHR logo<sup>*</sup> | | icon | true | string | Icon class for the button | | background | true | string | Background color of the button | | color | true | string | Text color of the button | | clientId | false | string | Client ID of the application in the login provider | | iss | false | string | Issuer (login provider) | | redirectUri | false | string | Callback page after login to handle token | | scope | false | string | Requested scopes (add `launch/patient` scope for the patient facing apps) | | aud | true | string | Use if the `aud` claim should be different than the `iss` | | promptLogin | true | boolean | If set to true, the prompt=login parameter is added to the authentication request so the user will be asked for credentials even if an active session exists | | logoutUri | true | string | Logout url of the authentication provider to securely terminate the user session | | isPublic | true | boolean | If set to true, the authentication will be disabled. Additionally, if `launch/patient` scope exists, a patient selection page will be shown. | **If the `image` is provided, it will be shown in the login page. Otherwise, it will appear as a button with `label` as text.* ### 2. Adding SMART Routes (Login, Callback, Launch) to Your Application Adding SMART authentication handling routes in your **Routing Module**: ``` import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import {withSmartHandlerRoutes} from "smart-on-fhir"; import {HomeComponent} from "./home/home.component"; import {ResultsComponent} from "./results/results.component"; const routes: Routes = withSmartHandlerRoutes( // wrap your own routes with the SMART routes [ { path: '', component: HomeComponent } ], // your app routes '/', // base url to be redirected 'both', // supported login methods; options are: 'launch'|'client'|'both' true // redirect to login page if not authorized ); @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } ``` > The `withSmartHandlerRoutes` method adds an auth Guard to your routes automatically if `redirectToLoginIfUnauthorized` parameter is `true`. ### 3. Inject the SMART Fhir Client Service in Your Components ``` ... import {SmartOnFhirService} from "@srdc/smart-on-fhir" @Component({ selector: 'app-component', templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent { private client: Client|undefined; patient: fhir4.Patient|undefined; vitalSigns: fhir4.Bundle<fhir4.Observation>|undefined; constructor(private smartOnFhirService: SmartOnFhirService) {} async ngOnInit() { this.patient = await this.sof.getPatient(); this.vitalSigns = await this.sof.search<fhir4.Observation>( "Observation", { category: 'vital-signs' } ); } ... ``` ### 4. Theming The NgSmartOnFhir library provides two predefined themes: - Default - Bootstrap #### Default Theme You can import the default theme to your root `style.scss` file, or to the project styles in `angular.json`. ```{sass} @import 'node_modules/ng-smart-on-fhir/themes/default.scss' ``` You can also override the classes to design a custom theme: ``` @import 'node_modules/ng-smart-on-fhir/themes/default.scss' .sof-shadow { box-shadow: 0 0 2px 0 #ccc; } .sof-light-background { background: #e0e0e0 !important; } .sof-primary-background { background: #16A4D8 !important; } .sof-text-light { color: #ffffff !important; } .sof-text-gray { color: #999999 !important; } .sof-text-dark { color: #000000 !important; } .sof-text-danger { color: #ba1239 !important; } .sof-text-center { text-align: center; } .sof-text-bold { font-weight: bold; } .sof-card { box-shadow: 0 0 3px 0 #eee; } .sof-card-header { background: #1181aa; color: white; } .sof-login-card-header { /* ... */ } .sof-button { background: #ffffff; color: #000000; &:hover { background: #e0e0e0; } } /* .sof-button-[primary, secondary, ...] { ... } */ .sof-alert-danger { background: #ff979b; color: #550509; } .sof-login-client-w-image { /* ... */ } /* ... */ ``` You can find the custom classes in the [default.scss](https://github.com/srdc/ng-smart-on-fhir/blob/main/src/lib/themes/default.scss) file. #### Bootstrap Theme You can import bootstrap css to your project in `angular.json`: ``` { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { ... "architect": { "build": { ... "styles": [ "node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.css" ], "scripts": [] }, ... "test": { ... "styles": [ "node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.css" ], "scripts": [] } } } } } } ``` Or you can import it to your `styles.scss` and customize theme variables: ``` /* You can add global styles to this file, and also import other style files */ @import "../../../node_modules/bootstrap/scss/functions"; $_primary: #761eb1; $_secondary: #9328DA; $theme-colors: ( "light": #f5f5f5, "dark": adjust-hue(shade-color($_primary, 45), 10), "primary": $_primary, "secondary": $_secondary, "info": #abedf6, "success": #b8e186, "warning": #fde47f, "danger": #f32509, "primary-text": #f8f9fa, "secondary-text": #f8f9fa ); .btn { color: #f8f9fa !important; } .input-group > input:focus + .input-group-text { background: $_primary !important; } @import "../../../node_modules/bootstrap/scss/variables"; @import "../../../node_modules/bootstrap/scss/variables-dark"; @import "../../../node_modules/bootstrap/scss/maps"; @import "../../../node_modules/bootstrap/scss/mixins"; @import "../../../node_modules/bootstrap/scss/root"; @import "../../../node_modules/bootstrap/scss/buttons"; @import "../../../node_modules/bootstrap/scss/bootstrap"; ``` After importing bootstrap, add the bootstrap theme to your root `styles.scss` file or `angular.json`: ``` /* ...import/customize bootsrap */ @import '../../../node_modules/ng-smart-on-fhir/themes/bootstrap.scss'; ``` ## Development You can continue development of this library by including it as a `devDependency` in your `package.json`. Before doing it, you will need to link the library. First, build the library: ``` cd path/to/smart-on-fhir ng build smart-on-fhir ``` Then, link the `smart-on-fhir` library globally: ``` cd path/to/smart-on-fhir/dist/smart-on-fhir npm link ``` Next, link the `smart-on-fhir` library to your project: ``` cd path/to/your-project npm link smart-on-fhir ``` Finally, add your `smart-on-fhir` library as a `devDependency` in your `package.json`: ``` "devDependencies": { "smart-on-fhir": "file:.path/to/smart-on-fhir/dist/smart-on-fhir", } ``` Import the module in your project with something like this: ``` import { SmartOnFhirModule } from "../../../../../../smart-on-fhir/projects/smart-on-fhir/src/lib/smart-on-fhir.module"; ```