GithubHelp home page GithubHelp logo

masslight / ottehr Goto Github PK

View Code? Open in Web Editor NEW
118.0 15.0 127.0 3.8 MB

Modular, Production-Ready, Open-Source EHR

Home Page: https://ottehr.com

License: Other

JavaScript 0.36% HTML 0.08% TypeScript 99.11% CSS 0.07% Shell 0.39%
ehr electronic-health-record fhir health healthcare hipaa medical react telemedicine ottehr

ottehr's Introduction

Ottehr Logo.

The production-ready, open-source EHR

Ottehr.com

Last Commit Code Size Contributors GitHub Issues GitHub Stars GitHub Pull Requests GitHub Pull Requests Closed

Ottehr

This monorepo contains code for Ottehr telehealth.

Ottehr is a modern, modular EHR that began as a reference implementation for Oystehr. It quickly outgrew "sample EHR" status and became the foundation for large-scale production EHR installations. Ottehr uses Oystehr for back-end service endpoints, and requires a free Oystehr account to run as-is, but you are welcome to modify and use a third-party service vendor or build your own service architecture. Ottehr is designed for developers, hopefully making it easy to fork, white-label, and build entire new classes of EHRs and health-tech products with a fraction of the effort of starting from scratch.

Setup

Ottehr currently has two websites. One is for patients -- Ottehr Intake -- and one is for staff -- Ottehr EHR.

  • Ottehr Intake: A patient-facing registration website for creating appointments, with features including rescheduling, checking in, text messages and emails, and listing appointments for an account
  • Ottehr EHR: A staff-facing EHR for managing appointments created, with features including checking appointments, managing patient queues, texting patients, updating a location's slots, setting a location's schedule, joining telemedicine calls, HPI and medical history, exam charting, eRx and Assessment, patient plan, coming soon: RCM and claims submission

First Time Setup

To run Ottehr for the first time, you need to set up the project.

Node Installation

To manage Node.js versions efficiently, we recommend using Node Version Manager (nvm).

  1. Install nvm by following the instructions provided here.

  2. Use nvm to install Node.js version 18 with the following commands:

    nvm install 18
  3. Set Node.js version 18 as the default with:

    nvm alias default 18

After successful installation, verify the setup by executing:

node -v

This command should display the installed Node.js version.

Installing pnpm

npm install -g pnpm@9

Joining Oystehr

You'll need a free Oystehr account to run Ottehr. Register for access at oystehr.com. Follow these simple steps:

  1. Visit oystehr.com.
  2. Click on Free Access to initiate your early access request.

Once your request is received, the Oystehr team will promptly reach out to you via email, providing the credentials you need to kickstart your Oystehr journey.

For comprehensive guidance on getting started with Oystehr, explore our technical documentation available at https://docs.oystehr.com.

Setup Procedure

To proceed with this setup guide, it is assumed that you have access to a Oystehr project. If you have done so, please follow these steps:

  1. Fork Ottehr: Visit https://github.com/masslight/ottehr/fork and fork the repository.

  2. Clone Your Fork: Copy the SSH clone link of your fork and execute the following command in your preferred folder:

    git clone [email protected]:{your_profile}/ottehr.git
  3. (Optional) Add Ottehr as Upstream: If desired, add the original Ottehr repository as an upstream remote:

    git remote add upstream [email protected]:masslight/ottehr.git
  4. Open Repository in Your Editor: Open the repository in your chosen editor; for example, in VSCode:

    code .vscode/Ottehr.code-workspace

Before proceeding, ensure that you have Node.js v18.x and pnpm installed on your machine.

Once these dependencies are in place, enter the following command from the root directory.

sh scripts/ottehr-setup.sh

The script will prompt you for the following information:

  • Your access token: Log in to your Oystehr project on the Oystehr Console, and copy the access token from the dashboard
  • Your project ID: Listed on the Oystehr Console next to the access token
  • Your first provider email: This can be your email address

Once the program finishes running,

  1. The Intake and EHR websites will open.
  2. To log in to the EHR, enter the email you input during the setup program. Click Forgot password? and set a password then log in.

The URL for a test location is http://localhost:3002/location/ak/in-person/prebook.

Scripts

pnpm <script name>

If a script is environment specific, use:

pnpm <script name>:<env>

telemed:start

Starts Intake and EHR

build

Builds all packages using the build script.

lint

Lints all packages using ESLint.

update

Interactively updates all dependencies to their latest versions, respecting ranges specified in package.json.

SendGrid Email Configuration

Required Environment / Secrets

  • SENDGRID_API_KEY
  • TELEMED_SENDGRID_EMAIL_BCC
  • TELEMED_SENDGRID_EMAIL_FROM
  • TELEMED_SENDGRID_EMAIL_FROM_NAME
  • TELEMED_SENDGRID_CONFIRMATION_EMAIL_TEMPLATE_ID
  • TELEMED_SENDGRID_CANCELLATION_EMAIL_TEMPLATE_ID
  • TELEMED_SENDGRID_VIDEO_CHAT_INVITATION_EMAIL_TEMPLATE_ID

Example Confirmation Template:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <h2>You're confirmed!</h2>
    <p>Thanks for choosing Ottehr!</p><br>
    <p>Your check-in time for {{ firstName }} at {{ locationName }} is on {{ startTime }}.</p><br>
    <p>Please complete your paperwork in advance to save time at check-in. <a href="{{ paperworkUrl }}">Click here to complete paperwork</a></p><br>
    {{#notEquals appointmentType "walkin"}}
        <p><a href="{{ checkInUrl }}">Click here to modify/cancel your check-in</a></p><br>
    {{/notEquals}}
    <hr>
    <p>Thank you for choosing Ottehr. We look forward to partnering with you and your family.</p><br>
    <small>For questions or feedback, please <a target="_blank" href="https://www.ottehr.com/">Check out Ottehr</a></small>
</body>
</html>

Example Cancellation Template:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <h2>Sorry to have you go!</h2>
    <p>Your appointment for {{firstName}} at {{locationName}} on {{startTime}} has been cancelled.</p><br>
    <p><a href="{{ locationUrl }}">Click here to book again</a></p><br>
    <hr>
    <p>Thank you for choosing Ottehr. We look forward to partnering with you and your family.</p><br>
    <small>For questions or feedback, please <a target="_blank" href="https://www.ottehr.com/">Check out Ottehr</a></small>
</body>
</html>

Example Invitation Template:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <h2>You're Invited!</h2>
    <p>You have been invited to join an Ottehr visit with {{patientName}}.</p><br>
    <p><a href="{{ inviteUrl }}">Click here to join</a></p><br>
    <hr>
    <p>Thank you for choosing Ottehr. We look forward to partnering with you and your family.</p><br>
    <small>For questions or feedback, please <a target="_blank" href="https://www.ottehr.com/">Check out Ottehr</a></small>
</body>
</html>

SendGrid Email Configuration

Required Environment / Secrets

  • SENDGRID_API_KEY
  • TELEMED_SENDGRID_EMAIL_BCC
  • TELEMED_SENDGRID_EMAIL_FROM
  • TELEMED_SENDGRID_EMAIL_FROM_NAME
  • TELEMED_SENDGRID_CONFIRMATION_EMAIL_TEMPLATE_ID
  • TELEMED_SENDGRID_CANCELLATION_EMAIL_TEMPLATE_ID
  • TELEMED_SENDGRID_VIDEO_CHAT_INVITATION_EMAIL_TEMPLATE_ID

Example Confirmation Template:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <h2>You're confirmed!</h2>
    <p>Thanks for choosing Ottehr!</p><br>
    <p>Your check-in time for {{ firstName }} at {{ locationName }} is on {{ startTime }}.</p><br>
    <p>Please complete your paperwork in advance to save time at check-in. <a href="{{ paperworkUrl }}">Click here to complete paperwork</a></p><br>
    {{#notEquals appointmentType "walkin"}}
        <p><a href="{{ checkInUrl }}">Click here to modify/cancel your check-in</a></p><br>
    {{/notEquals}}
    <hr>
    <p>Thank you for choosing Ottehr. We look forward to partnering with you and your family.</p><br>
    <small>For questions or feedback, please <a target="_blank" href="https://www.ottehr.com/">Check out Ottehr</a></small>
</body>
</html>

Example Cancellation Template:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <h2>Sorry to have you go!</h2>
    <p>Your appointment for {{firstName}} at {{locationName}} on {{startTime}} has been cancelled.</p><br>
    <p><a href="{{ locationUrl }}">Click here to book again</a></p><br>
    <hr>
    <p>Thank you for choosing Ottehr. We look forward to partnering with you and your family.</p><br>
    <small>For questions or feedback, please <a target="_blank" href="https://www.ottehr.com/">Check out Ottehr</a></small>
</body>
</html>

Example Invitation Template:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <h2>You're Invited!</h2>
    <p>You have been invited to join an Ottehr visit with {{patientName}}.</p><br>
    <p><a href="{{ inviteUrl }}">Click here to join</a></p><br>
    <hr>
    <p>Thank you for choosing Ottehr. We look forward to partnering with you and your family.</p><br>
    <small>For questions or feedback, please <a target="_blank" href="https://www.ottehr.com/">Check out Ottehr</a></small>
</body>
</html>

Contribute to Ottehr

We love it when you contribute to Ottehr! By submitting to this project, you agree to adopt the Developer Certificate of Origin (DCO) for your contributions.

ottehr's People

Contributors

afgarcia86 avatar alexwillingham avatar aykhanahmadli avatar dmabram avatar fuyu avatar giladschneider avatar mtimpson avatar ncgreene avatar rzinger avatar saewitz avatar samiromarov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ottehr's Issues

Open Source Documentation

We should have:

  • License
  • README
  • Contributing guidelines
  • Code of conduct

For v0.1 we are not expecting to be ready for people to fork and contribute to the project, but for v1.0 we want to support this. We should explain this in the above documents so that people are clear on our expectations.

Contributing guidelines

CONTRIBUTING.md

We can explain

  • what contributions we're looking for
  • how to file a bug report (issue/PR templates)
  • How to set up locally and run tests
  • roadmap and project vision
  • How to get in touch with us

Code of conduct

CODE_OF_CONDUCT.md

We can just use https://www.contributor-covenant.org/

Add missing deployment details

App

#### package.json

- s3://${PREFIX}-TODO.masslight.com
- --profile TODO
- CLOUDFRONT_ID=TODO

#### readme.md

- "Todo this section is out of date"
- "...you must set up an aws profile called, TODO, with..."

env/* files

  • VITE_PROJECT_API_URL=http://localhost:todo,

src/index.tsx

  • clientId="TODO"

### Zambdas

#### README.md

- "...copy in the env files from the TODO-secrets repository..."
- Zambdas One Time Setup, Step 6 link in ", ...testing backend in secrets repo)."
- Scripts > create subscription has no description

#### scripts/package-for-release.sh

- ZIP_ORDER=('TODO', 'TODO', 'TODO')

#### src/version/index.ts

- version: 'TODO'

Update Provider Profile Information

Update the Provider Profile with the data from /profile page.

Update the following fields:

  • Title
  • First Name
  • Last Name
  • Slug
  • Practitioner.name.text (combine Title, FirstName, and LastName)

NOTE: Email: please note that it is currently not possible to change the user's email. Therefore, the email field should be disabled for editing.

Logging out doesn't redirect to the login page

I suspect this needs us to build the patient/provider wrapper/redirection in the root page

STR

  1. Login as a provider
  2. Logout

ER

  1. Redirected back to the login page

AR

  1. Redirected to the root of the app

Profile page update button doesn't work

STR

  1. Login as a provider
  2. Navigate to the profile page
  3. Fill in or update information
  4. Click the update button

ER

  1. The form is updated
  2. The page is refreshed or I'm redirected to the dashboard

AR

  1. Nothing happens

Update Repo License To Include Attribution Requirement

Copyright 2023 MassLight, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

You may not remove or reduce in prominence any attribution or reference to zapEHR or MassLight displayed in user interfaces, source code, images, or other materials covered by this license. Any user interfaces or source code derived from material covered by this license must display similar attribution. You may arrange an attribution-free commercial license by contacting [email protected].

You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits or requires.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Dev2 environment setup

For now .env/dev2.json exists, but there is more work to be done if we want this environment to be useful.

Tasks

  • Add dev2.ottehr.com to vercel
  • Create dev2 github environment and add dev2.json to github secrets
  • Update package.json and build-and-deploy scripts to support dev2 deployments

Video preview disappears when editing settings

STR

  1. Join the waiting room
  2. Open the video settings
  3. Change microphone
  4. Close settings

ER

  1. Settings modal is closed
  2. Back in the waiting room with video preview

AR

  1. Settings modal is closed
  2. Back in the waiting room without video preview
Screenshot 2023-12-01 at 14 50 06

Move all copy to translation files

This includes but is not limited to:

  • Buttons
  • Descriptions
  • Dropdown choice labels but not values (e.g. gender)
  • Image alt texts
  • Labels
  • Menu items
  • Titles

For translations of these files (e.g. to Spanish), use e.g. "footer": "TODO Powered by"

Room name (slug)

Description

The goal for this ticket is to check availability, store the slug in a way that it is linked to the provider, and then make that slug a unique URL where patient checkin can happen.

Below is a description of the slug availability endpoint, but this doesn't cover all of the functionality described above.

POST Slug Availability

Description: During provider registration, once they update the slug, we will execute this endpoint to check the availability of the chosen slug. This will also run on provider profile update.

Zambda Settings

Name: Get Slug Availability
Trigger method: http_auth
Schedule: undefined

Request

HTTP Method: POST
Endpoint URL: https://project-api.zapehr.com/v1/zambda/{zambda-id}/execute

Headers

Authorization: Bearer {auth-token}
Content-Type: application/json

Body

Old slug?: string (nathanrobinson)
Slug: string (nathanrobinson)

Response

Status: 200

Body

Available: boolean (true)

`/post-call` page patient issues

STR

  1. Join a call
  2. Leave the call

ER

  1. Redirected to the /post-call page

AR

  1. Redirected to the /post-call page, but actually shown the /waiting-room page.
  2. Can't confirm the actual structure of the page because it's never shown

Patient can't see provider video

STR

  1. Open provider slug in new tab
  2. Fill in information and join waiting room
  3. Join the call as a provider

ER

  1. Provider can see both videos
  2. Patient can see both videos

AR

  1. Provider can see both videos
Screenshot 2023-12-01 at 13 21 08 2. Patient can see own video, but not provider's Screenshot 2023-12-01 at 13 20 51

Note: this can be fixed by the provider toggling their video, but that shouldn't be the case

Write Unit Tests for Patients Queue Encounter Data Processing Logic

In get-patient-queue Zambda searches for encounters using a PractitionerID and then processes and maps these encounters into the Patient Queue format. This is a complex process, so we should write unit tests to ensure that the logic gracefully handles errors or unexpected response structures.

Relevant code:

  const encountersSearchResults: Encounter[] = await fhirClient.searchResources({
    resourceType: 'Encounter',
    searchParams: [
      {
        name: 'practitioner',
        value: `Practitioner/${providerId}`,
      },
      {
        name: 'status',
        value: 'arrived',
      },

      {
        name: 'date',
        value: `sa${startOfDay}`,
      },
    ],
  });

  const patientsQueue = encountersSearchResults.map((encounter) => {
    const patientNameExtension = encounter.extension
      ?.find((ext) => ext.url === 'https://extensions.fhir.zapehr.com/encounter-other-participants')
      ?.extension?.find((ext) => ext.url === 'https://extensions.fhir.zapehr.com/encounter-other-participant')
      ?.extension?.find((ext) => ext.url === 'reference' && ext.valueReference?.display);

    const patientName = patientNameExtension?.valueReference?.display;
    const queuedTime = encounter.period?.start;

    return {
      encounterId: encounter.id,
      patientName,
      queuedTime,
    };
  });

Patient queue zambdas

For joining and fetching the patient queue, we plan to store the start time on Encounter.period.start and visit status on Encounter.status. Patients in the waiting room will have a start time and status on-hold. If the call is answered they move to status in-progress, and status completed once they end the call. When patients are joining the waiting room the only piece of information they provide is their name, so we will store this name on Encounter.extensions[other-participants][other-participant][reference].display in the same object where we store the M2M profile that lets anonymous users join video calls.

Add UX when user updates profile

When provider hits update, there is no feedback of success/error. We need to add loading with some indicator of success/error.

Also should add loading for the slug availability check

Screenshot 2023-11-28 at 6 07 06 PM

Improve mobile responsiveness

All screenshots taken at 320x900px

Looks fine

checkin
  • checkin
checkin-permission
  • checkin-permission
post-call
  • post-call
waiting-room
  • waiting-room

Needs work

dashboard
  • dashboard
provider-profile
  • provider-profile
registration
  • registration

`/register` page to be removed

I think the endpoint assumes I'm trying to update my profile as a provider instead of create one since both pages use the same underlying component

STR

  1. Open dev env (I'm using pnpm start:dev for now)
  2. Fill in details
  3. Notice button says "update" instead of "register"
  4. Try and submit the form

ER

I register and get sent to my dashboard

AR

Screenshot 2023-11-30 at 13 18 19

Fix Slug Availability Check to Exclude Current Practitioner in Profile Update

The current implementation of the slugAvailability function incorrectly flags a slug as unavailable if it is already used by the practitioner currently updating their profile. This results in an error message: "This slug is already taken, please use another one"

The function needs to be updated to exclude the current practitioner's slug from the availability check during profile updates.

image

`/post-call` page provider issues

STR

  1. Join a call
  2. Leave the call

ER

  1. Redirected to /post-call page
  2. The logo should be the orange provider otter
  3. See call time and button to go back to dashboard

AR

  1. #87

Decouple coupled components

I'm particularly thinking of FileUpload. It was built specifically for card uploads, but if we want this to be a full EHR eventually I think we should separate the file upload aspect.

If we're actively using this component in Ottehr, we can then make a card upload component that would use the focused file upload one.

zapEHR SDK 2.0 Migration

Migrate our v1.x zapehr/sdk usages to use the v2.x version.

Update usages of fetch to use v2.x zapehr/sdk.

When one participant leaves, the other should be kicked out of the room

STR

  1. Join a call as both patient and provider
  2. Leave as either patient or provider

ER

  1. Participants should be redirected to the /post-call page

AR

  1. If the patient leaves, they are redirected to the /post-call page, but are actually shown the /waiting-room page. If the provider leaves, they are redirected to the /post-call page (see #87).
  2. The remaining participant is still in the call with a frozen other participant video.
  3. In both cases, #98

WebCam shows Green Light when not in video call

Encountered a bug where the camera light remains active when navigating backwards from the waiting room.
This issue could lead to numerous edge cases and may affect user privacy.. A systematic solution is needed to ensure consistent behavior of the camera across app.

Add tests

Start adding app and zambda tests, particularly for common/helper/shared functions

Update mobile responsiveness

STR

Set screen resolution to 320x900 (then also check when the width is set to every breakpoint in the theme provider)

ER

https://www.figma.com/file/E2CNqjutGh7di0nBEZKJ0B/ZapEHR-%26-OttEHR---app-design?node-id=13243%3A7705&mode=dev
https://www.figma.com/file/E2CNqjutGh7di0nBEZKJ0B/ZapEHR-%26-OttEHR---app-design?node-id=13246%3A20699&mode=dev

AR

Provider

Dashboard:

Screenshot 2023-12-04 at 10 58 53 Screenshot 2023-12-04 at 10 59 01

Then I have to scroll right to find the burger menu

Screenshot 2023-12-04 at 10 59 16 Screenshot 2023-12-04 at 10 59 22
Patient

Check-In

Uploading Screenshot 2023-12-04 at 11.02.57.png…

Video Settings

Screenshot 2023-12-04 at 11 03 53

Waiting Room

Screenshot 2023-12-04 at 11 04 27

Note: I couldn't check the rest of the screens since the provider's join call button doesn't work

Advice from @DariaMyro on how to design these pages for now:

anything that is a form will follow this example in terms of paddings, all fields should be in one column and buttons take full width. Patient pages will have to be designed, but if design is a blocker you can try to look into MUI guide suggestions.

404/Redirect page

Once both provider and patient flows exist, create either a catch-all 404 route or redirect users to the login page (if not authenticated) or the dashboard page.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.