# Onegevity UI-Kit front-end library
# Overview
The Onegevity UI-Kit is a JavaScript library that offers a suite of capabilities that greatly simplifies the process of integrating the Onegevity Health Intelligence Service into your web application. These capabilities include:
- Built-in client SDKs for all of the Onegevity APIs
- Non-intrusive, secure authentication flow for obtaining API access tokens
- Rich UI components for performing all common actions needed to manage patient data throughout the process lifecycyle
- An embeddable Single Page Application (SPA) that brings all of the above together into a complete user experience that can be hosted on a single page
Keep reading to learn how integrate the UI-Kit into your web application and begin leveraging Onegevity's Health Intelligence Service in your application.
# Installation
Onegevity provides two methods for adding the UI-Kit to your web project. Choose the one that best fits our application build / deployment pattern.
# NPM module
If you are using npm and a JavaScript bundler (like webpack, rollup, etc.) you may find it most convenient to add our package as a dependency of your project.
npm install @onegevity/ui-kit
The ui-kit npm package exports two classes for you to use:
- OG - Provides access to the authentication flow
- UIKit - Provides access to all of the UI components and the SPA component
import {OG, UIKit} from '@onegevity/ui-kit'
As we'll discuss shortly, depending on your integration pattern you may not use both of these classes.
For browser use only
The UI-Kit library is a frontend library and expects to be running in a browser context. It will not function when run in a server environment.
# <script> tag
You can also integrate the UI-Kit library into your web application by including it on your page using a <script> tag.
You may reference the script from our content distribution network or you may download the library and include it in your application.
<script>
function initOnegevity({ OG, UIKit }) {
// Add code here to work with the UI-Kit .. examples to follow
}
</script>
<script src="https://cdn.onegevity.com/artifacts/onegevity-ui-kit/onegevity-ui-kit.1.0.0.js"></script>
# Authentication and Authorization
In order to access the full range of Onegevity UI Kit features you will need to access data from the Onegevity API and that means that first you must authenticate your application with the Onegevity API. The UI-Kit provides an out-of-the box facility for coordinating the OAuth2 Authorization Code authentication flow. If you are unfamiliar with OAuth2 it may be worth your while to read a bit about OAuth (opens new window) and Authorization Code (opens new window) to understand what's happening behind the scenes.
# Prerequisites
Before you get started, you'll need to have the following things in hand:
- Register your account with Onegevity and have obtained your OAuth Client ID and Client Secret
- Registered and validated your website domain with Onegevity
# Implementing the Authorization Code authentication flow
In short, the OAuth2 Authorization Code flow is used to establish trust between three parties: your end user, your website, and the Onegevity API, with the goal being to safely and securely allow your users private data (hosted by the Onegevity API) to be surfaced in their browser when using your website. The flow is performed in three steps:
- The end user's browser requests an authorization code from the Onegevity API authorization server, passing in a state parameter and a redirect URI (hosted on your website)
- The browser request is redirected to your website with the state parameter and an authorization code. Your server then must call the Onegevity API to exchange the authorization code for an access token
- The response from your server provides the access token to the user's browser, which uses it to make authenticated requests to the Onegevity API
# Front-end implementation
The UI-Kit provides a facility for performing steps 1 and 3, while you must implement step 2 in your website code.
To initiate the authorization flow call the OG.authUIKit() function, as demonstrated in the example below:
// Authenticate with the Onegevity service to initialize the UIKit.
const authOptions = {
// this will point to the onegevity api base url .. be sure to use the staging url for testing purposes
ogBasePath: 'https://api.onegevity.com',
// your unique OAuth Client ID for your application, provided to you by Onegevity
clientId: 'example-id',
// an endpoint implemented on your server that finalizes the authentication (must be https://)
redirectUri: 'https://www.example.com/onegevity/complete-authorization',
// a CSRF-prevention state value that must be unique to the end user's web session.
// your website backend is responsible for providing this value
state: '{{{state}}}',
// the user's unique Onegevity Patient identifier
// your website backend is responsible for providing this value
patientId: '{{{patientIdentifier}}}',
}
// returns a Promise that, when successful, yields an authenticated UIKit object
const authUIKit = OG.authUIKit(authOptions)
# Back-end implementation
In this scheme your website backend is responsible for 3 things:
- Providing a globally unique patientIdentifier that will be used to identify your logged in user in the Onegevity API.
patientIdentifier
A customerId or hashed email address are good options to use as your patientIdentifier.
- Computing a CSRF-prevention state parameter that can be used to verify the authenticity of the incoming request to exchange the authorization code for the access token
state
To fulfill it's job as a CSRF-prevention mechanism, regardless of how you generate your state parameter, you'll need to be able to retrieve or regenerate it on the subsequent web request to verify that the request is valid.
A good approach is to generate a lengthy random String and store it in the user's server-side session.
- Implementing an endpoint that will be called to exchange the authorization code for the access token
Register your endpoint with Onegevity
In order to complete the implementation process and begin testing your integration you must register your redirect endpoint with Onegevity.
Validate state
If the incoming state parameter on the request does not match, you must deny the request. Otherwise, POST a request to the /oauth/token endpoint on the Onegevity API to retrieve the access token and return the access token as the body of your response.
Example Code The following code examples demonstrate how a backend server might set up to complete the UI-Kit authorization flow
# Using the UIKit components
Once, an authenticated UIKit is initialized, full access to the functionality of the
component library is enabled. You can choose what is best for your use case: you can
use the SPA to provide access to all of the functionality from just one page or you can
choose to only load a certain component on your page. Either way, the usage pattern is
essentially the same. Examples of each are provided in the following sections.
# Using the UIKit Single Page Application
The SPA approach gives you a single component that you load into your page and it provides a complete UI for all of the functionality needed to interact with the Onegevity service:
- A page for listing and requesting tests for a patient
- A page for filling out surveys for tests
- A page for activating sample collection kits
- A page for reviewing the final results of a test
/*
target is the only required option of the `spa` function.
It must point to the target element where the SPA with be rendered.
*/
const target = document.querySelector('#demo')
/*
The second argument is completely optional, but would include a map
with a single key `patientInfo` containing additional information
about the patient that is not available through the Onegevity API.
All information is optional, but all available keys are enumerated
below.
*/
authUIKit.then((uiKit) => uiKit.patientSpa(target, {
patientInfo: {
email: /*[[${patientEmail}]]*/ '',
addressLine1: /*[[${patientAddressLine1}]]*/ '',
city: /*[[${patientCity}]]*/ '',
countryCode: /*[[${patientCountryCode}]]*/ '',
regionCode: /*[[${patientRegionCode}]]*/ '',
postalCode: /*[[${patientPostalCode}]]*/ '',
phone: /*[[${patientPhone}]]*/ '',
}
}))
# Using the Reports component
The Reports component is used to present the final report of a patient's test results. If the patient has multiple results for the same package (say they have retested every year) then it also provides a facility to view those historical results as well as display trendlines over time.
// Use the initialized UIKit to initialize the reports component
const reportOptions = {
// required. The Package Identifier for the test results being displayed.
packageId: 'BIOAGE',
// required. The order identifier for the initial results.
orderId: '300554-BA3',
}
/*
The `reports` components will display a historical view of all
results for the authenticated onegevity patient that match the
provide package identifier. The results for the provided order
identifier will be displayed first.
*/
const target = document.querySelector('#demo')
authUIKit.then(uiKit => uiKit.patientReports(target, reportOptions))
# Using the Survey component
The Survey component displays a step-by-step user interface for completing questionnaires or surveys needed to gather health information for a patient.
// Use the initialized UIKit to initialize the survey component
const surveyOptions = {
// required. The survey key of the requested survey.
surveyKey: 'thorne-health-profile',
// required. The order identifier associated with the requested survey.
orderId: '300554-1626808484301',
}
// The `survey` component will render a survey with all validation and submission logic provided.
const target = document.querySelector('#demo')
authUIKit.then(uiKit => uiKit.patientSurvey(target, surveyOptions))
# Using the Order component
The Order component is useful to display a form that collects all of the patient information necessary to submit an order for services to the Onegevity API.
// Use the initialized UIKit to initialize the order component
const orderOptions = {
/*
optional. Patient information that is otherwise not known
by the onegevity api. This information will auto populate
the relevant form fields to provide a smoother user experience.
*/
patientInfo: {
email: 'dapper@dan.com',
addressLine1: '1234 Somewhere Dr.',
city: 'Appleton',
countryCode: 'US',
regionCode: 'WI',
postalCode: '53590',
phone: '609-432-2345',
}
}
const target = document.querySelector('#demo')
authUIKit.then(uiKit => uiKit.patientOrder(target, orderOptions))
# Using the Activation Component
The Activation component provides a simple form needed to allow a patient to activate their sample collection kit.
// Use the initialized UIKit to initialize the activation component
const activationOptions = {
// required. The Kit element identifier for the kit being activated.
kitElementId: 'THYROID_KIT',
// required. The order identifier associated with the kit being activated.
orderId: '300554-1626808484301',
}
// The `activation` component provides a simple ui for activated a patients kit.
// and includes all frontend validation.
const target = document.querySelector('#demo')
authUIKit.then(uiKit => uiKit.patientActivation(target, activationOptions))
# Advanced Usage
# Backend data-fetching
In some situations you may decide that you need to integrate with the Onegevity API through your backend and will be obtaining access tokens on the server side, instead of doing it on the front-end using the UI-Kit authorization flow.
In this case you can still use the UIKit components to do the heavy lifting of rendering the data
even if you load it from the API in your website back end. Simply retrieve the data from the
Onegevity API on your server and make the resulting JSON objects available in the HTML document
by some mechanism (either an endpoint on your server that you secure, or by rendering the JSON
out into a <script> tag) and then pass the data directly into the component methods.
# Dynamic content slots
The UI-Kit components provide an eventing pattern that allows you to insert dynamic content of your own design into the visual elements it creates at specific, named slots by simply registering an event handler. This gives you the flexibility to add context to the information provided by the Onegevity platform that is relevant to your audience and your type of business.
TIP
At present the Reports component is the only component that offers dynamic content slots
# Banner
Description: This slot appears at the very beginning of the report, just under the table of contents navigation links. It is suitable for a header, logo, or message appropriate to share with the viewer of the report.
Event name:
og-banner-slot
Payload:
{
elem: HTMLElement, // The DOM element for the slot that can be appended to
type: String // String identifying the type of report being displayed
}
# Product Title
Description: This slot appears immediately alongside the name of a product recommendation in the report. It is suitable for providing a link to learn more, an add to cart button, etc.
Event name:
og-product-title-slot
Payload:
{
product: Object, // The product recommendation API object, as documented in API reference
elem: HTMLElement // The DOM element for the slot that can be appended to
}
# Product Content
Description: This slot appears immediately underneath the name of a product recommendation in the report. It is suitable for providing any additional content or metadata about the recommended product before the body of the product recommendation.
Event name:
og-product-content-slot
Payload:
{
product: Object, // The product recommendation API object, as documented in API reference
elem: HTMLElement // The DOM element for the slot that can be appended to
}
# Examples using dynamic slots
let reportContainerElement = window.querySelector('.report-container');
/* Append a link next to the product title to a detail page to learn more about it */
reportContainerElement.addEventListener("og-product-title-slot", (e) => {
let slotElem = e.detail.elem
let product = e.detail.product.products[0]
let linkElem = slotElem.appendChild(document.createElement('a'))
linkElem.append(`Read more about ${product.productName}`)
linkElem.setAttribute('href', `https://yourdomain.com/products/detail/${product.productIdentifier}`)
});
/* Load the report content .. for each product recommendation the event listener for the product title slot will be called */
UIKit.reports(reportContainerElement, {
reports: [ /*...*/ ],
currentReportId: /*...*/
})