feat: cornerstone3D stack and volume viewports (#2787)
* feat: cs3d working stack viewport and tools (#19) * Squashed everything * fix weird react issue * fix eslint / prettier stuff * thumbnails work now with cpu rendering * feat: use new loadImageToCanvas in cs3d * make jump to measurement work * fix active thumbnail * fix measurement delete * fix window level presets * remove segmentation and sync groups for now * fix the dicom pdf and dicom video * fix cornerstone window assignment for cypress * apply review comments Co-authored-by: Erik <erik.sweed@gmail.com> * feat: cs3d tools and toolGroups (#20) * add more tools to work with cs3d mode * fix hotkeys * add stack manager usage for stach viewports * add image scrollbar * wip viewport overlay * fix toAnnotation schema for tools * fix the unnecessary size change that triggered resize * hanging protocol improvement to allow unmatched errors * study description matching for hanging protocol * fix the displaysetOptions to work * fix handle the active tool when a new viewport is added * fix separate toolGroups for mode * apply review comments * apply review comments * yarn lock * feat: overlay component (#21) * fix default displayset options * add viewport overlay * apply review comments * feat: loading and orientation indicators (#22) * add loading indicator * add orientation marker initial work * apply review comments * fix: orientation markers (#23) * finished the orientation markers * fix various broken cypress tests * apply review comments * update yarn lock * feat: re-working measurement tracking mode with cornerstone3d (#2805) * feat: cs3d working stack viewport and tools (#19) * Squashed everything * fix weird react issue * fix eslint / prettier stuff * thumbnails work now with cpu rendering * feat: use new loadImageToCanvas in cs3d * make jump to measurement work * fix active thumbnail * fix measurement delete * fix window level presets * remove segmentation and sync groups for now * fix the dicom pdf and dicom video * fix cornerstone window assignment for cypress * apply review comments Co-authored-by: Erik <erik.sweed@gmail.com> * feat: Add Measurement tracking mode with cs3D (#2789) * feat: first render for cornerstone3d tracked viewport * make tool active work * wip for SR extension * renamed dicom sr to cornerstone dicom sr * remove cornerstone from dicom pdf and video * move dicom sr logic to sr extension * feat: Add hydration for the length tool * fix SR display tool for length using cs3d * fix default config * fix: various bugs with sr viewport and tracking * fix promptying to continue tracking for when SR is created * feat: add keep trackign of unique identifiers * fix hydration for same imageIds * feat: Add SR toolGroup creation on modeEnter * feat: remove the need for separate mapper for SR hydration * add SR display for ellipse * handle hydration of elliptical ROI tool * remove cornerstone extension * add arrow mapping * feat: Add ArrowAnnotate SR display and hydration * apply review comments * apply review comments * move viewport labels to the viewportData * apply review comments * fix: integration cypress tests with cornerstone3D and add CINE tool (#2795) * fix: integration cypress tests with cornerstone3D * revert to addOrUpdate as it makes more sense * fix local drag and drop * fix tests * move dicomLoaderService to cornerstone extension * fix various import bugs * fix bug for local PT series * fix various unit tests * bump cs3d versions * add angle and magnify tool * bump dependencies to avoid broken peerDeps * feat: add initial work for capture using cs3d * feat: show annotations on the image capture * feat: add svg layer export * feat: Add CINE Tool * feat: remove unnecessary viewport rendering for cine state changes Co-authored-by: Erik Ziegler <erik.sweed@gmail.com> * docs: modify and improve documentation (#2800) * cleanup docs versionings * feat: Add all version explanations * version docs for 3.0 * wip for changing docs * wip for updated docs * add utility module documentation * fix demo with nohoisting of history * add slides and video to resources * apply review comments * fix: drag and drop SR into SR viewport (#2803) * update yarn lock Co-authored-by: Erik <erik.sweed@gmail.com> * update pathnames to match v3-stable * update the e2e pathname * fix: various bugs with regard to tracking workflow (#2811) * fix: various issues with measurement panel * fix: update default tool style for annotations * fix: annotatoin label getting removed * feat: Add backward compatibility for SR hydration with legacy cornerstone * fix: cursors and ellipse ROI max style * fix: ArrowAnnotate SRDisplay * apply review comments * bump package versions * fix: bugin rehydration of SR * fix: e2e tests * fix active viewport thickness and arrowTool ui * add readme for measurement tracking * use uploaded image for readme * add back images * try to fix e2e test * fix: window level presets hotkeys * Update README.md * update yarn lock * feat: volume api and TMTV mode (#2817) * feat: volumeAPI and TMTV mode * feat: use cs3d cache service to obtain viewportData * wip for volume api * wip: fusion viewport * feat: add blend mode option * wip for image scrollbar * fix drag and drop thumbnail * wip for image scrollbar for voluems * fix: element mismatch bug for scroll * feat: Add image scrollbar to volumes * feat: add syncGroups to volume api * feat: add tmtv mode initial setup * feat: add initial image options for the stack viewports * feat: Add custom load strategy for volume viewports via HP * apply review comments fix: Jump presets cs3d (#2812) * feat: Add JumpPreset to OHIF for Cornerstone3D * fix: accessing viewport service from servicesManager feat: volume API and TMTV mode (#2814) * fix: do not display overlays on mip viewports * feat: add optional disableCommands for toggle buttons * fix: toggleCrossharis * feat: config the crosshairs * feat: add PetSUV Panel for changing metadata * feat: initial work for the rectangleROIThreshold panel * wip: measurement service * roi threshold working * feat: Add displayText to segmentations * feat: add remove segmentation * feat: add csv export * feat: add RT export for annotations in tmtv mode * fix: fusion to use pt in tmtv mode and measuremet mappings * fix: various bugs * apply review comments * apply review comments * feat: add fusion color maps * add readme to tmtv mode * Update README.md * fix: try to fix build * fix unit tests * Update README.md * feat: add about to the panel * fix: changing strategy in roi panel * apply review comments * update package versions * wip for stackPrefetch * fix: cornerstone3d hydration and renaming (#2818) * update readme * renamed cornerstone extension * wip for renaming cornerstone3D variables * wip for renaming cornerstone3D variables * wip for fixing bugs for SR viewport * fix: jumpToMeasurement and initial label after hydration * fix: fileName capitalization * feat: use the new prefetch stack in the cs3d (#2820) * feat: use the new prefetch stack in the cs3d * use viewport scroll api for stack viewport * fix cine stop when scrollbar changes * feat: use new prefetch events * fix loading state to not show repeatedly * fix: various bugs for tmtv mode thresholding and new icons (#2823) * feat: make tmtv mode available in worklist * feat: add new icons for tmtv mode * feat: add fusion color icon * fix: parallel scale calculation * fix: bump Cornerstone to get large image support working * fix: Fix issues with CPU viewport flipping, including config files * fix: bump cornerstone to fix magnify tool * fix: Bump Cornerstone version to fix resetCamera issue in StackViewport * ci: Add _headers file to enable CORS headers for Netlify Drag/Drop deploys * fix: WADO-URI was not working. PET Metadata was coming from the wrong place. Fixed some minor React errors * feat(OHIF):Allow modes and extensions to be added after commpile time. (#2838) Also works with the compile time add that the existing cli uses, so that both build types work. Eric and I agreed this doesn't change existing functionality, but is almost entirely build issues/fixes. * bump: dependency versions to fix hydration bugs (#2848) * bump: dcmjs version to fix hydration bugs * try to fix tests * bump dependency versions Co-authored-by: Alireza <ar.sedghi@gmail.com> Co-authored-by: Bill Wallace <wayfarer3130@gmail.com>
This commit is contained in:
668 files changed
+41669
-13410
No files matched your search
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Deployment",
|
||||
"position": 3
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Build for Production
|
||||
|
||||
### Build Machine Requirements
|
||||
|
||||
- [Node.js & NPM](https://nodejs.org/en/download/)
|
||||
- [Yarn](https://yarnpkg.com/lang/en/docs/install/)
|
||||
- [Git](https://www.atlassian.com/git/tutorials/install-git)
|
||||
|
||||
### Getting the Code
|
||||
|
||||
_With Git:_
|
||||
|
||||
```bash
|
||||
# Clone the remote repository to your local machine
|
||||
git clone https://github.com/OHIF/Viewers.git
|
||||
```
|
||||
|
||||
More on: _[`git clone`](https://git-scm.com/docs/git-clone),
|
||||
[`git checkout`](https://git-scm.com/docs/git-checkout)_
|
||||
|
||||
_From .zip:_
|
||||
|
||||
[OHIF/Viewers: master.zip](https://github.com/OHIF/Viewers/archive/master.zip)
|
||||
|
||||
### Restore Dependencies & Build
|
||||
|
||||
Open your terminal, and navigate to the directory containing the source files.
|
||||
Next run these commands:
|
||||
|
||||
```bash
|
||||
# If you haven't already, enable yarn workspaces
|
||||
yarn config set workspaces-experimental true
|
||||
|
||||
# Restore dependencies
|
||||
yarn install
|
||||
|
||||
# Build source code for production
|
||||
yarn run build
|
||||
```
|
||||
|
||||
If everything worked as expected, you should have a new `dist/` directory in the
|
||||
`platform/viewer/dist` folder. It should roughly resemble the following:
|
||||
|
||||
```bash title="<root>platform/viewer/dist/"
|
||||
├── app-config.js
|
||||
├── app.bundle.js
|
||||
├── app.css
|
||||
├── index.html
|
||||
├── manifest.json
|
||||
├── service-worker.js
|
||||
└── ...
|
||||
```
|
||||
|
||||
By default, the build output will connect to OHIF's publicly accessible PACS. If
|
||||
this is your first time setting up the OHIF Viewer, it is recommended that you
|
||||
test with these default settings. After testing, you can find instructions on
|
||||
how to configure the project for your own imaging archive below.
|
||||
|
||||
### Configuration
|
||||
|
||||
The configuration for our viewer is in the `<root>platform/viewer/public/config`
|
||||
directory. Our build process knows which configuration file to use based on the
|
||||
`APP_CONFIG` environment variable. By default, its value is
|
||||
[`config/default.js`][default-config]. The majority of the viewer's features,
|
||||
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 configuration options, check out our
|
||||
[configuration essentials guide](../configuration/index.md).
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Deploying Build Output
|
||||
|
||||
_Drag-n-drop_
|
||||
|
||||
- [Netlify: Drop](./static-assets#netlify-drop)
|
||||
|
||||
_Easy_
|
||||
|
||||
- [Surge.sh](./static-assets#surgesh)
|
||||
- [GitHub Pages](./static-assets#github-pages)
|
||||
|
||||
_Advanced_
|
||||
|
||||
- [AWS S3 + Cloudfront](./static-assets#aws-s3--cloudfront)
|
||||
- [GCP + Cloudflare](./static-assets#gcp--cloudflare)
|
||||
- [Azure](./static-assets#azure)
|
||||
|
||||
### Testing Build Output Locally
|
||||
|
||||
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:
|
||||
|
||||
```bash
|
||||
# Install http-server as a globally available package
|
||||
yarn global add http-server
|
||||
|
||||
# Change the directory to the platform/viewer
|
||||
|
||||
# Serve the files in our current directory
|
||||
# Accessible at: `http://localhost:8080`
|
||||
npx http-server ./dist
|
||||
```
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/551957266?badge=0&autopause=0&player_id=0&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
|
||||
|
||||
If you found setting up your environment and running all of these steps to be a
|
||||
bit tedious, then you are in good company. Thankfully, there are a large number
|
||||
of tools available to assist with automating tasks like building and deploying
|
||||
web application. For a starting point, check out this repository's own use of:
|
||||
|
||||
- [CircleCI][circleci]: [config.yaml][circleci-config]
|
||||
- [Netlify][netlify]: [netlify.toml][netlify.toml] |
|
||||
[build-deploy-preview.sh][build-deploy-preview.sh]
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[circleci]: https://circleci.com/gh/OHIF/Viewers
|
||||
[circleci-config]: https://github.com/OHIF/Viewers/blob/master/.circleci/config.yml
|
||||
[netlify]: https://app.netlify.com/sites/ohif/deploys
|
||||
[netlify.toml]: https://github.com/OHIF/Viewers/blob/master/netlify.toml
|
||||
[build-deploy-preview.sh]: https://github.com/OHIF/Viewers/blob/master/.netlify/build-deploy-preview.sh
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Google Cloud Healthcare
|
||||
|
||||
> Coming soon - We are working on bringing Google Cloud Healthcare to OHIF-v3
|
||||
@@ -0,0 +1,335 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
# Deployment
|
||||
|
||||
The OHIF Viewer can be embedded in other web applications via it's [packaged
|
||||
script source][viewer-npm], or served up as a stand-alone PWA ([progressive web
|
||||
application][pwa-url]) by building and hosting a collection of static assets. In
|
||||
either case, you will need to configure your instance of the Viewer so that it
|
||||
can connect to your data source (the database or PACS that provides the data
|
||||
your Viewer will display).
|
||||
|
||||
## Overview
|
||||
|
||||
Our goal is to make deployment as simple and painless as possible; however,
|
||||
there is an inherent amount of complexity in configuring and deploying web
|
||||
applications. If you find yourself a little lost, please don't hesitate to
|
||||
[reach out for help](/help)
|
||||
|
||||
## Deployment Scenarios
|
||||
|
||||
### Embedded Viewer (deprecated)
|
||||
|
||||
`OHIF-v3` has deprecated deploying the viewer as an embedded viewer the number
|
||||
of underlying libraries that run web workers are increasing for OHIF. An example
|
||||
of these libraries is OHIF's 3D rendering functionality that is provided by
|
||||
`vtk-js`.
|
||||
|
||||
### Stand-alone Viewer
|
||||
|
||||
Deploying the OHIF Viewer as a stand-alone web application provides many
|
||||
benefits, but comes at the cost of time and complexity. Some benefits include:
|
||||
|
||||
_Today:_
|
||||
|
||||
- Leverage [extensions](../platform/extensions/index.md) and
|
||||
[modes](../platform/modes/index.md) to drop-in powerful new features
|
||||
- Add routes and customize the viewer's workflow
|
||||
- Finer control over styling and whitelabeling
|
||||
|
||||
_In the future:_
|
||||
|
||||
- The ability to package the viewer for [App Store distribution][app-store]
|
||||
- Leverage `service-workers` for offline support and speed benefits from caching
|
||||
|
||||
#### Hosted Static Assets
|
||||
|
||||
At the end of the day, a production OHIF Viewer instance is a collection of
|
||||
HTML, CSS, JS, Font Files, and Images. We "build" those files from our
|
||||
`source code` with configuration specific to our project. We then make those
|
||||
files publicly accessible by hosting them on a Web Server.
|
||||
|
||||
If you have not deployed a web application before, this may be a good time to
|
||||
[reach out for help](/help), as these steps assume prior web development and
|
||||
deployment experience.
|
||||
|
||||
##### Part 1 - Build Production Assets
|
||||
|
||||
"Building", or creating, the files you will need is the same regardless of the
|
||||
web host you choose. You can find detailed instructions on how to configure and
|
||||
build the OHIF Viewer in our
|
||||
["Build for Production" guide](./build-for-production.md).
|
||||
|
||||
##### Part 2 - Host Your App
|
||||
|
||||
There are a lot of [benefits to hosting static assets][host-static-assets] over
|
||||
dynamic content. You can find instructions on how to host your build's output
|
||||
via one of these guides:
|
||||
|
||||
_Drag-n-drop_
|
||||
|
||||
- [Netlify: Drop](./static-assets.md#netlify-drop)
|
||||
|
||||
_Easy_
|
||||
|
||||
- [Surge.sh](./static-assets.md#surgesh)
|
||||
- [GitHub Pages](./static-assets.md#github-pages)
|
||||
|
||||
_Advanced_
|
||||
|
||||
- [AWS S3 + Cloudfront](./static-assets.md#aws-s3--cloudfront)
|
||||
- [GCP + Cloudflare](./static-assets.md#gcp--cloudflare)
|
||||
- [Azure](./static-assets.md#azure)
|
||||
|
||||
## Data
|
||||
|
||||
The OHIF Viewer is able to connect to any data source that implements the [DICOM
|
||||
Web Standard][dicom-web-standard]. [DICOM Web][dicom-web] refers to RESTful
|
||||
DICOM Services -- a recently standardized set of guidelines for exchanging
|
||||
medical images and imaging metadata over the internet. Not all archives fully
|
||||
support it yet, but it is gaining wider adoption.
|
||||
|
||||
### Configure Connection
|
||||
|
||||
If you have an existing archive and intend to host the OHIF Viewer at the same
|
||||
domain name as your archive, then connecting the two is as simple as following
|
||||
the steps layed out in our
|
||||
[Configuration Essentials Guide](./../configuration/index.md).
|
||||
|
||||
#### What if I don't have an imaging archive?
|
||||
|
||||
We provide some guidance on configuring a local image archive in our
|
||||
[Data Source Essentials](./../configuration/index.md#set-up-a-local-DICOM-server)
|
||||
guide. Hosting an archive remotely is a little trickier. You can check out some
|
||||
of our [advanced recipes](#recipes) for modeled setups that may work for you.
|
||||
|
||||
#### What if I intend to host the OHIF Viewer at a different domain?
|
||||
|
||||
There are two important steps to making sure this setup works:
|
||||
|
||||
1. Your Image Archive needs to be exposed, in some way, to the open web. This
|
||||
can be directly, or through a `reverse proxy`, but the Viewer needs _some
|
||||
way_ to request its data.
|
||||
2. \* Your Image Archive needs to have appropriate CORS (Cross-Origin Resource
|
||||
Sharing) Headers
|
||||
|
||||
> \* Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional
|
||||
> HTTP headers to tell a browser to let a web application running at one origin
|
||||
> (domain) have permission to access selected resources from a server at a
|
||||
> different origin. - [MDN Web Docs: Web - Http - CORS][cors]
|
||||
|
||||
Most image archives do not provide either of these features "out of the box".
|
||||
It's common to use IIS, Nginx, or Apache to route incoming requests and append
|
||||
appropriate headers. You can find an example of this setup in our
|
||||
[Nginx + Image Archive Deployment Recipe](./nginx--image-archive.md).
|
||||
|
||||
#### What if my archive doesn't support DicomWeb?
|
||||
|
||||
It's possible to supply all Study data via JSON format, in the event you do not
|
||||
have a DicomWeb endpoint. You can host all of the relevant files on any web
|
||||
accessible server (Amazon S3, Azure Blob Storage, Local file server etc.)
|
||||
|
||||
This JSON is supplied via the '?url=' query parameter. It should reference an
|
||||
endpoint that returns **application/json** formatted text.
|
||||
|
||||
If you do not have an API, you can simply return a text file containing the JSON
|
||||
from any web server.
|
||||
|
||||
You tell the OHIF viewer to use JSON by using the `dicomjson` datasource and
|
||||
appending `'?url='` query to your mode's route:
|
||||
|
||||
e.g.
|
||||
`https://my-test-ohif-server/myMode/dicomjson?url=https://my-json-server/study-uid.json`
|
||||
|
||||
The returned JSON object must contain a single root object with a 'studies'
|
||||
array.
|
||||
|
||||
You can read more about using different data sources for mode's routes
|
||||
[here](../platform/modes/routes.md#route-path)
|
||||
|
||||
_Sample JSON format:_
|
||||
|
||||
```json
|
||||
{
|
||||
"studies": [
|
||||
{
|
||||
"StudyInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.78",
|
||||
"StudyDescription": "BRAIN SELLA",
|
||||
"StudyDate": "20010108",
|
||||
"StudyTime": "120022",
|
||||
"PatientName": "MISTER^MR",
|
||||
"PatientId": "832040",
|
||||
"series": [
|
||||
{
|
||||
"SeriesDescription": "SAG T-1",
|
||||
"SeriesInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.121",
|
||||
"SeriesNumber": 2,
|
||||
"SeriesDate": "20010108",
|
||||
"SeriesTime": "120318",
|
||||
"Modality": "MR",
|
||||
"instances": [
|
||||
{
|
||||
"metadata": {
|
||||
"Columns": 512,
|
||||
"Rows": 512,
|
||||
"InstanceNumber": 3,
|
||||
"AcquisitionNumber": 0,
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 16,
|
||||
"PixelRepresentation": 1,
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelSpacing": [0.390625, 0.390625],
|
||||
"HighBit": 15,
|
||||
"ImageOrientationPatient": [0, 1, 0, 0, 0, -1],
|
||||
"ImagePositionPatient": [11.6, -92.5, 98.099998],
|
||||
"FrameOfReferenceUID": "1.2.840.113619.2.5.1762583153.223134.978956938.470",
|
||||
"ImageType": ["ORIGINAL", "PRIMARY", "OTHER"],
|
||||
"Modality": "MR",
|
||||
"SOPInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.124",
|
||||
"SeriesInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.121",
|
||||
"StudyInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.78"
|
||||
},
|
||||
"url": "dicomweb://s3.amazonaws.com/lury/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.124.dcm"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
More info on this JSON format can be found here
|
||||
[Issue #1500](https://github.com/OHIF/Viewers/issues/1500)
|
||||
|
||||
**Implementation Notes:**
|
||||
|
||||
<!-- 1. When hosting the viewer, you will also need to host a /viewer route on the server - or the browser may not be able to find the route. -->
|
||||
|
||||
1. For each instance url (dicom object) in the returned JSON, you must prefix
|
||||
the `url` with `dicomjson:` in order for the cornerstone image loader to
|
||||
retrieve it correctly. eg. `https://image-server/my-image.dcm` --->
|
||||
`dicomjson:https://image-server/my-image.dcm`
|
||||
2. The JSON format above is compatible with >= v3.7.8 of the application in `V2`
|
||||
version. Older versions of the viewer used a different JSON format. As of
|
||||
20/04/20 the public [https://viewer.ohif.org/] is a pre 3.0 version that does
|
||||
not support this format yet.
|
||||
3. The JSON format is case-sensitive. Please ensure you have matched casing with
|
||||
the naturalised Dicom format referenced in
|
||||
[Issue #1500](https://github.com/OHIF/Viewers/issues/1500).
|
||||
|
||||
_CORS Issues (Cross-Origin Resource Sharing)_
|
||||
|
||||
If you host a JSON API or Images on a different domain from the app itself,
|
||||
you will likely have CORS issues. This will also happen when testing from
|
||||
Localhost and reaching out to remote servers. Even if the domain is the same,
|
||||
different ports, subdomains or protocols (https vs http) will also cause CORS
|
||||
errors. You will to need add a configuration on each server hosting these assets
|
||||
to allow your App server origin.
|
||||
|
||||
For example:
|
||||
|
||||
Let's assume your application is hosted on `https://my-ohif-server.com`.
|
||||
|
||||
Your JSON API is hosted on `https://my-json-api.aws.com`
|
||||
|
||||
And your images are stored on Amazon S3 at `https://my-s3-bucket.aws.com`
|
||||
|
||||
When you first start your application, browsing to
|
||||
`https://my-ohif-server.com/myMode/dicomjson?url=https://my-json-api.aws.com/api/my-json-study-info.json`,
|
||||
you will likely get a CORS error in the browser console as it tries to connect
|
||||
to `https://my-json-api.aws.com`.
|
||||
|
||||
Adding a setting on the JSON server to allow the CORS origin =
|
||||
`https://my-ohif-server.com` should solve this.
|
||||
|
||||
Next, you will likely get a similar CORS error, as the browser tries to go to
|
||||
`https://my-s3-bucket.aws.com`. You will need to go to the S3 bucket
|
||||
configuration, and add a CORS setting to allow origin =
|
||||
`https://my-ohif-server.com`.
|
||||
|
||||
Essentially, whenever the application connects to a remote resource, you will
|
||||
need to add the applications url to the allowed CORS Origins on that resource.
|
||||
Adding an origin similar to https://localhost:3000 will also allow for local
|
||||
testing.
|
||||
|
||||
### Securing Your Data
|
||||
|
||||
Coming soon
|
||||
|
||||
<!--
|
||||
> Feeling lost? Securing your data is important, and it can be hard to tell if
|
||||
> you've gotten it right. Don't hesitate to work with professional auditors, or
|
||||
> [enlist help from experts](../help).
|
||||
|
||||
The OHIF Viewer can be configured to work with authorization servers that
|
||||
support one or more of the OpenID-Connect authorization flows. The Viewer finds
|
||||
it's OpenID-Connect settings on the `oidc` configuration key. You can set these
|
||||
values following the instructions laid out in the
|
||||
[Configuration Essentials Guide](./../configuration/index.md).
|
||||
|
||||
_Example OpenID-Connect Settings:_
|
||||
|
||||
```js
|
||||
window.config = {
|
||||
...
|
||||
oidc: [
|
||||
{
|
||||
// ~ REQUIRED
|
||||
// Authorization Server URL
|
||||
authority: 'http://127.0.0.1/auth/realms/ohif',
|
||||
client_id: 'ohif-viewer',
|
||||
redirect_uri: 'http://127.0.0.1/callback', // `OHIFStandaloneViewer.js`
|
||||
response_type: 'code', // "Authorization Code Flow"
|
||||
scope: 'openid', // email profile openid
|
||||
// ~ OPTIONAL
|
||||
post_logout_redirect_uri: '/logout-redirect.html',
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
You can find an example of this setup in our
|
||||
[User Account Control Deployment Recipe](./user-account-control.md).
|
||||
|
||||
#### Choosing a Flow for the Viewer
|
||||
|
||||
In general, we recommend using the "Authorization Code Flow" ( [see
|
||||
`response_type=code` here][code-flows]); however, the "Implicit Flow" ( [see
|
||||
`response_type=token` here][code-flows]) can work if additonal precautions are
|
||||
taken. If the flow you've chosen produces a JWT Token, it's validity can be used
|
||||
to secure access to your Image Archive as well.
|
||||
|
||||
-->
|
||||
|
||||
### Recipes
|
||||
|
||||
We've included a few recipes for common deployment scenarios. There are many,
|
||||
many possible configurations, so please don't feel limited to these setups.
|
||||
Please feel free to suggest or contribute your own recipes.
|
||||
|
||||
- [Build for Production](./build-for-production.md)
|
||||
- [Static](./static-assets.md)
|
||||
- [Nginx + Image Archive](./nginx--image-archive.md)
|
||||
- [User Account Control](./user-account-control.md)
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[viewer-npm]: https://www.npmjs.com/package/@ohif/viewer
|
||||
[pwa-url]: https://developers.google.com/web/progressive-web-apps/
|
||||
[static-assets-url]: https://www.maxcdn.com/one/visual-glossary/static-content/
|
||||
[app-store]: https://medium.freecodecamp.org/i-built-a-pwa-and-published-it-in-3-app-stores-heres-what-i-learned-7cb3f56daf9b
|
||||
[dicom-web-standard]: https://www.dicomstandard.org/dicomweb/
|
||||
[dicom-web]: https://en.wikipedia.org/wiki/DICOMweb
|
||||
[host-static-assets]: https://www.netlify.com/blog/2016/05/18/9-reasons-your-site-should-be-static/
|
||||
[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
[code-flows]: https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660
|
||||
[code-sandbox]: https://codesandbox.io/s/viewer-script-tag-tprch
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,273 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Nginx + Image Archive
|
||||
|
||||
> DISCLAIMER! We make no claims or guarantees of this approach's security. If in
|
||||
> doubt, enlist the help of an expert and conduct proper audits.
|
||||
|
||||
At a certain point, you may want others to have access to your instance of the
|
||||
OHIF Viewer and its medical imaging data. This post covers one of many potential
|
||||
setups that accomplish that. Please note, noticeably absent is user account
|
||||
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)
|
||||
that builds on the lessons learned here.
|
||||
|
||||
## Overview
|
||||
|
||||
Our two biggest hurdles when hosting our image archive and web client are:
|
||||
|
||||
- Risks related to exposing our PACS to the network
|
||||
- Cross-Origin Resource Sharing (CORS) requests
|
||||
|
||||
### Handling Web Requests
|
||||
|
||||
We mitigate our first issue by allowing [Nginx][nginx] to handle incoming web
|
||||
requests. Nginx is open source software for web serving, reverse proxying,
|
||||
caching, and more. It's designed for maximum performance and stability --
|
||||
allowing us to more reliably serve content than Orthanc's built-in server can.
|
||||
|
||||
More specifically, we accomplish this by using a
|
||||
[`reverse proxy`](https://en.wikipedia.org/wiki/Reverse_proxy) to retrieve
|
||||
resources from our image archive (Orthanc), and when accessing its web admin.
|
||||
|
||||
> A reverse proxy is a type of proxy server that retrieves resources on behalf
|
||||
> of a client from one or more servers. These resources are then returned to the
|
||||
> client, appearing as if they originated from the proxy server itself.
|
||||
|
||||
### CORS Issues
|
||||
|
||||
Cross-Origin Resource Sharing (CORS) is a mechanism that uses HTTP headers to
|
||||
tell a browser which web applications have permission to access selected
|
||||
resources from a server at a different origin (domain, protocol, port). IE. By
|
||||
default, a Web App located at `http://my-website.com` can't access resources
|
||||
hosted at `http://not-my-website.com`
|
||||
|
||||
We can solve this one of two ways:
|
||||
|
||||
1. Have our Image Archive located at the same domain as our Web App
|
||||
2. Add appropriate `Access-Control-Allow-*` HTTP headers
|
||||
|
||||
**This solution uses the first approach.**
|
||||
|
||||
You can read more about CORS in this Medium article: [Understanding
|
||||
CORS][understanding-cors]
|
||||
|
||||
### Diagram
|
||||
|
||||
This setup allows us to create a setup similar to the one pictured below:
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
- All web requests are routed through `nginx` on our `OpenResty` image
|
||||
- `/pacs` is a reverse proxy for `orthanc`'s `DICOM Web` endpoints
|
||||
- `/pacs-admin` is a reverse proxy for `orthanc`'s Web Admin
|
||||
- All static resources for OHIF Viewer are served up by `nginx` when a matching
|
||||
route for that resource is requested
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Requirements
|
||||
|
||||
- Docker
|
||||
- [Docker for Mac](https://docs.docker.com/docker-for-mac/)
|
||||
- [Docker for Windows](https://docs.docker.com/docker-for-windows/)
|
||||
|
||||
_Not sure if you have `docker` installed already? Try running `docker --version`
|
||||
in command prompt or terminal_
|
||||
|
||||
### Setup
|
||||
|
||||
- Navigate to `viewer` folder inside `platform`
|
||||
- then: `cd .recipes/OpenResty-Orthanc`
|
||||
- run: `docker-compose up --build`
|
||||
- Navigate to `127.0.0.1` for the viewer
|
||||
- Navigate to `127.0.0.1/pacs-admin` for uploading studies
|
||||
|
||||
|
||||
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&autopause=0&player_id=0&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
|
||||
|
||||
_Spin Things Up_
|
||||
|
||||
- Navigate to `<project-root>/docker/OpenResty-Orthanc` in your shell
|
||||
- Run `docker-compose up`
|
||||
|
||||
_Upload Your First Study_
|
||||
|
||||
- Navigate to `http://127.0.0.1/pacs-admin`
|
||||
- From the top right, select "Upload"
|
||||
- Click "Select files to upload..." (DICOM)
|
||||
- Click "Start the upload"
|
||||
- Navigate back to `http://127.0.0.1/` to view your studies in the Study List -->
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
_Exit code 137_
|
||||
|
||||
This means Docker ran out of memory. Open Docker Desktop, go to the `advanced`
|
||||
tab, and increase the amount of Memory available.
|
||||
|
||||
_Cannot create container for service X_
|
||||
|
||||
Use this one with caution: `docker system prune`
|
||||
|
||||
_X is already running_
|
||||
|
||||
Stop running all containers:
|
||||
|
||||
- Win: `docker ps -a -q | ForEach { docker stop $_ }`
|
||||
- Linux: `docker stop $(docker ps -a -q)`
|
||||
|
||||
|
||||
_Traceback (most recent call last):_
|
||||
_File "urllib3/connectionpool.py", line 670, in urlopen_
|
||||
_...._
|
||||
|
||||
Are you sure your docker is running? see explanation [here](https://github.com/docker/compose/issues/7896)
|
||||
|
||||
|
||||
### Configuration
|
||||
|
||||
After verifying that everything runs with default configuration values, you will
|
||||
likely want to update:
|
||||
|
||||
- The domain: `http://127.0.0.1`
|
||||
|
||||
#### OHIF Viewer
|
||||
|
||||
The OHIF Viewer's configuration is imported from a static `.js` file. The
|
||||
configuration we use is set to a specific file when we build the viewer, and
|
||||
determined by the env variable: `APP_CONFIG`. You can see where we set its value
|
||||
in the `dockerfile` for this solution:
|
||||
|
||||
`ENV APP_CONFIG=config/docker_openresty-orthanc.js`
|
||||
|
||||
You can find the configuration we're using here:
|
||||
`/public/config/docker_openresty-orthanc.js`
|
||||
|
||||
To rebuild the `webapp` image created by our `dockerfile` after updating the
|
||||
Viewer's configuration, you can run:
|
||||
|
||||
- `docker-compose build` OR
|
||||
- `docker-compose up --build`
|
||||
|
||||
#### Other
|
||||
|
||||
All other files are found in: `/docker/OpenResty-Orthanc/`
|
||||
|
||||
| Service | Configuration | Docs |
|
||||
| ----------------- | --------------------------------- | ------------------------------------------- |
|
||||
| OHIF Viewer | [dockerfile][dockerfile] | You're reading them now! |
|
||||
| OpenResty (Nginx) | [`/nginx.conf`][config-nginx] | [lua-resty-openidc][lua-resty-openidc-docs] |
|
||||
| Orthanc | [`/orthanc.json`][config-orthanc] | [Here][orthanc-docs] |
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Deploying to Production
|
||||
|
||||
While these configuration and docker-compose files model an environment suitable
|
||||
for production, they are not easy to deploy "as is". You can either:
|
||||
|
||||
- Manually recreate this environment and deploy built application files **OR**
|
||||
- Deploy to a cloud kubernetes provider like
|
||||
[Digital Ocean](https://www.digitalocean.com/products/kubernetes/) **OR**
|
||||
- [See a full list of cloud providers here](https://landscape.cncf.io/category=cloud&format=card-mode&grouping=category)
|
||||
- Find and follow your preferred provider's guide on setting up
|
||||
[swarms and stacks](https://docs.docker.com/get-started/)
|
||||
|
||||
### Adding SSL
|
||||
|
||||
Adding SSL registration and renewal for your domain with Let's Encrypt that
|
||||
terminates at Nginx is an incredibly important step toward securing your data.
|
||||
Here are some resources, specific to this setup, that may be helpful:
|
||||
|
||||
- [lua-resty-auto-ssl](https://github.com/GUI/lua-resty-auto-ssl)
|
||||
- [Let's Encrypt + Nginx](https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/)
|
||||
|
||||
While we terminate SSL at Nginx, it may be worth using self-signed certificates
|
||||
for communication between services.
|
||||
|
||||
- [SSL Termination for TCP Upstream Servers](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-tcp/)
|
||||
|
||||
### Use PostgresSQL w/ Orthanc
|
||||
|
||||
Orthanc can handle a large amount of data and requests, but if you find that
|
||||
requests start to slow as you add more and more studies, you may want to
|
||||
configure your Orthanc instance to use PostgresSQL. Instructions on how to do
|
||||
that can be found in the
|
||||
[`Orthanc Server Book`](http://book.orthanc-server.com/users/docker.html), under
|
||||
"PostgreSQL and Orthanc inside Docker"
|
||||
|
||||
### Improving This Guide
|
||||
|
||||
Here are some improvements this guide would benefit from, and that we would be
|
||||
more than happy to accept Pull Requests for:
|
||||
|
||||
- SSL Support
|
||||
- Complete configuration with `.env` file (or something similar)
|
||||
- Any security issues
|
||||
- One-click deploy to a cloud provider
|
||||
|
||||
## Resources
|
||||
|
||||
### Misc. Helpful Commands
|
||||
|
||||
_Check if `nginx.conf` is valid:_
|
||||
|
||||
```bash
|
||||
docker run --rm -t -a stdout --name my-openresty -v $PWD/config/:/usr/local/openresty/nginx/conf/:ro openresty/openresty:alpine-fat openresty -c /usr/local/openresty/nginx/conf/nginx.conf -t
|
||||
```
|
||||
|
||||
_Interact w/ running container:_
|
||||
|
||||
`docker exec -it CONTAINER_NAME bash`
|
||||
|
||||
_List running containers:_
|
||||
|
||||
`docker ps`
|
||||
|
||||
### Referenced Articles
|
||||
|
||||
For more documentation on the software we've chosen to use, you may find the
|
||||
following resources helpful:
|
||||
|
||||
- [Orthanc for Docker](http://book.orthanc-server.com/users/docker.html)
|
||||
- [OpenResty Guide](http://www.staticshin.com/programming/definitely-an-open-resty-guide/)
|
||||
- [Lua Ngx API](https://openresty-reference.readthedocs.io/en/latest/Lua_Nginx_API/)
|
||||
|
||||
For a different take on this setup, check out the repositories our community
|
||||
members put together:
|
||||
|
||||
- [mjstealey/ohif-orthanc-dimse-docker](https://github.com/mjstealey/ohif-orthanc-dimse-docker)
|
||||
- [trypag/ohif-orthanc-postgres-docker](https://github.com/trypag/ohif-orthanc-postgres-docker)
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- DOCS -->
|
||||
[nginx]: https://www.nginx.com/resources/glossary/nginx/
|
||||
[understanding-cors]: https://medium.com/@baphemot/understanding-cors-18ad6b478e2b
|
||||
[orthanc-docs]: http://book.orthanc-server.com/users/configuration.html#configuration
|
||||
[lua-resty-openidc-docs]: https://github.com/zmartzone/lua-resty-openidc
|
||||
<!-- SRC -->
|
||||
[dockerfile]: https://github.com/OHIF/Viewers/blob/master/platform/viewer/.recipes/OpenResty-Orthanc/dockerfile
|
||||
[config-nginx]: https://github.com/OHIF/Viewers/blob/master/platform/viewer/.recipes/OpenResty-Orthanc/config/nginx.conf
|
||||
[config-orthanc]: https://github.com/OHIF/Viewers/blob/master/platform/viewer/.recipes/OpenResty-Orthanc/config/orthanc.json
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,160 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Deploy Static Assets
|
||||
|
||||
> WARNING! All of these solutions stand-up a publicly accessible web viewer. Do
|
||||
> not hook your hosted viewer up to a sensitive source of data without
|
||||
> implementing authentication.
|
||||
|
||||
There are a lot of options for deploying static assets. Some services, like
|
||||
`netlify` and `surge.sh`, specialize in static websites. You'll notice that
|
||||
deploying with them requires much less time and effort, but comes at the cost of
|
||||
less product offerings.
|
||||
|
||||
While not required, it can simplify things to host your Web Viewer alongside
|
||||
your image archive. Services with more robust product offerings, like
|
||||
`Google Cloud`, `Microsoft's Azure`, and `Amazon Web Services (AWS)`, are able
|
||||
to accommodate this setup.
|
||||
|
||||
_Drag-n-drop_
|
||||
|
||||
- [Netlify: Drop](#netlify-drop)
|
||||
|
||||
_Easy_
|
||||
|
||||
- [Surge.sh](#surgesh)
|
||||
- [GitHub Pages](#github-pages)
|
||||
|
||||
_Advanced_
|
||||
|
||||
- [Deploy Static Assets](#deploy-static-assets)
|
||||
- [Drag-n-drop](#drag-n-drop)
|
||||
- [Netlify Drop](#netlify-drop)
|
||||
- [Easy](#easy)
|
||||
- [Surge.sh](#surgesh)
|
||||
- [GitHub Pages](#github-pages)
|
||||
- [Advanced](#advanced)
|
||||
- [AWS S3 + Cloudfront](#aws-s3--cloudfront)
|
||||
- [GCP + Cloudflare](#gcp--cloudflare)
|
||||
- [Azure](#azure)
|
||||
|
||||
## Drag-n-drop
|
||||
|
||||
### Netlify Drop
|
||||
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/551957463?badge=0&autopause=0&player_id=0&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_
|
||||
|
||||
1. https://app.netlify.com/drop
|
||||
2. Drag your `build/` folder on to the drop target
|
||||
3. ...
|
||||
4. _annnd you're done_
|
||||
|
||||
**Features:**
|
||||
|
||||
- Custom domains & HTTPS
|
||||
- Instant Git integration
|
||||
- Continuous deployment
|
||||
- Deploy previews
|
||||
- Access to add-ons
|
||||
|
||||
(Non-free tiers include identity, FaaS, Forms, etc.)
|
||||
|
||||
Learn more about [Netlify on their website](https://www.netlify.com/)
|
||||
|
||||
## Easy
|
||||
|
||||
### Surge.sh
|
||||
|
||||
> Static web publishing for Front-End Developers. Simple, single-command web
|
||||
> publishing. Publish HTML, CSS, and JS for free, without leaving the command
|
||||
> line.
|
||||
|
||||

|
||||
|
||||
_GIF demonstrating deployment with surge_
|
||||
|
||||
```shell
|
||||
# Add surge command
|
||||
yarn global add surge
|
||||
|
||||
# In the build directory
|
||||
surge
|
||||
```
|
||||
|
||||
**Features:**
|
||||
|
||||
- Free custom domain support
|
||||
- Free SSL for surge.sh subdomains
|
||||
- pushState support for single page apps
|
||||
- Custom 404.html pages
|
||||
- Barrier-free deployment through the CLI
|
||||
- Easy integration into your Grunt toolchain
|
||||
- Cross-origin resource support
|
||||
- And more…
|
||||
|
||||
Learn more about [surge.sh on their website](https://surge.sh/)
|
||||
|
||||
### GitHub Pages
|
||||
|
||||
> WARNING! While great for project sites and light use, it is not advised to use
|
||||
> GitHub Pages for production workloads. Please consider using a different
|
||||
> service for mission critical applications.
|
||||
|
||||
> Websites for you and your projects. Hosted directly from your GitHub
|
||||
> repository. Just edit, push, and your changes are live.
|
||||
|
||||
This deployment strategy makes more sense if you intend to maintain your project in
|
||||
a GitHub repository. It allows you to specify a `branch` or `folder` as the
|
||||
target for a GitHub Page's website. As you push code changes, the hosted content
|
||||
updates to reflect those changes.
|
||||
|
||||
1. Head over to GitHub.com and create a new repository, or go to an existing
|
||||
one. Click on the Settings tab.
|
||||
2. Scroll down to the GitHub Pages section. Choose the `branch` or `folder` you
|
||||
would like as the "root" of your website.
|
||||
3. Fire up a browser and go to `http://username.github.io/repository`
|
||||
|
||||
Configuring Your Site:
|
||||
|
||||
- [Setting up a custom domain](https://help.github.com/en/articles/using-a-custom-domain-with-github-pages)
|
||||
- [Setting up SSL](https://help.github.com/en/articles/securing-your-github-pages-site-with-https)
|
||||
|
||||
Learn more about [GitHub Pages on its website](https://pages.github.com/)
|
||||
|
||||
## Advanced
|
||||
|
||||
All of these options, while using providers with more service offerings,
|
||||
demonstrate how to host the viewer with their respective file storage and CDN
|
||||
offerings. While you can serve your static assets this way, if you're going
|
||||
through the trouble of using AWS/GCP/Azure, it's more likely you're doing so to
|
||||
avoid using a proxy or to simplify authentication.
|
||||
|
||||
If that is the case, check out some of our more advanced `docker` deployments
|
||||
that target these providers from the left-hand sidepanel.
|
||||
|
||||
These guides can be a bit longer and an update more frequently. To provide
|
||||
accurate documentation, we will link to each provider's own recommended steps:
|
||||
|
||||
### AWS S3 + Cloudfront
|
||||
|
||||
- [Host a Static Website](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html)
|
||||
- [Speed Up Your Website with Cloudfront](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-cloudfront-walkthrough.html)
|
||||
|
||||
### GCP + Cloudflare
|
||||
|
||||
- [Things to Know Before Getting Started](https://code.luasoftware.com/tutorials/google-cloud-storage/things-to-know-before-hosting-static-website-on-google-cloud-storage/)
|
||||
- [Hosting a Static Website on GCP](https://cloud.google.com/storage/docs/hosting-static-website)
|
||||
|
||||
### Azure
|
||||
|
||||
- [Host a Static Website](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website)
|
||||
- [Add SSL Support](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-https-custom-domain-cdn)
|
||||
- [Configure a Custom Domain](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-custom-domain-name)
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# User Account Control
|
||||
|
||||
> Coming soon - We are working on bringing the User Account Control to OHIF-v3
|
||||
Reference in new issue
Block a user