working docs v3

This commit is contained in:
Alireza 2021-06-15 23:32:37 -04:00
parent 9d49bf4348
commit d501335143
100 changed files with 1064 additions and 941 deletions

View File

@ -17,8 +17,7 @@ sidebar_position: 1
> ATTENTION! You are looking at the docs for the `OHIF-v3` Viewer (third time is always a charm). If you're looking for the our `OHIF-v2` (React stable version) or OHIF-v1 (deprecated `Meteor` version) select it's version from the dropdown box in the top left corner
> of this page.
 
# Introduction
The [Open Health Imaging Foundation][ohif-org] (OHIF) Viewer is an open source,
web-based, medical imaging viewer. It can be configured to connect to Image
@ -100,13 +99,13 @@ Below, you can find the gap analysis between the `OHIF-v2` and `OHIF-v3`:
</tr>
<tr>
<td align="left">Internationalization</td>
<td align="center">🔜</td>
<td align="center">Not Started</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">Drag/drop DICOM data into the viewer (see https://viewer.ohif.org/local)</td>
<td align="center">🔜</td>
<td align="center">Not Started</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">IHE Invoke Image Display - Standard-compliant launching of the viewer (e.g. from PACS or RIS)</td>
@ -121,7 +120,7 @@ Below, you can find the gap analysis between the `OHIF-v2` and `OHIF-v3`:
<tr>
<td align="left">DICOM Whole-slide imaging viewport</td>
<td align="center">🔜</td>
<td align="center">Not Started</td>
<td align="center">In Progress</td>
</tr>
<tr>
<td align="left">Displaying non-renderable DICOM as HTML</td>
@ -140,8 +139,8 @@ Below, you can find the gap analysis between the `OHIF-v2` and `OHIF-v3`:
</tr>
<tr>
<td align="left">White-labelling: Easily replace the OHIF Logo with your logo</td>
<td align="center">🔜</td>
<td align="center">Not Started</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">DICOM upload to PACS</td>

View File

@ -1,3 +1,8 @@
---
sidebar_position: 7
sidebar_label: Architecture
---
# Architecture
@ -9,17 +14,6 @@ In order to achieve a platform that can support various workflows and be extensi
Below, we aim to demystify that complexity by providing insight into how `OHIF Platform` is
architected, and the role each of it's dependent libraries plays.
- [Architecture](#architecture)
- [Overview](#overview)
- [Extensions](#extensions)
- [Modes](#modes)
- [Platform](#platform)
- [`@ohif/viewer`](#ohifviewer)
- [`@ohif/core`](#ohifcore)
- [`@ohif/ui`](#ohifui)
- [Overview of the architecture](#overview-of-the-architecture)
- [Common Questions](#common-questions)
## Overview
@ -30,7 +24,6 @@ single project, contains many projects. If you explore our project structure,
you'll see the following:
```bash
.
├── extensions
│ ├── _example # Skeleton of example extension
@ -80,12 +73,12 @@ in `OHIF-v3` and their api is expanded. In summary:
OHIF team maintains several high value and commonly used functionalities in its
own extensions. For a list of extensions maintained by OHIF,
[check out this helpful table](../extensions/index.md#maintained-extensions).
[check out this helpful table](./extensions/index.md#maintained-extensions).
As an example `default` extension provides a default viewer layout,
a study/series browser and a datasource that maps to a DICOMWeb compliant backend.
[Click here to read more about extensions!](../extensions/index.md)
[Click here to read more about extensions!](./extensions/index.md)
@ -131,7 +124,7 @@ To summarize the difference between extensions and modes in `OHIF-v3` and extens
> - In v2 extensions are “plugins” that add functionality to a core viewer.
> - In v3 extensions are building blocks that a mode uses to build an entire viewer layout.
[Click here to read more about modes!](../modes/index.md)
[Click here to read more about modes!](./modes/index.md)
@ -169,7 +162,7 @@ These components are presentational only, so you can reuse them with whatever lo
OHIF-v3 architecture can be seen in the following figure. We will explore each
piece in more detail.
![mode-archs](../assets/img/mode-archs.png)
![mode-archs](./assets/img/mode-archs.png)
@ -206,7 +199,7 @@ your functionality in one of the modules of your new extension, and let the mod
[viewers-project]: https://github.com/OHIF/Viewers
[viewer-npm]: https://www.npmjs.com/package/@ohif/viewer
[pwa]: https://developers.google.com/web/progressive-web-apps/
[configuration]: ../configuring/index.md
[configuration]: ./configuring/index.md
[extensions]: ../extensions/index.md
[core-github]: https://github.com/OHIF/viewers/platform/core
[ui-github]: https://github.com/OHIF/Viewers/tree/master/platform/ui

View File

@ -0,0 +1,4 @@
{
"label": "Configuring",
"position": 5
}

View File

@ -1,13 +1,11 @@
## Set up a local DICOM server
---
sidebar_position: 2
sidebar_label: Data Source
---
- [Set up a local DICOM server](#set-up-a-local-dicom-server)
- [Requirements](#requirements)
- [Open Source DICOM Image Archives](#open-source-dicom-image-archives)
- [Running Orthanc](#running-orthanc)
- [Orthanc: Learn More](#orthanc-learn-more)
- [Connecting to Orthanc](#connecting-to-orthanc)
- [Configuration: Learn More](#configuration-learn-more)
- [Running DCM4CHEE](#running-dcm4chee)
# Data Source
## Set up a local DICOM server
ATTENTION! Already have a remote or local server? Skip to the
@ -176,7 +174,10 @@ DCM4chee installation is out of scope for these tutorials and can be found [here
An overview of steps for running OHIF Viewer using a local DCM4CHEE is shown below:
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/557570043?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Local dcm4chee"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/557570043?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>

View File

@ -1,14 +1,9 @@
# Configuring Data Source
---
sidebar_position: 1
sidebar_label: Overview
---
- [Configuring Data Source](#configuring-data-source)
- [Overview](#overview)
- [Configuration Files](#configuration-files)
- [Environment Variables](#environment-variables)
## Overview
# Overview
After following the steps outlined in
[Getting Started](./../development/getting-started.md), you'll notice that the
@ -31,9 +26,8 @@ and registered extension's features, are configured using this file.
The simplest way is to update the existing default config:
> _/platform/viewer/public/config/default.js_
```js
```js title="platform/viewer/public/config/default.js"
window.config = {
routerBasename: '/',
extensions: [],

View File

@ -0,0 +1,4 @@
{
"label": "Deployment",
"position": 13
}

View File

@ -1,4 +0,0 @@
<div style="text-align: center;">
<img src="/assets/img/embedded-viewer-diagram.png" alt="Embedded Viewer Diagram" style="margin: 0 auto;" />
<div><i>embedded viewer diagram</i></div>
</div>

View File

@ -1,4 +0,0 @@
<div style="text-align: center;">
<img src="/assets/img/nginx-image-archive.png" alt="request flow example" style="margin: 0 auto;" />
<div><i>simplified request flow diagram</i></div>
</div>

View File

@ -1,4 +0,0 @@
<div style="text-align: center;">
<img src="/assets/img/user-access-control-request-flow.png" alt="request flow example" style="margin: 0 auto;" />
<div><i>simplified request flow diagram</i></div>
</div>

View File

@ -1,10 +1,9 @@
---
sidebar_position: 2
---
# Build for Production
> If you've already followed the
> ["Getting Started" Guide](/development/getting-started.md), you can skip ahead
> to [Configuration](#configuration)
## Overview
### Build Machine Requirements
@ -33,7 +32,7 @@ _From .zip:_
Open your terminal, and navigate to the directory containing the source files.
Next run these commands:
```js
```bash
// If you haven't already, enable yarn workspaces
yarn config set workspaces-experimental true
@ -47,8 +46,7 @@ yarn run build
If everything worked as expected, you should have a new `dist/` directory in the
project's folder. It should roughly resemble the following:
```bash
<root>platform/viewer/dist/
```bash title="<root>platform/viewer/dist/"
├── app-config.js
├── app.bundle.js
├── app.css
@ -73,7 +71,7 @@ and registered extension's features, are configured using this file.
The easiest way to apply your own configuration is to modify the `default.js`
file. For more advanced cofiguration options, check out our
[configuration essentials guide](/configuring/index.md).
[configuration essentials guide](../configuring/index.md).
## Next Steps
@ -81,18 +79,18 @@ file. For more advanced cofiguration options, check out our
_Drag-n-drop_
- [Netlify: Drop](/deployment/recipes/static-assets.md#netlify-drop)
- [Netlify: Drop](./static-assets#netlify-drop)
_Easy_
- [Surge.sh](/deployment/recipes/static-assets.md#surgesh)
- [GitHub Pages](/deployment/recipes/static-assets.md#github-pages)
- [Surge.sh](./static-assets#surgesh)
- [GitHub Pages](./static-assets#github-pages)
_Advanced_
- [AWS S3 + Cloudfront](/deployment/recipes/static-assets.md#aws-s3--cloudfront)
- [GCP + Cloudflare](/deployment/recipes/static-assets.md#gcp--cloudflare)
- [Azure](/deployment/recipes/static-assets.md#azure)
- [AWS S3 + Cloudfront](./static-assets#aws-s3--cloudfront)
- [GCP + Cloudflare](./static-assets#gcp--cloudflare)
- [Azure](./static-assets#azure)
### Testing Build Output Locally
@ -100,7 +98,7 @@ A quick way to test your build output locally is to spin up a small webserver.
You can do this by running the following commands in the `dist/` output
directory:
```js
```bash
// Install http-server as a globally available package
yarn global add http-server
@ -111,7 +109,10 @@ yarn global add http-server
npx http-server ./dist
```
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/551957266?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="HTTP Server Deploy"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/551957266?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
### Automating Builds and Deployments

View File

@ -1,3 +1,7 @@
---
sidebar_position: 6
---
# Google Cloud Healthcare
> Coming soon - We are working on bringing Google Cloud Healthcare to OHIF-v3

View File

@ -1,3 +1,7 @@
---
sidebar_position: 1
sidebar_label: Overview
---
# Deployment
The OHIF Viewer can be embedded in other web applications via it's [packaged
@ -139,7 +143,7 @@ The returned JSON object must contain a single root object with a 'studies' arra
You can read more about using different data sources for mode's routes [here](../modes/routes.md#route-path)
*Sample JSON format:*
```JSON
```json
{
"studies": [
{

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
---
# Nginx + Image Archive
> DISCLAIMER! We make no claims or guarantees of this approach's security. If in
@ -11,7 +15,7 @@ control.
Do not use this recipe to host sensitive medical data on the open web. Depending
on your company's policies, this may be an appropriate setup on an internal
network when protected with a server's basic authentication. For a more robust
setup, check out our [user account control recipe](./user-account-control.md)
setup, check out our [user account control recipe](./user-account-control)
that builds on the lessons learned here.
## Overview
@ -58,7 +62,9 @@ CORS][understanding-cors]
This setup allows us to create a setup similar to the one pictured below:
{% include "./../_nginx-image-archive-diagram.md" %}
![nginX](../assets/img/nginx-image-archive.png)
- All web requests are routed through `nginx` on our `OpenResty` image
- `/pacs` is a reverse proxy for `orthanc`'s `DICOM Web` endpoints
@ -89,7 +95,10 @@ in command prompt or terminal_
You can see the overview of the mentioned steps:
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/554726410?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="NginX Deployment"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/554726410?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
<!-- ### Setup

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
---
# Deploy Static Assets
> WARNING! All of these solutions stand-up a publicly accessible web viewer. Do
@ -27,7 +31,7 @@ _Advanced_
- [Deploy Static Assets](#deploy-static-assets)
- [Drag-n-drop](#drag-n-drop)
- [Netlify: Drop](#netlify-drop)
- [Netlify Drop](#netlify-drop)
- [Easy](#easy)
- [Surge.sh](#surgesh)
- [GitHub Pages](#github-pages)
@ -38,9 +42,12 @@ _Advanced_
## Drag-n-drop
### Netlify: Drop
### Netlify Drop
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/551957463?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Netlify Drop"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/551957463?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
_GIF demonstrating deployment with Netlify Drop_
@ -70,7 +77,7 @@ Learn more about [Netlify on their website](https://www.netlify.com/)
> publishing. Publish HTML, CSS, and JS for free, without leaving the command
> line.
![surge.sh deploy example](../../assets/img/surge-deploy.gif)
![surge.sh deploy example](../assets/img/surge-deploy.gif)
_GIF demonstrating deployment with surge_

View File

@ -1,3 +1,7 @@
---
sidebar_position: 5
---
# User Account Control
> Coming soon - We are working on bringing the User Account Control to OHIF-v3

View File

@ -0,0 +1,4 @@
{
"label": "Development",
"position": 4
}

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
sidebar_label: Continous Integration
---
# Continous Integration (CI)
This repository uses `CircleCI` and `Netlify` for continous integration.
@ -25,12 +29,8 @@ The PR_CHECKS workflow (Pull Request Checks) runs our automated unit and
end-to-end tests for every code check-in. These tests must all pass before code
can be merged to our `master` branch.
<div style="text-align: center;">
<a href="/assets/img/WORKFLOW_PR_CHECKS.png">
<img src="/assets/img/WORKFLOW_PR_CHECKS.png" alt="workflow diagram" style="margin: 0 auto; max-width: 500px;" />
</a>
<div><i>Workflow diagram for PR_CHECKS</i></div>
</div>
![PR_CHECKS](../assets/img/WORKFLOW_PR_CHECKS.png)
### Workflow: PR_OPTIONAL_DOCKER_PUBLISH
@ -38,12 +38,9 @@ The PR_OPTIONAL_DOCKER_PUBLISH workflow allows for "manual approval" to publish
the pull request as a tagged docker image. This is helpful when changes need to
be tested with the Google Adapter before merging to `master`.
<div style="text-align: center;">
<a href="/assets/img/WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png">
<img src="/assets/img/WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png" alt="workflow diagram" style="margin: 0 auto; max-width: 500px;" />
</a>
<div><i>Workflow diagram for PR_WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH</i></div>
</div>
![PR_Workflow](../assets/img/WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png)
> NOTE: This workflow will fail unless it's for a branch on our `upstream`
> repository. If you need this functionality, but the branch is from a fork,
@ -56,12 +53,9 @@ It uses the Netlify CLI to deploy assets created as part of the repository's PWA
Build process (`yarn run build`). The workflow allows for "Manual Approval" to
promote the build to `STAGING` and `PRODUCTION` environments.
<div style="text-align: center;">
<a href="/assets/img/WORKFLOW_DEPLOY.png">
<img src="/assets/img/WORKFLOW_DEPLOY.png" alt="workflow diagram" style="margin: 0 auto; max-width: 500px;" />
</a>
<div><i>Workflow diagram for WORKFLOW_DEPLOY</i></div>
</div>
![WORKFLOW_DEPLOY](../assets/img/WORKFLOW_DEPLOY.png)
| Environment | Description | URL |
| ----------- | ---------------------------------------------------------------------------------- | --------------------------------------------- |
@ -82,16 +76,11 @@ GitHub hosts the `gh-pages` branch with GitHub Pages.
- Extension Packages: https://github.com/ohif/viewers/#extensions
- Documentation: https://docs.ohif.org/
<div style="text-align: center;">
<a href="/assets/img/WORKFLOW_RELEASE.png">
<img src="/assets/img/WORKFLOW_RELEASE.png" alt="workflow diagram" style="margin: 0 auto; max-width: 500px;" />
</a>
<div><i>Workflow diagram for WORKFLOW_RELEASE</i></div>
</div>
### HOTFIX
_Not yet implemented_
![WORKFLOW_RELEASE](../assets/img/WORKFLOW_RELEASE.png)
<!--
LINKS

View File

@ -1,3 +1,7 @@
---
sidebar_position: 2
sidebar_label: Contributing
---
# Contributing
## How can I help?
@ -34,9 +38,7 @@ dependencies:
On your local file system:
```bash
# code/my-projects/
.
```bash title="/my-projects/"
├── cornerstonejs/cornerstone-tools
└── ohif/viewers
```
@ -57,12 +59,11 @@ On your local file system:
As you make changed to `cornerstone-tools`, and it's output is rebuilt, you
should see the following behavior:
<div style="text-align: center;">
<a href="/assets/img/cornerstone-tools-link.gif">
<img src="/assets/img/cornerstone-tools-link.gif" alt="Example of linked cornerstone-tools package" style="margin: 0 auto; max-width: 500px;" />
</a>
<div><i>example of linked cornerstone-tools package</i></div>
</div>
![tools](..//assets/img/cornerstone-tools-link.gif)
If you wish to stop using your local package, run the following commands in the
`ohif/viewers` repository root:

View File

@ -1,3 +1,7 @@
---
sidebar_position: 1
sidebar_label: Getting Started
---
# Getting Started
## Setup
@ -70,7 +74,11 @@ You should see the following output:
### 🎉 Celebrate 🎉
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545988245?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="getting-started"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/545988245?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
### Building for Production

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
sidebar_label: Testing
---
# Running Tests for OHIF
We introduce here various test types that is available
@ -7,7 +11,7 @@ part of this page.
## Unit test
To run the unit test:
```
```bash
yarn run test:unit:ci
```
@ -23,7 +27,7 @@ For running the OHIF e2e test you need to run the following steps:
- Create a mini-pacs for OHIF to access the images for testing. We download
and run our lightweight implementation which provides a collection of DICOM studies ([source code][mini-pacs]).
```
```bash
docker run -p 5985:5985 -p 5984:5984 -e USE_POUCHDB=true -e DB_SERVER=http://0.0.0.0 ohif/viewer-testdata:0.1-test
```
@ -33,7 +37,7 @@ and run our lightweight implementation which provides a collection of DICOM stud
- Open a new terminal, navigate to the OHIF project, and run OHIF with the dicom-server config
```
```bash
APP_CONFIG=config/dicomweb-server.js yarn start
```
@ -43,7 +47,7 @@ and run our lightweight implementation which provides a collection of DICOM stud
- Open a new terminal inside the OIHF project, and run the e2e cypress test
```
```bash
yarn run test:e2e
```
@ -63,7 +67,7 @@ and run our lightweight implementation which provides a collection of DICOM stud
# Testing Philosiphy
## Testing Philosiphy
> Testing is an opinionated topic. Here is a rough overview of our testing
> philosophy. See something you want to discuss or think should be changed? Open

View File

@ -0,0 +1,4 @@
{
"label": "Extensions",
"position": 9
}

View File

@ -1,94 +0,0 @@
<table>
<thead>
<tr>
<th align="left" width="30%">
Types
</th>
<th align="left">Description</th>
<th align="left">Examples</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">
<a href="./modules/layout-template.md">
LayoutTemplate (NEW)
</a>
</td>
<td align="left">Control Layout of a route</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/data-source.md">
DataSource (NEW)
</a>
</td>
<td align="left">Control the mapping from DICOM metadata to OHIF-metadata</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/sop-class-handler.md">
SOPClassHandler
</a>
</td>
<td align="left">Determines how retrieved study data is split into "DisplaySets"</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/panel.md">
Panel
</a>
</td>
<td align="left">Adds left or right hand side panels</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/viewport.md">
Viewport
</a>
</td>
<td align="left">Adds a component responsible for rendering a "DisplaySet"</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/commands.md">
Commands
</a>
</td>
<td align="left">Adds named commands, scoped to a context, to the CommandsManager</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/toolbar.md">
Toolbar
</a>
</td>
<td align="left">Adds buttons or custom components to the toolbar</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/context.md">
Context
</a>
</td>
<td align="left">Shared state for a workflow or set of extension module definitions</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">
<a href="./modules/hpModule.md">
HangingProtocol
</a>
</td>
<td align="left">Adds hanging protocol rules</td>
<td align="left"></td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,55 @@
---
sidebar_position: 4
sidebar_label: Extension Manager
---
# Extension Manager
## Overview
The `ExtensionManager` is a class made available to us via the `@ohif/core`
project (platform/core). Our application instantiates a single instance of it,
and provides a `ServicesManager` and `CommandsManager` along with the
application's configuration through the appConfig key (optional).
```js
const commandsManager = new CommandsManager();
const servicesManager = new ServicesManager();
const extensionManager = new ExtensionManager({
commandsManager,
servicesManager,
appConfig,
});
```
The `ExtensionManager` only has a few public members:
- `setActiveDataSource` - Sets the active data source for the application
- `getDataSources` - Returns the registered data sources
- `getActiveDataSource` - Returns the currently active data source
- `getModuleEntry` - Returns the module entry by the give id.
## Accessing Modules
We use `getModuleEntry` in our `ViewerLayout` logic to find the panels based on the
provided IDs in the mode's configuration.
For instance: `extensionManager.getModuleEntry("org.ohif.measurement-tracking.panelModule.seriesList")`
accesses the `seriesList` panel from `panelModule` of the `org.ohif.measurement-tracking` extension.
```js
const getPanelData = id => {
const entry = extensionManager.getModuleEntry(id);
const content = entry.component;
return {
iconName: entry.iconName,
iconLabel: entry.iconLabel,
label: entry.label,
name: entry.name,
content,
};
};
```

View File

@ -1,7 +1,9 @@
# Extensions
---
sidebar_position: 1
sidebar_label: Introduction
---
## Overview
# Introduction
We have re-designed the architecture of the `OHIF-v3` to enable building applications
that are easily extensible to various use cases (modes) that behind the scene would utilize desired functionalities (extensions) to reach the goal of the use case.
@ -70,7 +72,8 @@ A small number of powerful extensions for popular use cases are maintained by
OHIF. They're co-located in the [`OHIF/Viewers`][viewers-repo] repository, in
the top level [`extensions/`][ext-source] directory.
<!-- <table>
<table>
<thead>
<tr>
<th>Extension</th>
@ -102,6 +105,7 @@ the top level [`extensions/`][ext-source] directory.
</td>
<td>ViewportModule, CommandsModule</td>
</tr>
<tr>
<td>
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-pdf">DICOM PDF</a>
</td>
@ -129,8 +133,7 @@ the top level [`extensions/`][ext-source] directory.
<td> ContextModule,PanelModule,ViewportModule,CommandsModule</td>
</tr>
</tbody>
</table> -->
</table>
## Registering an Extension
@ -158,7 +161,6 @@ import MySecondExtension from '@ohif/extension-second'
const extensionConfig = {/* extension configuration */}
// prettier-ignore
const config = {
routerBasename: '/',
extensions: [
@ -193,9 +195,9 @@ You can update the list of bundled extensions by:
1. Having your `@ohif/viewer` project depend on the extension
2. Importing and adding it to the list of extensions in the
`<repo-root>/platform/src/index.js` entrypoint:
entrypoint:
```js
```js title="<repo-root>/platform/src/index.js"
import OHIFDefaultExtension from '@ohif/extension-default';
import OHIFCornerstoneExtension from '@ohif/extension-cornerstone';
import OHIFMeasurementTrackingExtension from '@ohif/extension-measurement-tracking';
@ -242,10 +244,94 @@ Each module type has a special purpose, and is consumed by our viewer
differently.
{% include "./_modules.md" %}
<table>
<thead>
<tr>
<th align="left" width="30%">
Types
</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">
<a href="./modules/layout-template.md">
LayoutTemplate (NEW)
</a>
</td>
<td align="left">Control Layout of a route</td>
</tr>
<tr>
<td align="left">
<a href="./modules/data-source.md">
DataSource (NEW)
</a>
</td>
<td align="left">Control the mapping from DICOM metadata to OHIF-metadata</td>
</tr>
<tr>
<td align="left">
<a href="./modules/sop-class-handler.md">
SOPClassHandler
</a>
</td>
<td align="left">Determines how retrieved study data is split into "DisplaySets"</td>
</tr>
<tr>
<td align="left">
<a href="./modules/panel.md">
Panel
</a>
</td>
<td align="left">Adds left or right hand side panels</td>
</tr>
<tr>
<td align="left">
<a href="./modules/viewport.md">
Viewport
</a>
</td>
<td align="left">Adds a component responsible for rendering a "DisplaySet"</td>
</tr>
<tr>
<td align="left">
<a href="./modules/commands.md">
Commands
</a>
</td>
<td align="left">Adds named commands, scoped to a context, to the CommandsManager</td>
</tr>
<tr>
<td align="left">
<a href="./modules/toolbar.md">
Toolbar
</a>
</td>
<td align="left">Adds buttons or custom components to the toolbar</td>
</tr>
<tr>
<td align="left">
<a href="./modules/context.md">
Context
</a>
</td>
<td align="left">Shared state for a workflow or set of extension module definitions</td>
</tr>
<tr>
<td align="left">
<a href="./modules/hpModule.md">
HangingProtocol
</a>
</td>
<td align="left">Adds hanging protocol rules</td>
</tr>
</tbody>
</table>
<figure style="text-align: center; font-style: italic;">Tbl. Module types with abridged descriptions and examples. Each module links to a dedicated documentation page.</figure>
<span style={{"textAlign": 'center', 'fontStyle': 'italic'}}>Tbl. Module types with abridged descriptions and examples. Each module links to a dedicated documentation page.</span>

View File

@ -0,0 +1,4 @@
{
"label": "LifeCycle",
"position": 1
}

View File

@ -1,3 +1,7 @@
---
sidebar_position: 2
sidebar_label: Mode Enter
---
# Lifecycle Hook: onModeEnter
If an extension defines the `onModeEnter` lifecycle hook, it is called

View File

@ -1,4 +1,8 @@
# Lifecylce Hook: onModeExit
---
sidebar_position: 3
sidebar_label: Mode Exit
---
# Lifecycle Hook: onModeExit
If an extension defines the `onModeExit` lifecycle hook, it is called when navigating
away from a mode. This hook can be used to clean up data tasks such as unregistering services,

View File

@ -1,3 +1,7 @@
---
sidebar_position: 1
sidebar_label: Pre Registration
---
# Lifecylce Hook: preRegistration
If an extension defines the `preRegistration` lifecycle hook, it is called
@ -18,7 +22,6 @@ available in the app. We will talk more in details for creating a new service fo
`OHIF-v3`.
```js
// new service inside new extension
import MyNewService from './MyNewService';

View File

@ -0,0 +1,4 @@
{
"label": "Modules",
"position": 3
}

View File

@ -1,14 +1,10 @@
---
sidebar_position: 2
sidebar_label: Commands
---
# Module: Commands
- [Module: Commands](#module-commands)
- [Overview](#overview)
- [Command Definitions](#command-definitions)
- [Command Behavior](#command-behavior)
- [`CommandsManager` Public API](#commandsmanager-public-api)
- [Contexts](#contexts)
## Overview
`CommandsModule` includes list of arbitrary functions. These may activate tools, communicate with a server, open a modal, etc.
The significant difference between `OHIF-v3` and `OHIF-v2` is that in `v3` a `mode` defines

View File

@ -1,9 +1,9 @@
---
sidebar_position: 9
sidebar_label: Context
---
# Module: Context
- [Module: Context](#module-context)
- [Overview](#overview)
## Overview
This new module type allows you to connect components via a shared context. You can create a context that two components, e.g. a viewport and a panel can use to synchronize and communicate. An extensive example of this can be seen in the longitudinal modes custom extensions.

View File

@ -1,7 +1,10 @@
---
sidebar_position: 3
sidebar_label: Data Source
---
# Module: Data Source
## Overview
The internal data structure of OHIFs metadata follows naturalized DICOM JSON, A format pioneered by `dcmjs`. In short DICOM metadata headers with DICOM Keywords instead of tags and sequences as arrays, for easy development and clear code.
@ -57,9 +60,7 @@ You need to make sure, you implement the following functions for the data source
```js
// platform/core/src/DataSources/IWebApiDataSource.js
```js title="platform/core/src/DataSources/IWebApiDataSource.js"
function create({
query,
retrieve,

View File

@ -1,10 +1,16 @@
Module: Hanging Protocol
---
sidebar_position: 8
sidebar_label: Hanging Protocol
---
# Module: Hanging Protocol
## Overview
`hangingProtocolModule` provides the protocols for hanging the displaySets in the viewer.
This module can be as simple as loading a list of pre-defined protocols, or it can be more complex
and `fetch` the protocols from a server.
You can read more about hanging protocols in HangingProtocolService.
```js
const deafultProtocol = {
id: 'defaultProtocol',

View File

@ -1,10 +1,9 @@
---
sidebar_position: 7
sidebar_label: Layout Template
---
# Module: Layout Template
- [Module: Layout Template](#module-layout-template)
- [Overview](#overview)
- [Overview Video](#overview-video)
## Overview
`LayoutTemplates` are a new concept in v3 that modes use to control the layout of a route.
A layout template is a React component that is given a set of managers that define apis to access toolbar state, commands, and hotkeys, as well as props defined by the layout template.
@ -34,8 +33,7 @@ LayoutTemplate leverages extensionManager to grab typed extension module entries
A simplified code for `Default extention`'s layout template is:
```jsx
// extensions/default/src/ViewerLayout/index.jsx
```jsx title="extensions/default/src/ViewerLayout/index.jsx"
import React from 'react'
import { SidePanel } from '@ohif/ui'
@ -133,4 +131,6 @@ function ViewerLayout({
## Overview Video
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545993263?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Viewer-layout"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/545993263?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>

View File

@ -1,7 +1,11 @@
---
sidebar_position: 6
sidebar_label: Panel
---
# Module: Panel
## Overview
UI that is intended to be displayed within a panel. The default LayoutTemplate has panels on the left and right sides, however one could make a template with panels at the top or bottom and make extensions with panels intended for such slots.
The default LayoutTemplate has panels on the left and right sides, however one could make a template with panels at the top or bottom and make extensions with panels intended for such slots.
An extension can register a Panel Module by defining a `getPanelModule` method.
@ -10,18 +14,19 @@ that can be used by the consuming application. `components` are React Components
that can be displayed in the consuming application's "Panel" Component.
<!-- <center><i>A panel extension example</i></center> -->
The `menuOptions`'s `target` key points to a registered `components`'s `id`. A
![panel-module-v3](../../assets/img/panel-module-v3.png)
The `menuOptions`'s `target` key, points to a registered `components`'s `id`. A
`defaultContext` is applied to all `menuOption`s; however, each `menuOption` can
optional provide it's own `context` value.
optionally provide it's own `context` value.
The `getPanelModule` receives an object containing the `ExtensionManager`'s
associated `ServicesManager` and `CommandsManager`.
![panel-module-v3](../../assets/img/panel-module-v3.png)
```js
```jsx
import PanelMeasurementTable from './PanelMeasurementTable.js';
@ -96,6 +101,4 @@ export default function mode({ modeConfiguration }) {
],
};
}
```

View File

@ -1,6 +1,9 @@
---
sidebar_position: 4
sidebar_label: SOP Class Handler
---
# Module: SOP Class Handler
## Overview
This module defines how a specific DICOM SOP class should be processed to make a displaySet, something that can be hung in a viewport. An extension can register a [SOP Class][sop-class-link] Handler Module by defining a `getSopClassHandlerModule` method. The [SOP Class][sop-class-link].

View File

@ -1,17 +1,12 @@
---
sidebar_position: 1
sidebar_label: Toolbar
---
# Module: Toolbar
An extension can register a Toolbar Module by defining a `getToolbarModule`
method. `OHIF-v3`'s `default` extension (`"ohif.org.default"`) provides 5 main toolbar button types:
- [Module: Toolbar](#module-toolbar)
- [Example Toolbar Module](#example-toolbar-module)
- [Toolbar buttons consumed in modes](#toolbar-buttons-consumed-in-modes)
- [Button Definitions](#button-definitions)
- [Nested Buttons](#nested-buttons)
- [Layout Template](#layout-template)
- [Custom Button](#custom-button)
- [Custom tool](#custom-tool)
![toolbarModule](../../assets/img/toolbarModule.png)
@ -150,9 +145,7 @@ You can see below how `longitudinal` mode is using the available toolbarModule t
![toolbarModule-nested-buttons](../../assets/img/toolbarModule-nested-buttons.png)
```js
// modes/longitudinal/src/toolbarButtons.js
```js title="modes/longitudinal/src/toolbarButtons.js"
{
id: 'MeasurementTools',
type: 'ohif.splitButton',
@ -210,7 +203,13 @@ You can see below how `longitudinal` mode is using the available toolbarModule t
}
```
<div style="padding:62.5% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/547957214?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Toolbar"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/547957214?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
## Layout Template
Layout selector button and logic is also provided by the OHIF-v3 `default` extension.
@ -224,8 +223,9 @@ To use it, you can just add the following definition to the list of `toolDefinit
}
```
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545993263?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Viewer-layout"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/545993263?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
## Custom Button
You can also create your own extension, and add your new custom tool appearance (e.g., split horizantlly instead of vertically for split tool).

View File

@ -1,6 +1,9 @@
---
sidebar_position: 5
sidebar_label: Viewport
---
# Module: Viewport
## Overview
Viewports consume a displaySet and display/allow the user to interact with data. An extension can register a Viewport Module by defining a `getViewportModule`
method that returns a React component. Currently, we use viewport components to
@ -18,7 +21,7 @@ add support for:
The general pattern is that a mode can define which `Viewport` to use for which specific
`SOPClassHandlerUID`, so if you want to fork just a single Viewport component for a specialized mode, this is possible.
```JSX
```jsx
// displaySet, viewportIndex, dataSource
const getViewportModule = () => {
const wrappedViewport = props => {
@ -44,7 +47,7 @@ a cornerstone viewport and and action bar on top of it.
```JSX
```jsx
function TrackedCornerstoneViewport({
children,
dataSource,

View File

@ -0,0 +1,4 @@
{
"label": "FAQ",
"position": 14
}

View File

@ -1,3 +1,6 @@
---
sidebar_position: 2
---
# Browser Support
The browsers that we support are specified in the `.browserlistrc` file located

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
---
# Frequently Asked Questions
## Index

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
---
# PWA vs Packaged
It's important to know that the OHIF Viewer project provides two different build
@ -26,7 +30,7 @@ that subsequent requests are from the local file system instead of over the
network.
You can read more about this particular strategy in our
[Build for Production Deployment Guide](./../deployment/recipes/build-for-production.md)
[Build for Production Deployment Guide](./../deployment/build-for-production.md)
## Commonjs Bundle (Packaged Script)

View File

@ -1,3 +1,6 @@
---
sidebar_position: 1
---
# Scope of Project
The OHIF Viewer is a web based medical imaging viewer. This allows it to be used

View File

@ -1,3 +1,6 @@
---
sidebar_position: 15
---
# Help
We all need a little help sometimes. Don't let a few roadblocks stand in the way

View File

@ -0,0 +1,4 @@
{
"label": "Managers",
"position": 11
}

View File

@ -1,50 +0,0 @@
<table>
<thead>
<tr>
<th>Manager</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="./extension.md">
Extension Manager
</a>
</td>
<td>
Aggregating and exposing modules and features through out the app
</td>
</tr>
<tr>
<td>
<a href="./service.md">
Services Manager
</a>
</td>
<td>
Single point of registration for all internal and external services
</td>
</tr>
<tr>
<td>
<a href="./commands.md">
Commands Manager
</a>
</td>
<td>
Register commands with specific context and run commands in the app
</td>
</tr>
<tr>
<td>
<a href="./hotkeys.md">
Hotkeys Manager
</a>
</td>
<td>
For keyboard keys assignment to commands
</td>
</tr>
</tbody>
</table>

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
sidebar_label: Commands Manager
---
# Commands Manager
## Overview
@ -70,9 +74,7 @@ These methods are used internally to help determine which commands are currently
valid, and how to provide them with any state they may need at the time they are
called.
```js
// platform/viewer/src/appInit.js
```js title="platform/viewer/src/appInit.js"
const commandsManagerConfig = {
getAppState: () => {},
/** Used by commands to determine active context */
@ -167,7 +169,6 @@ use `runCommand(commandName, options = {}, contextName)`.
```js
// Run a command, it will run all the `speak` commands in all contexts
commandsManager.runCommand('speak', { command: 'hello' });

View File

@ -1,3 +1,7 @@
---
sidebar_position: 2
sidebar_label: Extension Manager
---
# Extension Manager
## Overview

View File

@ -1,3 +1,7 @@
---
sidebar_position: 5
sidebar_label: Hotkeys Manager
---
# Hotkeys Managers
## Overview

View File

@ -1,3 +1,7 @@
---
sidebar_position: 1
sidebar_label: Introduction
---
# Managers
## Overview
@ -7,7 +11,56 @@
`OHIF-v3` provides the following managers which we will discuss in depth.
{% include "./_managers.md" %}
<table>
<thead>
<tr>
<th>Manager</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="./extension.md">
Extension Manager
</a>
</td>
<td>
Aggregating and exposing modules and features through out the app
</td>
</tr>
<tr>
<td>
<a href="./service.md">
Services Manager
</a>
</td>
<td>
Single point of registration for all internal and external services
</td>
</tr>
<tr>
<td>
<a href="./commands.md">
Commands Manager
</a>
</td>
<td>
Register commands with specific context and run commands in the app
</td>
</tr>
<tr>
<td>
<a href="./hotkeys.md">
Hotkeys Manager
</a>
</td>
<td>
For keyboard keys assignment to commands
</td>
</tr>
</tbody>
</table>

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
sidebar_label: Service Manager
---
# Services Manager
## Overview
@ -39,9 +43,7 @@ export default class ServicesManager {
## Default Registered Services
By default, `OHIF-v3` registers the following services in the `appInit`.
```js
// platform/viewer/src/appInit.js
```js title="platform/viewer/src/appInit.js"
servicesManager.registerServices([
UINotificationService,
UIModalService,
@ -64,9 +66,7 @@ find out that services need to be exported as an object with `name` and `create`
For instance, `ToolbarService` is exported as:
```js
// platform/core/src/services/ToolBarService/index.js
```js title="platform/core/src/services/ToolBarService/index.js"
import ToolBarService from './ToolBarService';
export default {
@ -112,9 +112,7 @@ function PanelMeasurementTableTracking({ servicesManager }) {
## Registering Custom Services
You might need to write you own custom service in an extension. `preRegistration` hook inside your extension is the place for registering your custom service.
```js
// extensions/customExtension/src/index.js
```js title="extensions/customExtension/src/index.js"
import WrappedBackEndService from './services/backEndService'
export default {
@ -129,8 +127,7 @@ export default {
and the logic for your service shall be
```js
// extensions/customExtension/src/services/backEndService/index.js
```js title="extensions/customExtension/src/services/backEndService/index.js"
import backEndService from './backEndService';
export default function WrappedBackEndService(serviceManager) {

View File

@ -1,95 +0,0 @@
<table>
<thead>
<tr>
<th align="left">Property</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">
id
</td>
<td align="left">unique mode id used to refer to the mode</td>
</tr>
<tr>
<td align="left">
displayName
</td>
<td align="left">actual name of the mode being displayed for each study in the study summary panel</td>
</tr>
<tr>
<td align="left">
<a href="./lifeCycle.md#onModeEnter">
onModeEnter
</a>
</td>
<td align="left">hook is called when the mode is entered by the specified route</td>
</tr>
<tr>
<td align="left">
<a href="./lifeCycle.md#onModeExit">
onModeExit
</a>
</td>
<td align="left">hook is called when the mode exited</td>
</tr>
<tr>
<td align="left">
<a href="">
validationTags
</a>
</td>
<td align="left">validationTags</td>
</tr>
<tr>
<td align="left">
<a href="">
isValidMode
</a>
</td>
<td align="left">Checks if the mode is valid for a study</td>
</tr>
<tr>
<td align="left">
<a href="">
routes
</a>
</td>
<td align="left">route config which defines the route address, and the layout for it</td>
</tr>
<tr>
<td align="left">
<a href="./index.md#consuming-extensions">
extensions
</a>
</td>
<td align="left">extensions needed by the mode</td>
</tr>
<tr>
<td align="left">
<a href="">
hanging protocol
</a>
</td>
<td align="left">list of hanging protocols that the mode should have access to</td>
</tr>
<tr>
<td align="left">
<a href="">
sopClassHandlers
</a>
</td>
<td align="left">list of SOPClass modules needed by the mode </td>
</tr>
<tr>
<td align="left">
<a href="">
hotkeys
</a>
</td>
<td align="left">hotkeys</td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,4 @@
{
"label": "Modes",
"position": 10
}

View File

@ -1,15 +1,9 @@
---
sidebar_position: 1
sidebar_label: Introduction
---
# Modes
- [Modes](#modes)
- [Overview](#overview)
- [Anatomy](#anatomy)
- [Consuming Extensions](#consuming-extensions)
- [routes](#routes)
- [extensions](#extensions)
- [hangingProtocols](#hangingprotocols)
- [sopClassHandlers](#sopclasshandlers)
- [hotkeys](#hotkeys)
- [Registration](#registration)
## Overview
A mode can be thought of as a viewer app configured to perform a specific task,
@ -55,9 +49,7 @@ Mode's config is actually a function that return a config object with certain pr
```js
// modes/example/src/index.js
```js title="modes/example/src/index.js"
export default function mode() {
return {
id: '',
@ -81,7 +73,101 @@ export default function mode() {
}
```
{% include "./_anatomy.md" %}
<table>
<thead>
<tr>
<th align="left">Property</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">
id
</td>
<td align="left">unique mode id used to refer to the mode</td>
</tr>
<tr>
<td align="left">
displayName
</td>
<td align="left">actual name of the mode being displayed for each study in the study summary panel</td>
</tr>
<tr>
<td align="left">
<a href="./lifeCycle.md#onModeEnter">
onModeEnter
</a>
</td>
<td align="left">hook is called when the mode is entered by the specified route</td>
</tr>
<tr>
<td align="left">
<a href="./lifeCycle.md#onModeExit">
onModeExit
</a>
</td>
<td align="left">hook is called when the mode exited</td>
</tr>
<tr>
<td align="left">
<a href="">
validationTags
</a>
</td>
<td align="left">validationTags</td>
</tr>
<tr>
<td align="left">
<a href="">
isValidMode
</a>
</td>
<td align="left">Checks if the mode is valid for a study</td>
</tr>
<tr>
<td align="left">
<a href="">
routes
</a>
</td>
<td align="left">route config which defines the route address, and the layout for it</td>
</tr>
<tr>
<td align="left">
<a href="./index.md#consuming-extensions">
extensions
</a>
</td>
<td align="left">extensions needed by the mode</td>
</tr>
<tr>
<td align="left">
<a href="">
hanging protocol
</a>
</td>
<td align="left">list of hanging protocols that the mode should have access to</td>
</tr>
<tr>
<td align="left">
<a href="">
sopClassHandlers
</a>
</td>
<td align="left">list of SOPClass modules needed by the mode </td>
</tr>
<tr>
<td align="left">
<a href="">
hotkeys
</a>
</td>
<td align="left">hotkeys</td>
</tr>
</tbody>
</table>
@ -96,9 +182,7 @@ For instance, if a mode requires the left panel with name of `AIPanel` that is a
In the background `OHIF` will handle grabbing the correct panel via `ExtensionManager`.
```js
// extensions/myAIExtension/getPanelModule.js
```js title="extensions/myAIExtension/getPanelModule.js"
import PanelAI from './PanelAI.js';
@ -127,7 +211,6 @@ function getPanelModule({
},
];
}
```
@ -194,15 +277,13 @@ export default function mode({ modeConfiguration }) {
}
```
### routes
### Routes
routes config is an array of route settings, and the overall look and behavior of the viewer at the designated route is defined by the `layoutTemplate` and `init` functions for the route. We will learn more about each of the above properties inside the [route documentation](./routes.md)
### extensions
### Extensions
Currently `extensions` property in the mode config is used to add *contextModule* of the mentioned extensions to the list of contexts and provide them through out the app. Since extensions are registered by the ExtensionManager, modes have access to the them even if they have not been referred in the mode config file inside *extensions* property. [Read more about extension registration](../extensions/index.md#registering-an-extension)
```js
// platform/viewer/src/routes/Mode/Mode.jsx
```js title="platform/viewer/src/routes/Mode/Mode.jsx"
const { extensions } = mode;
extensions.forEach(extensionId => {
@ -216,13 +297,11 @@ extensions.forEach(extensionId => {
});
```
### hangingProtocols
### HangingProtocols
Currently, you can pass your defined hanging protocols inside the `hangingProtocols` property of
the mode's config. This will get used inside the `Mode.jsx` to configure the `HangingProtocolService`.
```js
// platform/viewer/src/routes/Mode/Mode.jsx
```js title="platform/viewer/src/routes/Mode/Mode.jsx"
const { hangingProtocols } = mode;
hangingProtocols.forEach(extentionProtocols => {
@ -231,20 +310,18 @@ hangingProtocols.forEach(extentionProtocols => {
});
```
### sopClassHandlers
### SopClassHandlers
Mode's configuration also accepts the `sopClassHandler` modules that have been added by the extensions.
This information will get used inside the `Mode.jsx` to initialize the `DisplaySetService` with the provided
SOPClass modules which handles creation of the displaySets.
```js
// platform/viewer/src/routes/Mode/Mode.jsx
```js title="platform/viewer/src/routes/Mode/Mode.jsx"
const { sopClassHandlers } = mode;
DisplaySetService.init(extensionManager, sopClassHandlers);
```
### hotkeys
### Hotkeys
`hotkeys` is another property in the configuration of a mode that can be defined to add the specific hotkeys to the viewer at all routes.
```js
@ -281,9 +358,7 @@ export default function mode() {
```
```js
// platform/viewer/src/routes/Mode/Mode.jsx
```js title="platform/viewer/src/routes/Mode/Mode.jsx"
hotkeysManager.setDefaultHotKeys(hotkeys);
hotkeysManager.setHotkeys(hotkeys);
```
@ -299,9 +374,7 @@ hotkeysManager.setHotkeys(hotkeys);
Upon release modes will also be plugged into the app via configuration, but this is still an area which is under development/discussion, and they are currently pulled from the `window` in beta.
```js
// modes/longitudinal/src/index.js
```js title="modes/longitudinal/src/index.js"
export default function mode() {
return {
id: 'viewer',
@ -325,14 +398,11 @@ export default function mode() {
}
window.longitudinalMode = mode({});
```
and inside `@ohif/viwer` we have:
```js
// platform/viewer/src/appInit.js
```js title="platform/viewer/src/appInit.js"
if (!appConfig.modes.length) {
appConfig.modes.push(window.longitudinalMode);
// appConfig.modes.push(window.segmentationMode);

View File

@ -1,11 +1,10 @@
---
sidebar_position: 2
sidebar_label: Life Cycle
---
# Mode: LifeCycle
- [Mode: LifeCycle](#mode-lifecycle)
- [Overview](#overview)
- [onModeEnter](#onmodeenter)
- [onModeExit](#onmodeexit)
## Overview
Currently there are two hooks that are called for modes.

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
sidebar_label: Routes
---
# Mode: Routes
## Overview

View File

@ -1,8 +1,9 @@
---
sidebar_position: 4
sidebar_label: Validity
---
# Mode: Validity
- [Mode: Validity](#mode-validity)
- [Overview](#overview)
- [isValidMode](#isvalidmode)
## Overview
There are two mechanism for checking the validity of a mode for a study.

View File

@ -1,3 +1,6 @@
---
sidebar_position: 2
---
# Our Process
Our process is a living, breathing thing. We strive to have regular
@ -8,14 +11,6 @@ that process in an effort to:
- Strengthen community member involvement and understanding
- Welcome feedback and helpful suggestions
## Overview
- [Issue Triage](#issue-triage)
- [Issue Curation ("backlog grooming")](#issue-curation-backlog-grooming)
- [Contributions (Pull Requests)](#contributions-pull-requests)
- [Releases](#releases)
## Issue Triage
[GitHub issues][gh-issues] are the best way to provide feedback, ask questions,

View File

@ -1,28 +0,0 @@
# Quick Start
This page details how to get an instance of the OHIF Viewer up and running as
fast as possible. It shows how to grab a pre-built version of the application,
point it at your data source (PACS), and plop it on a web server.
## Options
### 1. Pre-built PWA
...
### 2. Script-Tag
...
### 3. Docker
...
## Security Concerns
- Secure your data
## Common Issues
- Missing server rewrite rules
- CORS issues when requesting data from PACS

View File

@ -0,0 +1,4 @@
{
"label": "Services",
"position": 12
}

View File

@ -1,132 +0,0 @@
<table>
<thead>
<tr>
<th>Service</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="./data/DicomMetadataStore.md">
DicomMetadataStore (NEW)
</a>
</td>
<td>Data Service</td>
<td>
DicomMetadataStore
</td>
</tr>
<tr>
<td>
<a href="./data/DisplaySetService.md">
DisplaySetService (NEW)
</a>
</td>
<td>Data Service</td>
<td>
DisplaySetService
</td>
</tr>
<tr>
<td>
<a href="./data/HangingProtocolService.md">
HangingProtocolService (NEW)
</a>
</td>
<td>Data Service</td>
<td>
HangingProtocolService
</td>
</tr>
<tr>
<td>
<a href="./data/MeasurementService.md">
MeasurementService (MODIFIED)
</a>
</td>
<td>Data Service</td>
<td>
MeasurementService
</td>
</tr>
<tr>
<td>
<a href="./data/ToolbarService.md">
ToolBarService (NEW)
</a>
</td>
<td>Data Service</td>
<td>
ToolBarService
</td>
</tr>
<tr>
<td>
<a href="./ui/ViewportGridService.md">
ViewportGridService (NEW)
</a>
</td>
<td>UI Service</td>
<td>
ViewportGridService
</td>
</tr>
<tr>
<td>
<a href="./ui/cine.md">
Cine Service (NEW)
</a>
</td>
<td>UI Service</td>
<td>
cine
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-dialog-service.md">
UIDialogService
</a>
</td>
<td>UI Service</td>
<td>
UIDialogService
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-modal-service.md">
UIModalService
</a>
</td>
<td>UI Service</td>
<td>
UIModalService
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-notification-service.md">
UINotificationService
</a>
</td>
<td>UI Service</td>
<td>
UINotificationService
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-viewport-dialog-service.md">
UIViewportDialogService (NEW)
</a>
</td>
<td>UI Service</td>
<td>
UIViewportDialogService
</td>
</tr>
</tbody>
</table>

View File

@ -1,3 +1,7 @@
---
sidebar_position: 2
sidebar_label: DICOM Metadata Store
---
# DICOM Metadata Store
@ -62,9 +66,7 @@ stored and in what format and hierarchy. `_model` is a private variable in the s
which holds all the metadata for all studies, series, and instances, and it looks like:
```js
// platform/core/src/services/DicomMetadataStore/DicomMetadataStore.js
```js title="platform/core/src/services/DicomMetadataStore/DicomMetadataStore.js"
const _model = {
studies: [
{
@ -107,5 +109,4 @@ const _model = {
},
],
}
```

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
sidebar_label: DisplaySet Service
---
# DisplaySet Service
@ -7,9 +11,7 @@
> Based on the instanceMetadata's `SOPClassHandlerId`, the correct module from the registered extensions is found by `OHIF` and its `getDisplaySetsFromSeries` runs to create a DisplaySet for the Series.
```js
// platform/core/src/services/DisplaySetService/DisplaySetService.js
```js title="platform/core/src/services/DisplaySetService/DisplaySetService.js"
init(extensionManager, SOPClassHandlerIds) {
this.extensionManager = extensionManager;
this.SOPClassHandlerIds = SOPClassHandlerIds;
@ -19,9 +21,7 @@ init(extensionManager, SOPClassHandlerIds) {
in `Mode.jsx`
```js
// platform/viewer/src/routes/Mode/Mode.jsx
```js title="platform/viewer/src/routes/Mode/Mode.jsx"
export default function ModeRoute(/** ... **/) {
/** ... **/
const { DisplaySetService } = servicesManager.services

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
sidebar_label: Hanging Protocol Service
---
# Hanging Protocol Service
## Overview

View File

@ -1,3 +1,7 @@
---
sidebar_position: 6
sidebar_label: Measurement Service
---
# Measurement Service
@ -75,9 +79,7 @@ provide three mappers:
- `toMeasurement`: a function that converts the tool data to OHIF internal representation of measurement data.
```js
// extensions/cornerstone/src/utils/measurementServiceMappings/Length.js
```js title="extensions/cornerstone/src/utils/measurementServiceMappings/Length.js"
function toMeasurement(
csToolsAnnotation,
DisplaySetService,

View File

@ -1,3 +1,7 @@
---
sidebar_position: 5
sidebar_label: Toolbar Service
---
# Toolbar Service
@ -6,9 +10,12 @@
the user.
<div style="padding:62.5% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/547957214?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Toolbar"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/547957214?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
## Events
@ -158,9 +165,7 @@ You can see below how `longitudinal` mode is using the available toolbarModule t
![toolbarModule-nested-buttons](../../assets/img/toolbarModule-nested-buttons.png)
```js
// modes/longitudinal/src/toolbarButtons.js
```js title="modes/longitudinal/src/toolbarButtons.js"
{
id: 'MeasurementTools',
type: 'ohif.splitButton',

View File

@ -0,0 +1,4 @@
{
"label": "Data Services",
"position": 2
}

View File

@ -1,65 +0,0 @@
# Services (default)
- [Overview](#overview)
- [Example](#example)
## Overview
Services are a work in progress. As we are still in the progress of creating a
non-ui maintained service, this usage may change.
<div style="text-align: center;">
<a href="/assets/img/services.png">
<img src="/assets/img/services.png" alt="UI Services Diagram" style="margin: 0 auto; max-width: 500px;" />
</a>
<div><i>Diagram showing relationship between React Context and UI Service</i></div>
</div>
## Example
The simplest service return a new object that has a `name` property, and
methods/properties that give the service its functionality. The "Factory
Function" that creates the service is provided with the implementation (this is
slightly different for UI Services).
```js
const _speak = () => {
console.warn('Speak is not implemented');
};
/**
* Factory function to create `HelloWorldService`
*
* @param {object} implementation
* @param {function} implementation.speak - Speak's implementation
* @returns HelloWorldService
*/
export default function createHelloWorldService({ speak }) {
return {
name: 'HelloWorldService',
speak: speak || _speak,
};
}
```
A service, once created, can be registered with the `ServicesManager` to make it
accessible to extensions. Similarly, the application code can access named
services from the `ServicesManager`.
```js
// In the application
const speak = () => {
window.alert('HELLO WORLD');
};
const HelloWorldService = createHelloWorldService({ speak });
const servicesManager = new ServicesManager();
servicesManager.registerService(HelloWorldService);
// In an extension
const { HelloWorldService } = servicesManager.services;
if (HelloWorldService) {
HelloWorldService.speak();
}
```

View File

@ -1,8 +1,11 @@
# Services (default)
---
sidebar_position: 1
sidebar_label: Overview
---
# Overview
## Overview
Data services are the first category of services which deal with handling non-ui related state
Each services have their own internal state which they handle.

View File

@ -1,8 +1,9 @@
# Services And Managers
---
sidebar_position: 1
sidebar_label: Introduction
---
# Services
- [Services And Managers](#services-and-managers)
- [Overview](#overview)
- [Services](#services)
## Overview
Services are "concern-specific" code modules that can be consumed across layers. Services provide
@ -25,7 +26,138 @@ Each service should be:
## Services
The following services is available in the `OHIF-v3`.
{% include "./_services.md" %}
<table>
<thead>
<tr>
<th>Service</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="./data/DicomMetadataStore.md">
DicomMetadataStore (NEW)
</a>
</td>
<td>Data Service</td>
<td>
DicomMetadataStore
</td>
</tr>
<tr>
<td>
<a href="./data/DisplaySetService.md">
DisplaySetService (NEW)
</a>
</td>
<td>Data Service</td>
<td>
DisplaySetService
</td>
</tr>
<tr>
<td>
<a href="./data/HangingProtocolService.md">
HangingProtocolService (NEW)
</a>
</td>
<td>Data Service</td>
<td>
HangingProtocolService
</td>
</tr>
<tr>
<td>
<a href="./data/MeasurementService.md">
MeasurementService (MODIFIED)
</a>
</td>
<td>Data Service</td>
<td>
MeasurementService
</td>
</tr>
<tr>
<td>
<a href="./data/ToolbarService.md">
ToolBarService (NEW)
</a>
</td>
<td>Data Service</td>
<td>
ToolBarService
</td>
</tr>
<tr>
<td>
<a href="./ui/ViewportGridService.md">
ViewportGridService (NEW)
</a>
</td>
<td>UI Service</td>
<td>
ViewportGridService
</td>
</tr>
<tr>
<td>
<a href="./ui/cine.md">
Cine Service (NEW)
</a>
</td>
<td>UI Service</td>
<td>
cine
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-dialog-service.md">
UIDialogService
</a>
</td>
<td>UI Service</td>
<td>
UIDialogService
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-modal-service.md">
UIModalService
</a>
</td>
<td>UI Service</td>
<td>
UIModalService
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-notification-service.md">
UINotificationService
</a>
</td>
<td>UI Service</td>
<td>
UINotificationService
</td>
</tr>
<tr>
<td>
<a href="./ui/ui-viewport-dialog-service.md">
UIViewportDialogService (NEW)
</a>
</td>
<td>UI Service</td>
<td>
UIViewportDialogService
</td>
</tr>
</tbody>
</table>
<!--

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
sidebar_label: Pub Sub
---
# Pub sub
## Overview
@ -64,8 +68,7 @@ You need to be careful if you are adding custom subscriptions to the app. Each s
Below, we can see `simplified` `Mode.jsx` and the corresponding `useEffect` where the unsubscription functions are executed upon destruction.
```js
// platform/viewer/src/routes/Mode/Mode.jsx
```js title="platform/viewer/src/routes/Mode/Mode.jsx"
export default function ModeRoute(/**..**/) {
/**...**/
useEffect(

View File

@ -1,3 +1,7 @@
---
sidebar_position: 6
sidebar_label: Viewport Grid Service
---
# Viewport Grid Service
@ -6,8 +10,6 @@ This is a new UI service, that handles the grid layout of the viewer.
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/549261939?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Viewport Modal"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
## Interface

View File

@ -0,0 +1,4 @@
{
"label": "UI Services",
"position": 3
}

View File

@ -1,7 +1,10 @@
# UI Services
---
sidebar_position: 1
sidebar_label: Overview
---
# Overview
## Overview
<!-- - Consistent look & feel
@ -61,9 +64,7 @@ The `ServicesManager` is:
**There are several context providers that wraps the application routes. This
makes the context values exposed in the app, and service's `setImplementation` can get run to override the implementation of the service.**
```js
// platform/viewer/src/App.jsx
```js title="platform/viewer/src/App.jsx"
function App({ config, defaultExtensions }) {
/**...**/
/**...**/
@ -91,9 +92,7 @@ function App({ config, defaultExtensions }) {
For instance `UIModalService` has the following Public API:
```js
// platform/core/src/services/UIModalService/index.js
```js title="platform/core/src/services/UIModalService/index.js"
const publicAPI = {
name,
hide: _hide,
@ -121,9 +120,7 @@ export default {
`UIModalService` implementation can be set (override) in its context provider. For instance in `ModalProvider` we have:
```js
// platform/ui/src/contextProviders/ModalProvider.jsx
```js title="platform/ui/src/contextProviders/ModalProvider.jsx"
import { Modal } from '@ohif/ui'
const ModalContext = createContext(null)
@ -194,9 +191,7 @@ Therefore, anywhere in the app that we have access to react context we can use i
A `simplified` code for our worklist is:
```js
// platform/viewer/src/routes/WorkList/WorkList.jsx
```js title="platform/viewer/src/routes/WorkList/WorkList.jsx"
import { useModal, Header } from '@ohif/ui'
function WorkList({

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
sidebar_label: UI Dialog Service
---
# UI Dialog Service
Dialogs have similar characteristics to that of Modals, but often with a

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
sidebar_label: UI Modal Service
---
# UI Modal Service
Modals have similar characteristics to that of Dialogs, but are often larger,
@ -11,7 +15,10 @@ be centered, and not draggable. They're commonly used when:
If you're curious about the DOs and DON'Ts of dialogs and modals, check out this
article: ["Best Practices for Modals / Overlays / Dialog Windows"][ux-article]
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/549261451?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Viewer Modal"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/549261451?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
## Interface

View File

@ -1,3 +1,7 @@
---
sidebar_position: 2
sidebar_label: UI Notification Service
---
# UI Notification Service
Notifications can be annoying and disruptive. They can also deliver timely
@ -12,7 +16,13 @@ guidance on when and how to use them:
If you're curious about the DOs and DON'Ts of notifications, check out this
article: ["How To Design Notifications For Better UX"][ux-article]
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/549260975?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="notification"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/549260975?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
## Interface
For a more detailed look on the options and return values each of these methods

View File

@ -1,3 +1,8 @@
---
sidebar_position: 5
sidebar_label: UI Viewport Dialog Service
---
# UI Viewport Dialog Service
## Overview
@ -15,8 +20,9 @@ article: ["Best Practices for Modals / Overlays / Dialog Windows"][ux-article]
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/549261939?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Viewport Modal"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/549261939?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
## Interface

View File

@ -0,0 +1,4 @@
{
"label": "User Manuals",
"position": 3
}

View File

@ -1,19 +1,70 @@
# Overview
Our documentations in this section is tailored toward the end-user. Developers
can skip this section and visit the development section.
In this section, we explore various core functionalities and use cases that `OHIF viewer`
provides. In order to follow the guides below, you need to have a running instance
of the viewer.
---
sidebar_position: 2
sidebar_label: Study list
---
# Study list
## Overview
The first page you will see when the viewer is loaded is called `Study List`.
In this page you can explore all the studies that are stored on the configured
server for the `OIHF Viewer`.
![user-study-list](../assets/img/user-study-list.png)
At the end of the page you can navigate to the next/previous page or change the
default number of studies that are shown
![user-study-next](../assets/img/user-study-next.png)
## Filters
There are certain filters that can be used to limit the study list to the desired
criteria.
- Patient Name: Searches between patients names
- MRN: Searches between patients Medical Record Number
- Study Data: Filters the date of the acquisition
- Description: Searches between study descriptions
- Modality: Filters the modalities
- Accession: Searches between patients accession number
- [Study List](./studyList/index.md)
- [Filters](./studyList/index.md#filters)
- [Study Summary](./studyList/index.md#study-summary)
- [Study-specific modes](./studyList/index.md#study-specific-modes)
- [Viewer (Basic Viewer)](./viewer/index.md)
- [Overview](./viewer/index.md#overview)
- [Study Panel](./viewer/studyPanel/study-panel.md#overview)
- [Measurement Panel](./viewer/measurementPanel/measurement-panel.md#overview)
- [Viewport](./viewer/viewport/viewport.md#overview)
- [Toolbar](./viewer/toolbar/toolbar.md#overview)
- [HotKeys](./viewer/hotkeys/hotkeys.md#overview)
An example of using study list filter is shown below:
![user-study-filter](../assets/img/user-study-filter.png)
## Study Summary
If you you click on one of the studies, the panel for displaying the summary
of the study will shows up.
![user-study-summary](../assets/img/user-study-summary.png)
As you can see, a summary of series available in the study is shown, which contains
the series description, series number, modality of the series, and instances in the series.
Next, We will discuss the modes, and their enabled/disabled states.
## Study Specific Modes
As seen for each study, all the available modes will get shown. What is a mode?
Modes define the higher-level functionalities and appearance for the viewer.
For instance, as seen, there are two modes shown for the selected study
- Basic Viewer: Default mode that enables rendering and measurement tracking
- PET/CT Fusion: Mode for visualizing the PET CT study in a 3x3 format.
However, based on the mode configurations (e.g., available modalities), they can be
enabled or disabled.
Below, you can see two studies, In Study 1, Basic Viewer mode is enabled and
ready to be used; however, the PET/CT fusion is disabled by the viewer since
only PET images are found in the study.
![user-studyist-modespecific](../assets/img/user-studyist-modespecific.png)
## View Study
You can click on the `Basic Viewer` to open the viewer for the selected study.
![user-open-viewer](../assets/img/user-open-viewer.png)

View File

@ -1,70 +0,0 @@
# Study list
- [Study List](./index.md)
- [Filters](./index.md#filters)
- [Study Summary](./index.md#study-summary)
- [Study-specific modes](./index.md#study-specific-modes)
- [View Study](./index.md#view-study)
## Overview
The first page you will see when the viewer is loaded is called `Study List`.
In this page you can explore all the studies that are stored on the configured
server for the `OIHF Viewer`.
![user-study-list](../../assets/img/user-study-list.png)
At the end of the page you can navigate to the next/previous page or change the
default number of studies that are shown
![user-study-next](../../assets/img/user-study-next.png)
## Filters
There are certain filters that can be used to limit the study list to the desired
criteria.
- Patient Name: Searches between patients names
- MRN: Searches between patients Medical Record Number
- Study Data: Filters the date of the acquisition
- Description: Searches between study descriptions
- Modality: Filters the modalities
- Accession: Searches between patients accession number
An example of using study list filter is shown below:
![user-study-filter](../../assets/img/user-study-filter.png)
## Study Summary
If you you click on one of the studies, the panel for displaying the summary
of the study will shows up.
![user-study-summary](../../assets/img/user-study-summary.png)
As you can see, a summary of series available in the study is shown, which contains
the series description, series number, modality of the series, and instances in the series.
Next, We will discuss the modes, and their enabled/disabled states.
## Study Specific Modes
As seen for each study, all the available modes will get shown. What is a mode?
Modes define the higher-level functionalities and appearance for the viewer.
For instance, as seen, there are two modes shown for the selected study
- Basic Viewer: Default mode that enables rendering and measurement tracking
- PET/CT Fusion: Mode for visualizing the PET CT study in a 3x3 format.
However, based on the mode configurations (e.g., available modalities), they can be
enabled or disabled.
Below, you can see two studies, In Study 1, Basic Viewer mode is enabled and
ready to be used; however, the PET/CT fusion is disabled by the viewer since
only PET images are found in the study.
![user-studyist-modespecific](../../assets/img/user-studyist-modespecific.png)
## View Study
You can click on the `Basic Viewer` to open the viewer for the selected study.
![user-open-viewer](../../assets/img/user-open-viewer.png)

View File

@ -0,0 +1,22 @@
---
sidebar_position: 7
---
# Language
OHIF supports internationalization capabilities and setting the general language
of the Viewer.
It should be noted that we don't have complete translations for all the components
and all the languages; however, you can easily add the key value translation pairs
following developer guides.
Summary of language changing usage can be seen below:
## Overview Video
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/559038442?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>

View File

@ -1,12 +0,0 @@
# Language
OHIF supports internationalization capabilities and setting the general language
of the Viewer.
It should be noted that we don't have complete translations for all the components
and all the languages; however, you can easily add the key value translation pairs
following developer guides.
Summary of language changing usage can be seen below:
**Upload**

View File

@ -0,0 +1,4 @@
{
"label": "Viewer",
"position": 2
}

View File

@ -1,10 +1,14 @@
---
sidebar_position: 6
---
# Hotkeys
To open the hotkey assignment panel, you can click on the Preferences gear on the
top right side of the viewer.
![user-hotkeys](../../../assets/img/user-hotkeys.png)
![user-hotkeys](../../assets/img/user-hotkeys.png)
Below, you can see the default hotkeys key bindings:
![user-hotkeys-default](../../../assets/img/user-hotkeys-default.png)
![user-hotkeys-default](../../assets/img/user-hotkeys-default.png)

View File

@ -1,10 +1,7 @@
# Viewer
- [Viewer](./index.md)
- [Overview](./index.md#overview)
- [Study Panel](./studyPanel/study-panel.md)
- [Measurement Panel](./measurementPanel/measurement-panel.md)
- [Toolbar](./toolbar/toolbar.md)
- [HotKeys](./hotkeys/hotkeys.md)
---
sidebar_position: 1
sidebar_label: Overview
---
# Overview

View File

@ -1,49 +1,54 @@
---
sidebar_position: 3
---
# Measurement panel
## Introduction
In `Basic Viewer` mode, right panel is the `Measurement Panel`. When you use an annotation tool, a pop up will show up and asks the user if they want to track measurements for the
series on which the annotation was drawn.
![user-measurement-panel-modal](../../../assets/img/user-measurement-panel-modal.png)
![user-measurement-panel-modal](../../assets/img/user-measurement-panel-modal.png)
If you select `yes`, the series becomes a `tracked series`, and the current drawn measurement and next measurements will get shown up on the measurement panel on the right.
![user-measurement-panel-tracked](../../../assets/img/user-measurement-panel-tracked.png)
![user-measurement-panel-tracked](../../assets/img/user-measurement-panel-tracked.png)
# Renaming Measurements
## Renaming Measurements
You can edit the measurement name by hovering over the measurement and selecting the edit icon.
![user-measurement-edit](../../../assets/img/user-measurement-edit.png)
![user-measurement-edit](../../assets/img/user-measurement-edit.png)
![user-measurement-edit-name](../../../assets/img/user-measurement-edit-name.png)
![user-measurement-edit-name](../../assets/img/user-measurement-edit-name.png)
Result:
![user-measurement-name](../../../assets/img/user-measurement-name.png)
![user-measurement-name](../../assets/img/user-measurement-name.png)
# Deleting a Measurement
## Deleting a Measurement
A measurement can be deleting by dragging it outside the image in the viewport. You can
take a look at the overview video to see this behavior.
# Jumping to a Measurement
## Jumping to a Measurement
Measurements that appear on the measurement panel are linked directly to their original
tool on the viewport. This enables the user to click on a measurement and the viewport will jump to the slice that the measurement has been drawn. You can
take a look at the overview video to see this behavior.
# Prev/Next Measurement
## Prev/Next Measurement
Measurement navigation inside the top viewport can be used to move to previous and next measurement.
![user-measurement-prevnext](../../../assets/img/user-measurement-prevnext.png)
![user-measurement-prevnext](../../assets/img/user-measurement-prevnext.png)
# Export Measurements
## Export Measurements
You can export the measurements by clicking on the `Export`. A CSV file will get downloaded to your local computer containing the drawn measurements.
![user-measurement-export](../../../assets/img/user-measurement-export.png)
![user-measurement-export](../../assets/img/user-measurement-export.png)
If you have set up your DICOM server to be able to store instances from the viewer, then you are able to create a report by clicking on the `Create Report`.
@ -52,11 +57,17 @@ to the server.
For instance, running the Viewer on a local DCM4CHEE:
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/557569965?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="DICOM SR Export"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/557569965?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
# Overview video
## Overview Video
An overview of measurement drawing and exporting can be seen below:
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545986384?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="measurement-report"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/545986384?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>

View File

@ -1,4 +1,8 @@
# Study panel
---
sidebar_position: 2
---
# Study Panel
In `Basic Viewer` mode, the left panel includes Studies related to the current patient.
You can see three main type of studies below
@ -7,10 +11,10 @@ You can see three main type of studies below
- Recent: Other studies for this patient
- All: Includes both primary and recent studies
![user-study-panel](../../../assets/img/user-study-panel.png)
![user-study-panel](../../assets/img/user-study-panel.png)
This is a new feature that we have added to `OHIF-v3`, that shows all the studies that the patient with the specific MRN had and are available from the data storage.
![user-studylist-all](../../../assets/img/user-studylist-all.png)
![user-studylist-all](../../assets/img/user-studylist-all.png)
As you can see the first picture, the dashed circle on the left side of each series demonstrates whether the series is being tracked for measurement or not.

View File

@ -1,19 +1,21 @@
---
sidebar_position: 5
---
# Toolbar
The four main components of the toolbar are:
- Navigation back to the [Study List](../../studyList/index.md)
- Navigation back to the [Study List](../index.md)
- Logo and white labelling
- [Tools](#tools)
- [Preferences](#preferences)
![user-viewer-toolbar](../../../assets/img/user-viewer-toolbar.png)
![user-viewer-toolbar](../../assets/img/user-viewer-toolbar.png)
# Tools
## Tools
This section displays all the available tools inside the mode.
## Measurement tools
@ -28,7 +30,7 @@ via:
- Probe: To read the intensity value at a location
![user-viewer-toolbar-measurements](../../../assets/img/user-viewer-toolbar-measurements.png)
![user-viewer-toolbar-measurements](../../assets/img/user-viewer-toolbar-measurements.png)
To draw a measurement you can select it from the toolbar and click and drag mouse
to reach the desired shape, size and direction.
@ -36,35 +38,39 @@ to reach the desired shape, size and direction.
A sample tool drawing is shown below
# Presets
## Presets
Preset tool enables manipulating the window level and window width of the rendered
image, which basically modifies the contrast and brightness.
You can also choose from the list of pre-defined presets by clicking on the triangle.
![user-toolbar-preset](../../../assets/img/user-toolbar-preset.png)
![user-toolbar-preset](../../assets/img/user-toolbar-preset.png)
# Download High Quality Image
## Download High Quality Image
By clicking on the Camera icon you can open the window for downloading the image as
common image formats (png, jpg)
![user-toolbar-download-icon](../../../assets/img/user-toolbar-download-icon.png)
![user-toolbar-download-icon](../../assets/img/user-toolbar-download-icon.png)
In the opened modal, you can set the filename, image's width and height, and filetype and press download for downloading the image to your local computer.
![user-toolbar-download](../../../assets/img/user-toolbar-download.png)
![user-toolbar-download](../../assets/img/user-toolbar-download.png)
# Extra tools
## Extra tools
Lots of other tools are also available in the last tool icon drawer. If you
click on the triangle they will get appeared.
![user-toolbar-extra](../../../assets/img/user-toolbar-extra.png)
![user-toolbar-extra](../../assets/img/user-toolbar-extra.png)
# Overview
## Overview Video
An overview of tool usage can been seen below:
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545989422?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Toolbar-annotation"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/545989422?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>

View File

@ -1,9 +1,14 @@
---
sidebar_position: 4
---
# Viewport
## Introduction
Image visualization happens at the viewport which contains canvas or canvases that
renders series.
![user-viewer-main](../../../assets/img/user-viewer-main.png)
![user-viewer-main](../../assets/img/user-viewer-main.png)
By default you can modify:
@ -14,21 +19,24 @@ By default you can modify:
# Changing Series for display
## Changing Series for display
To change the displayed series, you can drag and drop the desired series from the left panel. Start, by dragging the thumbnail of the series, and drop it on the viewport.
# Changing Layout
## Changing Layout
If you click on the layout icon on the toolbar, you can use the layout selector UI. After changing the layout, you can select studies for each new viewport by dragging and dropping in to the viewport.
After changing the layout from 1x1, you will see each viewport gets tagged by a letter,
which matches its series section in the study list.
![user-viewer-layout](../../../assets/img/user-viewer-layout.png)
![user-viewer-layout](../../assets/img/user-viewer-layout.png)
# Overview video
## Overview Video
An overview of viewport layout change, and manipulation can be seen below:
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545995881?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="viewer-layout-2"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
<iframe src="https://player.vimeo.com/video/545995881?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>

View File

@ -0,0 +1,4 @@
{
"label": "Viewer",
"position": 8
}

View File

@ -1,12 +1,23 @@
---
sidebar_position: 1
sidebar_label: Config
---
# Viewer: Configuration
The OHIF Viewing Platform strives to be highly configurable and extensible. This
makes it easier for our community members to keep their "secret sauce" private,
and incentives contributions back to the platform. The `@ohif/viewer` project
of the platform is the lynchpin that combines everything to create our
application.
We maintain a number of common viewer application configurations at
[`<root>/platform/viewer/public/configs`][config-dir].
You can take a look at how to use different configs in the [Environment Variables](../configuring/index.md#environment-variables)
```js
```js title="<root>/platform/viewer/public/configs"
window.config = {
routerBasename: '/',
/**

View File

@ -1,3 +1,7 @@
---
sidebar_position: 3
sidebar_label: Environment Variables
---
# Environment Variables
There are a number of environment variables we use at build time to influence the output application's behavior.

View File

@ -1,3 +0,0 @@
# Hotkeys
...

View File

@ -1,7 +0,0 @@
# Viewer
The OHIF Viewing Platform strives to be highly configurable and extensible. This
makes it easier for our community members to keep their "secret sauce" private,
and incentives contributions back to the platform. The `@ohif/viewer` project
of the platform is the lynchpin that combines everything to create our
application.

View File

@ -1,3 +1,7 @@
---
sidebar_position: 4
sidebar_label: Internationalization
---
# Viewer: Internationalization
OHIF supports internationalization using [i18next](https://www.i18next.com/)
@ -102,7 +106,7 @@ all.
But, if you need to use it completely outside of OHIF viewer, you can set the
I18nextProvider this way:
```js
```jsx
import i18n from '@ohif/i18n';
import { I18nextProvider } from 'react-i18next';
import App from './App';
@ -132,7 +136,7 @@ console.log(T('$t(Common:Play) my translated text'));
---
# Main Concepts While Translating
## Main Concepts While Translating
## Namespaces

View File

@ -1,3 +1,7 @@
---
sidebar_position: 2
sidebar_label: Theming
---
# Viewer: Theming

View File

@ -45,13 +45,13 @@ const isI18nStaging = process.env.I18N_STAGING === 'true';
/** @type {import('@docusaurus/types').DocusaurusConfig} */
(module.exports = {
title: 'Docusaurus',
title: 'OHIF',
tagline: 'Build optimized websites quickly, focus on your content',
organizationName: 'facebook',
projectName: 'docusaurus',
projectName: 'OHIF',
baseUrl,
baseUrlIssueBanner: true,
url: 'https://docusaurus.io',
url: 'https://ohif.org',
i18n: {
defaultLocale: 'en',
locales: isDeployPreview

View File

@ -8,7 +8,12 @@ it into an existing web application. It allows us to forego a "build step", and
add a powerful medical imaging viewer to an existing web page using only a few
include tags. Here's how it works:
{% include "./../_embedded-viewer-diagram.md" %}
![embeddedViewer](../../assets/img/embedded-viewer-diagram.png)
1. Create a new web page or template that includes the following external
dependencies:

View File

@ -61,7 +61,6 @@ CORS][understanding-cors]
This setup allows us to create a setup similar to the one pictured below:
<!-- {% include "./../_nginx-image-archive-diagram.md" %} -->
![nginX](../../assets/img/nginx-image-archive.png)