init
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Development",
|
||||
"position": 5
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
sidebar_label: Architecture
|
||||
---
|
||||
|
||||
# Architecture
|
||||
|
||||
In order to achieve a platform that can support various workflows and be
|
||||
extensible for the foreseeable future we went through extensive planning of
|
||||
possible use cases and decided to significantly change and improve the
|
||||
architecture.
|
||||
|
||||
Below, we aim to demystify that complexity by providing insight into how
|
||||
`OHIF Platform` is architected, and the role each of its dependent libraries
|
||||
plays.
|
||||
|
||||
## Overview
|
||||
|
||||
The [OHIF Medical Image Viewing Platform][viewers-project] is maintained as a
|
||||
[`monorepo`][monorepo]. This means that this repository, instead of containing a
|
||||
single project, contains many projects. If you explore our project structure,
|
||||
you'll see the following:
|
||||
|
||||
```bash
|
||||
│
|
||||
├── extensions
|
||||
│ ├── default # default functionalities
|
||||
│ ├── cornerstone # 2D/3D images w/ Cornerstonejs
|
||||
│ ├── cornerstone-dicom-sr # Structured reports
|
||||
│ ├── measurement-tracking # measurement tracking
|
||||
│ └── dicom-pdf # View DICOM wrapped PDFs in viewport
|
||||
| # and many more ...
|
||||
│
|
||||
├── modes
|
||||
│ └── longitudinal # longitudinal measurement tracking mode
|
||||
| └── basic-dev-mode # basic viewer with Cornerstone (a developer focused mode)
|
||||
| # and many more
|
||||
│
|
||||
├── platform
|
||||
│ ├── core # Business Logic
|
||||
│ ├── i18n # Internationalization Support
|
||||
│ ├── ui # React component library
|
||||
│ └── app # Connects platform and extension projects
|
||||
│
|
||||
├── ... # misc. shared configuration
|
||||
├── lerna.json # MonoRepo (Lerna) settings
|
||||
├── package.json # Shared devDependencies and commands
|
||||
└── README.md
|
||||
```
|
||||
|
||||
OHIF v3 is composed of the following components, described in detail in further
|
||||
sections:
|
||||
|
||||
- `@ohif/app`: The core framework that controls extension registration, mode
|
||||
composition and routing.
|
||||
- `@ohif/core`: A library of useful and reusable medical imaging functionality
|
||||
for the web.
|
||||
- `@ohif/ui`: A library of reusable components to build OHIF-styled applications
|
||||
with.
|
||||
- `Extensions`: A set of building blocks for building applications. The OHIF org
|
||||
maintains a few core libraries.
|
||||
- `Modes`: Configuration objects that tell @ohif/app how to compose
|
||||
extensions to build applications on different routes of the platform.
|
||||
|
||||
## Extensions
|
||||
|
||||
The `extensions` directory contains many packages that provide essential
|
||||
functionalities such as rendering, study/series browsers, measurement tracking
|
||||
that modes can consume to enable a certain workflow. Extensions have had their
|
||||
behavior changed in `OHIF-v3` and their api is expanded. In summary:
|
||||
|
||||
> In `OHIF-v3`, extensions no longer automatically hook themselves to the app.
|
||||
> Now, registering an extension makes its component available to `modes` that
|
||||
> wish to use them. Basically, extensions in `OHIF-v3` are **building blocks**
|
||||
> for building applications.
|
||||
|
||||
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](../platform/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!](../platform/extensions/index.md)
|
||||
|
||||
## Modes
|
||||
|
||||
The `modes` directory contains workflows that can be registered with OHIF within
|
||||
certain `routes`. The mode will get used once the user opens the viewer on the
|
||||
registered route.
|
||||
|
||||
OHIF extensions were designed to provide certain core functionalities for
|
||||
building your viewer. However, often in medical imaging we face a specific use
|
||||
case in which we are using some core functionalities, adding our specific UI,
|
||||
and use it in our workflows. Previously, to achieve this you had to create an
|
||||
extension to add have such feature. `OHIF-v3` introduces `Modes` to enable
|
||||
building such workflows by re-using the core functionalities from the
|
||||
extensions.
|
||||
|
||||
Some common workflows may include:
|
||||
|
||||
- Measurement tracking for lesions
|
||||
- Segmentation of brain abnormalities
|
||||
- AI probe mode for detecting prostate cancer
|
||||
|
||||
In the mentioned modes above, they will share the same core rendering module
|
||||
that the `default` extension provides. However, segmentation mode will require
|
||||
segmentation tools which is not needed for the other two. As you can see, modes
|
||||
are a layer on top of extensions, that you can configure in order to achieve
|
||||
certain workflows.
|
||||
|
||||
To summarize the difference between extensions and modes in `OHIF-v3` and
|
||||
extensions in `OHIF-v2`
|
||||
|
||||
> - `Modes` are configuration objects that tell _@ohif/app_ how to compose
|
||||
> extensions to build applications on different routes of the platform.
|
||||
> - 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!](../platform/modes/index.md)
|
||||
|
||||
## Platform
|
||||
|
||||
### `@ohif/app`
|
||||
|
||||
This library is the core library which consumes modes and extensions and builds
|
||||
an application. Extensions can be passed in as app configuration and will be
|
||||
consumed and initialized at the appropriate time by the application. Upon
|
||||
initialization the viewer will consume extensions and modes and build up the
|
||||
route desired, these can then be accessed via the study list, or directly via
|
||||
url parameters.
|
||||
|
||||
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.
|
||||
|
||||
Future ideas for this framework involve only adding modes and fetching the
|
||||
required extension versions at either runtime or build time, but this decision
|
||||
is still up for discussion.
|
||||
|
||||
### `@ohif/core`
|
||||
|
||||
OHIF core is a carefully maintained and tested set of web-based medical imaging
|
||||
functions and classes. This library includes managers and services used from
|
||||
within the viewer app.
|
||||
|
||||
OHIF core is largely similar to the @ohif/core library in v2, however a lot of
|
||||
logic has been moved to extensions: however all logic about DICOMWeb and other
|
||||
data fetching mechanisms have been pulled out, as these now live in extensions,
|
||||
described later.
|
||||
|
||||
### `@ohif/ui`
|
||||
|
||||
Firstly, a large time-consumer/barrier for entry we discovered was building new
|
||||
UI in a timely manner that fit OHIF’s theme. For this reason we have built a new
|
||||
UI component library which contains all the components one needs to build their
|
||||
own viewer.
|
||||
|
||||
These components are presentational only, so you can reuse them with whatever
|
||||
logic you desire. As the components are presentational, you may swap out
|
||||
@ohif/ui for a custom UI library with conforming API if you wish to white label
|
||||
the viewer. The UI library is here to make development easier and quicker, but
|
||||
it is not mandatory for extension components to use.
|
||||
|
||||
[Check out our component library!](https://ui.ohif.org/)
|
||||
|
||||
## Overview of the architecture
|
||||
|
||||
OHIF-v3 architecture can be seen in the following figure. We will explore each
|
||||
piece in more detail.
|
||||
|
||||

|
||||
|
||||
## Common Questions
|
||||
|
||||
> Can I create my own Viewer using Vue.js or Angular.js?
|
||||
|
||||
You can, but you will not be able to leverage as much of the existing code and
|
||||
components. `@ohif/core` could still be used for business logic, and to provide
|
||||
a model for extensions. `@ohif/ui` would then become a guide for the components
|
||||
you would need to recreate.
|
||||
|
||||
> When I want to implement a functionality, should it be in the mode or in an
|
||||
> extension?
|
||||
|
||||
This is a great question. Modes are designed to consume extensions, so you
|
||||
should implement your functionality in one of the modules of your new extension,
|
||||
and let the mode consume it. This way, in the future, if you needed another mode
|
||||
that utilizes the same functionality, you can easily hook the extension to the
|
||||
new mode as well.
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[monorepo]: https://github.com/OHIF/Viewers/issues/768
|
||||
[viewers-project]: https://github.com/OHIF/Viewers
|
||||
[viewer-npm]: https://www.npmjs.com/package/@ohif/app
|
||||
[pwa]: https://developers.google.com/web/progressive-web-apps/
|
||||
[configuration]: ../configuration/index.md
|
||||
[extensions]: ../platform/extensions/index.md
|
||||
[core-github]: https://github.com/OHIF/viewers/platform/core
|
||||
[ui-github]: https://github.com/OHIF/Viewers/tree/master/platform/ui
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
sidebar_label: Continuous Integration
|
||||
---
|
||||
|
||||
# Continuous Integration (CI)
|
||||
|
||||
This repository uses `CircleCI` and `Netlify` for Continuous integration.
|
||||
|
||||
## Deploy Previews
|
||||
|
||||
[Netlify Deploy previews][deploy-previews] are generated for every pull request.
|
||||
They allow pull request authors and reviewers to "Preview" the OHIF Viewer as if
|
||||
the changes had been merged.
|
||||
|
||||
Deploy previews can be configured by modifying the `netlify.toml` file in the
|
||||
root of the repository. Some additional scripts/assets for netlify are included
|
||||
in the root `.netlify` directory.
|
||||
|
||||
## Workflows
|
||||
|
||||
[CircleCI Workflows][circleci-workflows] are a set of rules for defining a
|
||||
collection of jobs and their run order. They are self-documenting and their
|
||||
configuration can be found in our CircleCI configuration file:
|
||||
`.circleci/config.yml`.
|
||||
|
||||
### Workflow: PR_CHECKS
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
### Workflow: PR_OPTIONAL_DOCKER_PUBLISH
|
||||
|
||||
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`.
|
||||
|
||||

|
||||
|
||||
> 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,
|
||||
> merge the changes to a short-lived `feature/` branch on `upstream`
|
||||
|
||||
### Workflow: DEPLOY
|
||||
|
||||
The DEPLOY workflow deploys the OHIF Viewer when changes are merged to master.
|
||||
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.
|
||||
|
||||

|
||||
|
||||
| Environment | Description | URL |
|
||||
| ----------- | ---------------------------------------------------------------------------------- | --------------------------------------------- |
|
||||
| Development | Always reflects latest changes on `master` branch. | [Netlify][netlify-dev] / [OHIF][ohif-dev] |
|
||||
| Staging | For manual testing before promotion to prod. Keeps development workflow unblocked. | [Netlify][netlify-stage] / [OHIF][ohif-stage] |
|
||||
| Production | Stable, tested, updated less frequently. | [Netlify][netlify-prod] / [OHIF][ohif-prod] |
|
||||
|
||||
### Workflow: RELEASE
|
||||
|
||||
The RELEASE workflow publishes our `npm` packages, updated documentation, and
|
||||
`docker` image when changes are merged to master. `Lerna` and "Semantic Commit
|
||||
Syntax" are used to independently version and publish the many packages in our
|
||||
monorepository. If a new version is cut/released, a Docker image is created.
|
||||
Documentation is generated with `gitbook` and pushed to our `gh-pages` branch.
|
||||
GitHub hosts the `gh-pages` branch with GitHub Pages.
|
||||
|
||||
- Platform Packages: https://github.com/ohif/viewers/#platform
|
||||
- Extension Packages: https://github.com/ohif/viewers/#extensions
|
||||
- Documentation: https://docs.ohif.org/
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
LINKS
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[deploy-previews]: https://www.netlify.com/blog/2016/07/20/introducing-deploy-previews-in-netlify/
|
||||
[circleci-workflows]: https://circleci.com/docs/2.0/workflows/
|
||||
[netlify-dev]: https://ohif-dev.netlify.com
|
||||
[netlify-stage]: https://ohif-stage.netlify.com
|
||||
[netlify-prod]: https://ohif-prod.netlify.com
|
||||
[ohif-dev]: https://viewer-dev.ohif.org
|
||||
[ohif-stage]: https://viewer-stage.ohif.org
|
||||
[ohif-prod]: https://viewer-prod.ohif.org
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,152 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
sidebar_label: Contributing
|
||||
---
|
||||
|
||||
# Contributing
|
||||
|
||||
## How can I help?
|
||||
|
||||
Fork the repository, make your change and submit a pull request. If you would
|
||||
like to discuss the changes you intend to make to clarify where or how they
|
||||
should be implemented, please don't hesitate to create a new issue. At a
|
||||
minimum, you may want to read the following documentation:
|
||||
|
||||
- [Getting Started](/development/getting-started.md)
|
||||
- [Architecture](./architecture.md)
|
||||
|
||||
Pull requests that are:
|
||||
|
||||
- Small
|
||||
- [Well tested](./testing.md)
|
||||
- Decoupled
|
||||
|
||||
Are much more likely to get reviewed and merged in a timely manner.
|
||||
|
||||
## When changes impact multiple repositories
|
||||
|
||||
While this can be tricky, we've tried to reduce how often this situation crops
|
||||
up this with our [recent switch to a monorepo][monorepo]. Our maintained
|
||||
extensions, ui components, internationalization library, and business logic can
|
||||
all be developed by simply running `yarn run dev` from the repository root.
|
||||
|
||||
Testing the viewer with locally developed, unpublished package changes from a
|
||||
package outside of the monorepo is most common with extension development. Let's
|
||||
demonstrate how to accomplish this with two commonly forked extension
|
||||
dependencies:
|
||||
|
||||
### `cornerstone-tools`
|
||||
|
||||
On your local file system:
|
||||
|
||||
```bash title="/my-projects/"
|
||||
├── cornerstonejs/cornerstone-tools
|
||||
└── ohif/viewers
|
||||
```
|
||||
|
||||
- Open a terminal/shell
|
||||
- Navigate to `cornerstonejs/cornerstone-tools`
|
||||
- `yarn install`
|
||||
- [`yarn link`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run dev`
|
||||
|
||||
* Open a new terminal/shell
|
||||
* Navigate to `ohif/viewers` (the root of ohif project)
|
||||
- `yarn install`
|
||||
- [`yarn link cornerstone-tools`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run dev`
|
||||
|
||||
As you make changed to `cornerstone-tools`, and it's output is rebuilt, you
|
||||
should see the following behavior:
|
||||
|
||||

|
||||
|
||||
If you wish to stop using your local package, run the following commands in the
|
||||
`ohif/viewers` repository root:
|
||||
|
||||
- `yarn unlink cornerstone-tools`
|
||||
- `yarn install --force`
|
||||
|
||||
<!--
|
||||
### `react-vtkjs-viewport`
|
||||
|
||||
On your local file system:
|
||||
|
||||
```bash
|
||||
# code/my-projects/
|
||||
.
|
||||
├── ohif/react-vtkjs-viewport
|
||||
└── ohif/viewers
|
||||
```
|
||||
|
||||
- Open a terminal/shell
|
||||
- Navigate to `ohif/react-vtkjs-viewport`
|
||||
- `yarn install`
|
||||
- [`yarn link`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run start`
|
||||
- Open a new terminal/shell
|
||||
- Navigate to `ohif/viewers`.
|
||||
- `yarn install`
|
||||
- [`yarn link react-vtkjs-viewport`](https://yarnpkg.com/en/docs/cli/link)
|
||||
- `yarn run dev` -->
|
||||
|
||||
#### Other linkage notes
|
||||
|
||||
We're still working out some of the kinks with local package development as
|
||||
there are a lot of factors that can influence the behavior of our development
|
||||
server and bundler. If you encounter issues not addressed here, please don't
|
||||
hesitate to reach out on GitHub.
|
||||
|
||||
Sometimes you might encounter a situation where the linking doesn't work as
|
||||
expected. This might happen when there are multiple linked packages with the
|
||||
same name. You can [remove][unlink] the linked packages inside yarn and try
|
||||
again.
|
||||
|
||||
## Any guidance on submitting changes?
|
||||
|
||||
While we do appreciate code contributions, triaging and integrating contributed
|
||||
code changes can be very time consuming. Please consider the following tips when
|
||||
working on your pull requests:
|
||||
|
||||
- Functionality is appropriate for the repository. Consider creating a GitHub
|
||||
issue to discuss your suggested changes.
|
||||
- The scope of the pull request is not too large. Please consider separate pull
|
||||
requests for each feature as big pull requests are very time consuming to
|
||||
understand.
|
||||
|
||||
We will provide feedback on your pull requests as soon as possible. Following
|
||||
the tips above will help ensure your changes are reviewed.
|
||||
|
||||
<!-- ## Testing contribution pull requests
|
||||
|
||||
OHIF uses [netlify](https://www.netlify.com/) so that pull requests are
|
||||
autogenerated and available for testing.
|
||||
|
||||
For example, [this url][example-url] allows you to test [pull request 237, the
|
||||
request that created this FAQ entry,][pr-237] using data pulled from Amazon S3.
|
||||
|
||||
Replacing the number 237 in the link below with your pull request number should
|
||||
let you test it as well and you can use this link for discussions on github
|
||||
without requiring reviewers to download and build your branch.
|
||||
|
||||
```bash
|
||||
https://deploy-preview-237--ohif.netlify.com/viewer/?url=https://s3.eu-central-1.amazonaws.com/ohif-viewer/sampleDICOM.json
|
||||
```
|
||||
|
||||
If you have made a documentation change, a link like this will let you preview
|
||||
the gitbook generated by the pull request:
|
||||
|
||||
```bash
|
||||
https://deploy-preview-237--ohif.netlify.com/contributing.html
|
||||
``` -->
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[example-url]: https://deploy-preview-237--ohif.netlify.com/viewer/?url=https://s3.eu-central-1.amazonaws.com/ohif-viewer/sampleDICOM.json
|
||||
[pr-237]: https://github.com/OHIF/Viewers/pull/237
|
||||
[monorepo]: https://github.com/OHIF/Viewers/issues/768
|
||||
[unlink]: https://stackoverflow.com/questions/58459698/is-there-a-command-to-unlink-all-yarn-packages-yarn-unlink-all
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,132 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
sidebar_label: Getting Started
|
||||
---
|
||||
|
||||
# Getting Started
|
||||
|
||||
## Setup
|
||||
|
||||
### Fork & Clone
|
||||
|
||||
If you intend to contribute back changes, or if you would like to pull updates
|
||||
we make to the OHIF Viewer, then follow these steps:
|
||||
|
||||
- [Fork][fork-a-repo] the [OHIF/Viewers][ohif-viewers-repo] repository
|
||||
- [Create a local clone][clone-a-repo] of your fork
|
||||
- `git clone https://github.com/YOUR-USERNAME/Viewers`
|
||||
- Add OHIF/Viewers as a [remote repository][add-remote-repo] labeled `upstream`
|
||||
- Navigate to the cloned project's directory
|
||||
- `git remote add upstream https://github.com/OHIF/Viewers.git`
|
||||
|
||||
With this setup, you can now [sync your fork][sync-changes] to keep it
|
||||
up-to-date with the upstream (original) repository. This is called a "Triangular
|
||||
Workflow" and is common for Open Source projects. The GitHub blog has a [good
|
||||
graphic that illustrates this setup][triangular-workflow].
|
||||
|
||||
|
||||
### Private
|
||||
|
||||
Alternatively, if you intend to use the OHIF Viewer as a starting point, and you
|
||||
aren't as concerned with syncing updates, then follow these steps:
|
||||
|
||||
1. Navigate to the [OHIF/Viewers][ohif-viewers] repository
|
||||
2. Click `Clone or download`, and then `Download ZIP`
|
||||
3. Use the contents of the `.zip` file as a starting point for your viewer
|
||||
|
||||
> NOTE: It is still possible to sync changes using this approach. However,
|
||||
> submitting pull requests for fixes and features are best done with the
|
||||
> separate, forked repository setup described in "Fork & Clone"
|
||||
|
||||
## Developing
|
||||
|
||||
|
||||
### Branches
|
||||
|
||||
#### `master` branch - The latest dev (beta) release
|
||||
|
||||
- `master` - The latest dev release
|
||||
|
||||
This is typically where the latest development happens. Code that is in the master branch has passed code reviews and automated tests, but it may not be deemed ready for production. This branch usually contains the most recent changes and features being worked on by the development team. It's often the starting point for creating feature branches (where new features are developed) and hotfix branches (for urgent fixes).
|
||||
|
||||
Each package is tagged with beta version numbers, and published to npm such as `@ohif/ui@3.6.0-beta.1`
|
||||
|
||||
### `release/*` branches - The latest stable releases
|
||||
Once the `master` branch code reaches a stable, release-ready state, we conduct a comprehensive code review and QA testing. Upon approval, we create a new release branch from `master`. These branches represent the latest stable version considered ready for production.
|
||||
|
||||
For example, `release/3.5` is the branch for version 3.5.0, and `release/3.6` is for version 3.6.0. After each release, we wait a few days to ensure no critical bugs. If any are found, we fix them in the release branch and create a new release with a minor version bump, e.g., 3.5.1 in the `release/3.5` branch.
|
||||
|
||||
Each package is tagged with version numbers and published to npm, such as `@ohif/ui@3.5.0`. Note that `master` is always ahead of the `release` branch. We publish docker builds for both beta and stable releases.
|
||||
|
||||
Here is a schematic representation of our development workflow:
|
||||
|
||||
|
||||
|
||||
|
||||
### Requirements
|
||||
|
||||
- [Node.js & NPM](https://nodejs.org/en/)
|
||||
- [Yarn](https://yarnpkg.com/en/)
|
||||
- Yarn workspaces should be enabled:
|
||||
- `yarn config set workspaces-experimental true`
|
||||
|
||||
### Kick the tires
|
||||
|
||||
Navigate to the root of the project's directory in your terminal and run the
|
||||
following commands:
|
||||
|
||||
```bash
|
||||
# Restore dependencies
|
||||
yarn install
|
||||
|
||||
# Start local development server
|
||||
yarn run dev
|
||||
```
|
||||
|
||||
You should see the following output:
|
||||
|
||||
```bash
|
||||
@ohif/app: i 「wds」: Project is running at http://localhost:3000/
|
||||
@ohif/app: i 「wds」: webpack output is served from /
|
||||
@ohif/app: i 「wds」: Content not from webpack is served from D:\code\ohif\Viewers\platform\viewer
|
||||
@ohif/app: i 「wds」: 404s will fallback to /index.html
|
||||
|
||||
# And a list of all generated files
|
||||
```
|
||||
|
||||
### 🎉 Celebrate 🎉
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/843233770?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>
|
||||
|
||||
### Building for Production
|
||||
|
||||
> More comprehensive guides for building and publishing can be found in our
|
||||
> [deployment docs](./../deployment/index.md)
|
||||
|
||||
```bash
|
||||
# Build static assets to host a PWA
|
||||
yarn run build
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- If you receive a _"No Studies Found"_ message and do not see your studies, try
|
||||
changing the Study Date filters to a wider range.
|
||||
- If you see a 'Loading' message which never resolves, check your browser's
|
||||
JavaScript console inside the Developer Tools to identify any errors.
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[fork-a-repo]: https://help.github.com/en/articles/fork-a-repo
|
||||
[clone-a-repo]: https://help.github.com/en/articles/fork-a-repo#step-2-create-a-local-clone-of-your-fork
|
||||
[add-remote-repo]: https://help.github.com/en/articles/fork-a-repo#step-3-configure-git-to-sync-your-fork-with-the-original-spoon-knife-repository
|
||||
[sync-changes]: https://help.github.com/en/articles/syncing-a-fork
|
||||
[triangular-workflow]: https://github.blog/2015-07-29-git-2-5-including-multiple-worktrees-and-triangular-workflows/#improved-support-for-triangular-workflows
|
||||
[ohif-viewers-repo]: https://github.com/OHIF/Viewers/
|
||||
[ohif-viewers]: https://github.com/OHIF/Viewers
|
||||
<!-- prettier-ignore-end -->
|
||||
62
platform/docs/versioned_docs/version-3.8/development/link.md
Normal file
62
platform/docs/versioned_docs/version-3.8/development/link.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
sidebar_position: 9
|
||||
sidebar_label: Local Linking
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
Local linking allows you to develop and test a library in the context of an application before it's published or when you encounter
|
||||
a bug that you suspect is related to a library. With Yarn, this can be achieved through the yarn link command.
|
||||
|
||||
The general procedure is as follows:
|
||||
|
||||
|
||||
Link the Library:
|
||||
|
||||
```sh
|
||||
cd /path/to/library
|
||||
yarn link
|
||||
```
|
||||
|
||||
This command will create a symlink in a global directory for the library.
|
||||
|
||||
|
||||
Link to the Application:
|
||||
|
||||
```sh
|
||||
cd /path/to/application
|
||||
yarn link "library-name"
|
||||
```
|
||||
|
||||
Creates a symlink from the global directory to the application's node_modules.
|
||||
|
||||
|
||||
# Tutorial for linking Cornerstone3D to OHIF
|
||||
|
||||
Below we demonstrate how to link Cornerstone3D to OHIF Viewer. This is useful for testing and debugging Cornerstone3D in the context of OHIF Viewer.
|
||||
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/849096279?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>
|
||||
|
||||
::tip
|
||||
Since `@cornerstonejs/tools` depends on `@cornerstonejs/core`, if you need the changes
|
||||
you made in `@cornerstonejs/core` to be reflected in `@cornerstonejs/tools`, you need to
|
||||
also link `@cornerstonejs/core` to `@cornerstonejs/tools`.
|
||||
|
||||
```sh
|
||||
cd /path/to/cornerstonejs-core
|
||||
# for the core
|
||||
yarn link
|
||||
|
||||
cd /path/to/cornerstonejs-tools
|
||||
yarn link "@cornerstonejs/core"
|
||||
|
||||
# for the tools
|
||||
yarn link
|
||||
|
||||
# inside OHIF
|
||||
cd /path/to/OHIFViewer
|
||||
yarn link "@cornerstonejs/core"
|
||||
yarn link "@cornerstonejs/tools"
|
||||
```
|
||||
312
platform/docs/versioned_docs/version-3.8/development/ohif-cli.md
Normal file
312
platform/docs/versioned_docs/version-3.8/development/ohif-cli.md
Normal file
@@ -0,0 +1,312 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
sidebar_label: OHIF CLI
|
||||
---
|
||||
|
||||
# OHIF Command Line Interface
|
||||
|
||||
OHIF-v3 architecture has been re-designed 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.
|
||||
Now, the question is _how to create/remove/install/uninstall an extension and/or
|
||||
mode?_
|
||||
|
||||
You can use the `cli` script that comes with the OHIF monorepo to achieve these
|
||||
goals.
|
||||
|
||||
:::note Info
|
||||
In the long-term, we envision our `cli` tool to be a separate installable
|
||||
package that you can invoke anywhere on your local system to achieve the same
|
||||
goals. In the meantime, `cli` will remain as part of the OHIF monorepo and needs
|
||||
to be invoked using the `yarn` command.
|
||||
:::
|
||||
|
||||
|
||||
## CLI Installation
|
||||
|
||||
You don't need to install the `cli` currently. You can use `yarn` to invoke its
|
||||
commands.
|
||||
|
||||
## Commands
|
||||
|
||||
:::note Important
|
||||
All commands should run from the root of the monorepo.
|
||||
:::
|
||||
|
||||
|
||||
There are various commands that can be used to interact with the OHIF-v3 CLI. If
|
||||
you run the following command, you will see a list of available commands.
|
||||
|
||||
```
|
||||
yarn run cli --help
|
||||
```
|
||||
|
||||
which will output
|
||||
|
||||
```
|
||||
OHIF CLI
|
||||
|
||||
Options:
|
||||
-V, --version output the version number
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
create-extension Create a new template extension
|
||||
create-mode Create a new template Mode
|
||||
add-extension <packageName> [version] Adds an ohif extension
|
||||
remove-extension <packageName> removes an ohif extension
|
||||
add-mode <packageName> [version] Removes an ohif mode
|
||||
remove-mode <packageName> Removes an ohif mode
|
||||
link-extension <packageDir> Links a local OHIF extension to the Viewer to be used for development
|
||||
unlink-extension <extensionName> Unlinks a local OHIF extension from the Viewer
|
||||
link-mode <packageDir> Links a local OHIF mode to the Viewer to be used for development
|
||||
unlink-mode <extensionName> Unlinks a local OHIF mode from the Viewer
|
||||
list List Added Extensions and Modes
|
||||
search [options] Search NPM for the list of Modes and Extensions
|
||||
help [command] display help for command
|
||||
```
|
||||
|
||||
As seen there are commands for you such as: `create-extension`, `create-mode`,
|
||||
`add-extension`, `remove-extension`, `add-mode`, `remove-mode`,
|
||||
`link-extension`, `unlink-extension`, `link-mode`, `unlink-mode`, `list`,
|
||||
`search`, and `help`. Here we will go through each of the commands and describe
|
||||
them.
|
||||
|
||||
### create-mode
|
||||
|
||||
If you need to create a new mode, you can use the `create-mode` command. This
|
||||
command will create a new mode template in the directory that you specify.
|
||||
The command will ask you couple of information/questions in order
|
||||
to properly create the mode metadata in the `package.json` file.
|
||||
|
||||
```bash
|
||||
yarn run cli create-mode
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center',}}>
|
||||
|
||||

|
||||
|
||||
|
||||
</div>
|
||||
|
||||
Note 1: Some questions have a default answer, which is indicated inside the
|
||||
parenthesis. If you don't want to answer the question, just hit enter. It will
|
||||
use the default answer.
|
||||
|
||||
Note 2: As you see in the questions, you can initiate a git repository for the
|
||||
new mode right away by answering `Y` (default) to the question.
|
||||
|
||||
Note 3: Finally, as indicated by the green lines at the end, `create-mode` command only
|
||||
create the mode template. You will need to link the mode to the Viewer in order
|
||||
to use it. See the [`link-mode`](#link-mode) command.
|
||||
|
||||
If we take a look at the directory that we created, we will see the following
|
||||
files:
|
||||
|
||||
<div style={{maxWidth:"500px"}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### create-extension
|
||||
|
||||
Similar to the `create-mode` command, you can use the `create-extension`
|
||||
command to create a new extension template. This command will create a new
|
||||
extension template in the directory that you specify the path.
|
||||
|
||||
```bash
|
||||
yarn run cli create-extension
|
||||
```
|
||||
|
||||
|
||||
Note: again similar to the `create-extension` command, you need to manually link
|
||||
the extension to the Viewer in order to use it. See the
|
||||
[`link-mode`](#link-mode) command.
|
||||
|
||||
|
||||
### link-extension
|
||||
|
||||
`link-extension` command will link a local OHIF extension to the Viewer. This
|
||||
command will utilize `yarn link` to achieve so.
|
||||
|
||||
```bash
|
||||
yarn run cli link-extension <extensionDir>
|
||||
```
|
||||
|
||||
### unlink-extension
|
||||
|
||||
There might be situations where you want to unlink an extension from the Viewer
|
||||
after some developments. `unlink-extension` command will do so.
|
||||
|
||||
```bash
|
||||
ohif-cli unlink-extension <extensionName>
|
||||
```
|
||||
|
||||
|
||||
|
||||
### link-mode
|
||||
|
||||
Similar to the `link-extension` command, `link-mode` command will link a local
|
||||
OHIF mode to the Viewer.
|
||||
|
||||
```bash
|
||||
yarn run cli link-mode <modeDir>
|
||||
```
|
||||
|
||||
### unlink-mode
|
||||
|
||||
Similar to the `unlink-extension` command, `unlink-mode` command will unlink a
|
||||
local OHIF mode from the Viewer.
|
||||
|
||||
```bash
|
||||
ohif-cli unlink-mode <modeName>
|
||||
```
|
||||
|
||||
### add-mode
|
||||
|
||||
OHIF is a modular viewer. This means that you can install (add) different modes
|
||||
to the viewer if they are published online . `add-mode` command will add a new mode to
|
||||
the viewer. It will look for the mode in the NPM registry and installs it. This
|
||||
command will also add the extension dependencies that the mode relies on to the
|
||||
Viewer (if specified in the peerDependencies section of the package.json).
|
||||
|
||||
:::note Important
|
||||
`cli` will validate the npm package before adding it to the Viewer. An OHIF mode
|
||||
should have `ohif-mode` as one of its keywords.
|
||||
:::
|
||||
|
||||
Note: If you don't specify the version, the latest version will be used.
|
||||
|
||||
```bash
|
||||
yarn run cli add-mode <packageName> [version]
|
||||
```
|
||||
|
||||
For instance `@ohif-test/mode-clock` is an example OHIF mode that we have
|
||||
published to NPM. This mode basically has a panel that shows the clock :)
|
||||
|
||||
We can add this mode to the Viewer by running the following command:
|
||||
|
||||
```bash
|
||||
yarn run cli add-mode @ohif-test/mode-clock
|
||||
```
|
||||
|
||||
After installation, the Viewer has a new mode!
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
Note: If the mode has an extension peerDependency (in this case @ohif-test/extension-clock),
|
||||
`cli` will automatically add the extension to the Viewer too.
|
||||
|
||||
The result
|
||||
|
||||

|
||||

|
||||
|
||||
### add-extension
|
||||
|
||||
This command will add an OHIF extension to the Viewer. It will look for the
|
||||
extension in the NPM registry and install it.
|
||||
|
||||
```bash
|
||||
yarn run cli add-extension <packageName> [version]
|
||||
```
|
||||
|
||||
|
||||
### remove-mode
|
||||
|
||||
This command will remove the mode from the Viewer and also remove the extension
|
||||
dependencies that the mode relies on from the Viewer.
|
||||
|
||||
```bash
|
||||
yarn run cli remove-mode <packageName>
|
||||
```
|
||||
|
||||
|
||||
### remove-extension
|
||||
|
||||
Similar to the `remove-mode` command, this command will remove the extension
|
||||
from the Viewer.
|
||||
|
||||
```bash
|
||||
yarn run cli remove-extension <packageName>
|
||||
```
|
||||
|
||||
### list
|
||||
|
||||
`list` command will list all the installed extensions and modes in
|
||||
the Viewer. It uses the `PluginConfig.json` file to list the installed
|
||||
extensions and modes.
|
||||
|
||||
```bash
|
||||
yarn run cli list
|
||||
```
|
||||
|
||||
an output would look like this:
|
||||
|
||||
<div style={{maxWidth:"500px"}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
### search
|
||||
|
||||
Using `search` command, you can search for OHIF extensions and modes
|
||||
in the NPM registry. This tool can accept a `--verbose` flag to show more
|
||||
information about the results.
|
||||
|
||||
```bash
|
||||
yarn run cli search [--verbose]
|
||||
```
|
||||
|
||||
<div style={{maxWidth:"600px"}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
with the verbose flag `ohif-cli search --verbose` you will achieve the following
|
||||
output:
|
||||
|
||||
<div style={{maxWidth:"600px"}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## PluginConfig.json
|
||||
|
||||
To make all the above commands work, we have created a new file called `PluginConfig.json` which contains the
|
||||
information needed to run the commands. You **don't need to (and should not)**
|
||||
edit/update/modify this file as it is automatically generated by the CLI. You
|
||||
can take a look at what this file contains by going to
|
||||
`platform/app/PluginConfig.json` in your project's root directory. In short,
|
||||
this file tracks and stores all the extensions/modes and the their version that
|
||||
are currently being used by the viewer.
|
||||
|
||||
## Private NPM Repos
|
||||
|
||||
For the `yarn cli` to view private NPM repos, create a read-only token with the
|
||||
following steps and export it as an environmental variable. You may also export
|
||||
an existing npm token.
|
||||
```
|
||||
npm login
|
||||
npm token create --read-only
|
||||
export NPM_TOKEN=<your readonly token>
|
||||
```
|
||||
|
||||
## External dependencies
|
||||
The ohif-cli will add the path to the external dependencies to the webpack config,
|
||||
so that you can install them in your project and use them in your custom
|
||||
extensions and modes. To achieve this ohif-cli will update the webpack.pwa.js
|
||||
file in the platform/app directory.
|
||||
|
||||
## Video tutorials
|
||||
See the [Video Tutorials](./video-tutorials.md) for videos of some the above
|
||||
commands in action.
|
||||
@@ -0,0 +1,156 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
sidebar_label: Issue & PR Triage Process
|
||||
---
|
||||
|
||||
# Our Process
|
||||
|
||||
Our process is a living, breathing thing. We strive to have regular
|
||||
[retrospectives][retrospective] that help us shape and adapt our process to our
|
||||
team's current needs. This document attempts to capture the broad strokes of
|
||||
that process in an effort to:
|
||||
|
||||
- Strengthen community member involvement and understanding
|
||||
- Welcome feedback and helpful suggestions
|
||||
|
||||
## Issue Triage
|
||||
|
||||
[GitHub issues][gh-issues] are the best way to provide feedback, ask questions,
|
||||
and suggest changes to the OHIF Viewer's core team. Community issues generally
|
||||
fall into one of three categories, and are marked with a `triage` label when
|
||||
created.
|
||||
|
||||
| Issue Template Name | Description |
|
||||
| ---------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| Community: Report 🐛 | Describe a new issue; Provide steps to reproduce; Expected versus actual result? |
|
||||
| Community: Request ✋ | Describe a proposed new feature. Why should it be implemented? What is the impact/value? |
|
||||
| Community: Question ❓ | Seek clarification or assistance relevant to the repository. |
|
||||
|
||||
_table 1. issue template names and descriptions_
|
||||
|
||||
Issues that require `triage` are akin to support tickets. As this is often our
|
||||
first contact with would-be adopters and contributors, it's important that we
|
||||
strive for timely responses and satisfactory resolutions. We attempt to
|
||||
accomplish this by:
|
||||
|
||||
1. Responding to issue requiring `triage` at least once a week
|
||||
2. Create new "official issues" from "community issues"
|
||||
3. Provide clear guidance and next steps (when applicable)
|
||||
4. Regularly clean up old (stale) issues
|
||||
|
||||
> 🖋 Less obviously, patterns in the issues being reported can highlight areas
|
||||
> that need improvement. For example, users often have difficulty navigating
|
||||
> CORS issues when deploying the OHIF Viewer -- how do we best reduce our ticket
|
||||
> volume for this issue?
|
||||
|
||||
### Backlogged Issues
|
||||
|
||||
Community issues serve as vehicles of discussion that lead us to "backlogged
|
||||
issues". Backlogged issues are the distilled and actionable information
|
||||
extracted from community issues. They contain the scope and requirements
|
||||
necessary for hand-off to a core-team (or community) contributor ^\_^
|
||||
|
||||
| Category | Description | Labels |
|
||||
| -------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Bugs | An issue with steps that produce a bug (an unexpected result). | [Bug: Verified 🐛][label-bug] |
|
||||
| Stories | A feature/enhancement with a clear benefit, boundaries, and requirements. | [Story 🙌][label-story] |
|
||||
| Tasks | Changes that improve [UX], [DX], or test coverage; but don't impact application behavior | [Task: CI/Tooling 🤖][label-tooling], [Task: Docs 📖][label-docs], [Task: Refactor 🛠][label-refactor], [Task: Tests 🔬][label-tests] |
|
||||
|
||||
_table 2. backlogged issue types ([full list of labels][gh-labels])_
|
||||
|
||||
## Issue Curation (["backlog grooming"][groom-backlog])
|
||||
|
||||
If a [GitHub issue][gh-issues] has a `bug`, `story`, or `task` label; it's on
|
||||
our backlog. If an issue is on our backlog, it means we are, at the very least,
|
||||
committed to reviewing any community drafted Pull Requests to complete the
|
||||
issue. If you're interested in seeing an issue completed but don't know where to
|
||||
start, please don't hesitate to leave a comment!
|
||||
|
||||
While we don't yet have a long-term or quarterly road map, we do regularly add
|
||||
items to our ["Active Development" GitHub Project Board][gh-board]. Items on
|
||||
this project board are either in active development by Core Team members, or
|
||||
queued up for development as in-progress items are completed.
|
||||
|
||||
> 🖋 Want to contribute but not sure where to start? Check out [Up for
|
||||
> grabs][label-grabs] issues and our [Contributing
|
||||
> documentation][contributing-docs]
|
||||
|
||||
## Contributions (Pull Requests)
|
||||
|
||||
Incoming Pull Requests (PRs) are triaged using the following labels. Code review
|
||||
is performed on all PRs where the bug fix or added functionality is deemed
|
||||
appropriate:
|
||||
|
||||
| Labels | Description |
|
||||
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| **Classification** | |
|
||||
| [PR: Bug Fix][label-bug] | Filed to address a Bug. |
|
||||
| [PR: Draft][draft] | Filed to gather early feedback from the core team, but which is not intended for merging in the short term. |
|
||||
| **Review Workflow** | |
|
||||
| [PR: Awaiting Response 💬][awaiting-response] | The core team is waiting for additional information from the author. |
|
||||
| [PR: Awaiting Review 👀][awaiting-review] | The core team has not yet performed a code review. |
|
||||
| [PR: Awaiting Revisions 🖊][awaiting-revisions] | Following code review, this label is applied until the author has made sufficient changes. |
|
||||
| **QA** | |
|
||||
| [PR: Awaiting User Cases 💃][awaiting-stories] | The PR code changes need common language descriptions of impact to end users before the review can start |
|
||||
| [PR: No UX Impact 🙃][no-ux-impact] | The PR code changes do not impact the user's experience |
|
||||
|
||||
We rely on GitHub Checks and integrations with third party services to evaluate
|
||||
changes in code quality and test coverage. Tests must pass and User cases must
|
||||
be present (when applicable) before a PR can be merged to master, and code
|
||||
quality and test coverage must not be changed by a significant margin. For some
|
||||
repositories, visual screenshot-based tests are also included, and video
|
||||
recordings of end-to-end tests are stored for later review.
|
||||
|
||||
[You can read more about our continuous integration efforts here](/development/continuous-integration.md)
|
||||
|
||||
## Releases
|
||||
|
||||
Releases are made automatically based on the type of commits which have been
|
||||
merged (major.minor.patch). Releases are automatically pushed to NPM. Release
|
||||
notes are automatically generated. Users can subscribe to GitHub and NPM
|
||||
releases.
|
||||
|
||||
We host development, staging, and production environments for the Progressive
|
||||
Web Application version of the OHIF Viewer. [Development][ohif-dev] always
|
||||
reflects the latest changes on our master branch. [Staging][ohif-stage] is used
|
||||
to regression test a release before a bi-weekly deploy to our [Production
|
||||
environment][ohif-prod].
|
||||
|
||||
Important announcements are made on GitHub, tagged as Announcement, and pinned
|
||||
so that they remain at the top of the Issue page.
|
||||
|
||||
The Core team occasionally performs full manual testing to begin the process of
|
||||
releasing a Stable version. Once testing is complete, the known issues are
|
||||
addressed and a Stable version is released.
|
||||
|
||||
<!--
|
||||
LINKS
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[groom-backlog]: https://www.agilealliance.org/glossary/backlog-grooming
|
||||
[retrospective]: https://www.atlassian.com/team-playbook/plays/retrospective
|
||||
[gh-issues]: https://github.com/OHIF/Viewers/issues/new/choose
|
||||
[gh-labels]: https://github.com/OHIF/Viewers/labels
|
||||
<!-- Issue Labels -->
|
||||
[label-story]: https://github.com/OHIF/Viewers/labels/Story%20%3Araised_hands%3A
|
||||
[label-tooling]: https://github.com/OHIF/Viewers/labels/Task%3A%20CI%2FTooling%20%3Arobot%3A
|
||||
[label-docs]: https://github.com/OHIF/Viewers/labels/Task%3A%20Docs%20%3Abook%3A
|
||||
[label-refactor]: https://github.com/OHIF/Viewers/labels/Task%3A%20Refactor%20%3Ahammer_and_wrench%3A
|
||||
[label-tests]: https://github.com/OHIF/Viewers/labels/Task%3A%20Tests%20%3Amicroscope%3A
|
||||
[label-bug]: https://github.com/OHIF/Viewers/labels/Bug%3A%20Verified%20%3Abug%3A
|
||||
<!-- PR Labels -->
|
||||
[draft]: https://github.com/OHIF/Viewers/labels/PR%3A%20Draft
|
||||
[awaiting-response]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20Response%20%3Aspeech_balloon%3A
|
||||
[awaiting-review]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20Review%20%3Aeyes%3A
|
||||
[awaiting-stories]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20UX%20Stories%20%3Adancer%3A
|
||||
[awaiting-revisions]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20Revisions%20%3Apen%3A
|
||||
[no-ux-impact]: https://github.com/OHIF/Viewers/labels/PR%3A%20No%20UX%20Impact%20%3Aupside_down_face%3A
|
||||
<!-- -->
|
||||
[ohif-dev]: https://viewer-dev.ohif.org
|
||||
[ohif-stage]: https://viewer-stage.ohif.org
|
||||
[ohif-prod]: https://viewer.ohif.org
|
||||
[gh-board]: https://github.com/OHIF/Viewers/projects/4
|
||||
[label-grabs]: https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3A%22Up+For+Grabs+%3Araising_hand_woman%3A%22
|
||||
[contributing-docs]: ./development/contributing.md
|
||||
<!-- prettier-ignore-end -->
|
||||
217
platform/docs/versioned_docs/version-3.8/development/testing.md
Normal file
217
platform/docs/versioned_docs/version-3.8/development/testing.md
Normal file
@@ -0,0 +1,217 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
sidebar_label: Testing
|
||||
---
|
||||
|
||||
# Running Tests for OHIF
|
||||
|
||||
We introduce here various test types that is available for OHIF, and how to run
|
||||
each test in order to make sure your contribution hasn't broken any existing
|
||||
functionalities. Idea and philosophy of each testing category is discussed in
|
||||
the second part of this page.
|
||||
|
||||
## Unit test
|
||||
|
||||
To run the unit test:
|
||||
|
||||
```bash
|
||||
yarn run test:unit:ci
|
||||
```
|
||||
|
||||
Note: You should have already installed all the packages with `yarn install`.
|
||||
|
||||
Running unit test will generate a report at the end showing the successful and
|
||||
unsuccessful tests with detailed explanations.
|
||||
|
||||
## End-to-end test
|
||||
For running the OHIF e2e test you need to run the following steps:
|
||||
|
||||
- Open a new terminal, and from the root of the OHIF mono repo, run the following command:
|
||||
|
||||
```bash
|
||||
yarn test:data
|
||||
```
|
||||
|
||||
This will download the required data to run the e2e tests (it might take a while).
|
||||
The `test:data` only needs to be run once and checks the data out. Read more about
|
||||
test data [below](#test-data).
|
||||
|
||||
- Run the viewer with e2e config
|
||||
|
||||
```bash
|
||||
APP_CONFIG=config/e2e.js yarn start
|
||||
```
|
||||
|
||||
You should be able to see test studies in the study list
|
||||
|
||||

|
||||
|
||||
- Open a new terminal inside the OHIF project, and run the e2e cypress test
|
||||
|
||||
```bash
|
||||
yarn test:e2e
|
||||
```
|
||||
|
||||
You should be able to see the cypress window open
|
||||
|
||||

|
||||
|
||||
Run the tests by clicking on the `Run #number integration tests` .
|
||||
|
||||
A new window will open, and you will see e2e tests being executed one after
|
||||
each other.
|
||||
|
||||

|
||||
|
||||
## Test Data
|
||||
The testing data is stored in two OHIF repositories. The first contains the
|
||||
binary DICOM data, at [viewer-testdata](https://github.com/OHIF/viewer-testdata.git)
|
||||
while the second module contains data in the DICOMweb format, installed as a submodule
|
||||
into OHIF in the `testdata` directory. This is retrieved via the command
|
||||
```bash
|
||||
yarn test:data
|
||||
```
|
||||
or the equivalent command `git submodule update --init`
|
||||
When adding new data, run:
|
||||
```
|
||||
npm install -g dicomp10-to-dicomweb
|
||||
mkdicomweb -d dicomweb dcm
|
||||
```
|
||||
to update the local dicomweb submodule in viewer-testdata. Then, commit
|
||||
that data and update the submodules used in OHIF and in the viewer-testdata
|
||||
parent modules.
|
||||
|
||||
All data MUST be fully anonymized and allowed to be used for open access.
|
||||
Any attributions should be included in the DCM directory.
|
||||
|
||||
## Testing Philosophy
|
||||
|
||||
> 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
|
||||
> a PR and let's discuss.
|
||||
|
||||
You're an engineer. You know how to write code, and writing tests isn't all that
|
||||
different. But do you know why we write tests? Do you know when to write one, or
|
||||
what kind of test to write? How do you know if a test is a _"good"_ test? This
|
||||
document's goal is to give you the tools you need to make those determinations.
|
||||
|
||||
Okay. So why do we write tests? To increase our... **CONFIDENCE**
|
||||
|
||||
- If I do a large refactor, does everything still work?
|
||||
- If I changed some critical piece of code, is it safe to push to production?
|
||||
|
||||
Gaining the confidence we need to answer these questions after every change is
|
||||
costly. Good tests allow us to answer them without manual regression testing.
|
||||
What and how we choose to test to increase that confidence is nuanced.
|
||||
|
||||
## Further Reading: Kinds of Tests
|
||||
|
||||
Test's buy us confidence, but not all tests are created equal. Each kind of test
|
||||
has a different cost to write and maintain. An expensive test is worth it if it
|
||||
gives us confidence that a payment is processed, but it may not be the best
|
||||
choice for asserting an element's border color.
|
||||
|
||||
| Test Type | Example | Speed | Cost |
|
||||
| ----------- | ------------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------ |
|
||||
| Static | `addNums(1, '2')` called with `string`, expected `int`. | :rocket: Instant | :money_with_wings: |
|
||||
| Unit | `addNums(1, 2)` returns expected result `3` | :airplane: Fast | :money_with_wings::money_with_wings: |
|
||||
| Integration | Clicking "Sign In", navigates to the dashboard (mocked network requests) | :running: Okay | :money_with_wings::money_with_wings::money_with_wings: |
|
||||
| End-to-end | Clicking "Sign In", navigates to the dashboard (no mocks) | :turtle: Slow | :money_with_wings::money_with_wings::money_with_wings::money_with_wings: |
|
||||
|
||||
- :rocket: Speed: How quickly tests run
|
||||
- :money_with_wings: Cost: Time to write, and to debug when broken (more points
|
||||
of failure)
|
||||
|
||||
### Static Code Analysis
|
||||
|
||||
Modern tooling gives us this "for free". It can catch invalid regular
|
||||
expressions, unused variables, and guarantee we're calling methods/functions
|
||||
with the expected parameter types.
|
||||
|
||||
Example Tooling:
|
||||
|
||||
- [ESLint][eslint-rules]
|
||||
- [TypeScript][typescript-docs] or [Flow][flow-org]
|
||||
|
||||
### Unit Tests
|
||||
|
||||
The building blocks of our libraries and applications. For these, you'll often
|
||||
be testing a single function or method. Conceptually, this equates to:
|
||||
|
||||
_Pure Function Test:_
|
||||
|
||||
- If I call `sum(2, 2)`, I expect the output to be `4`
|
||||
|
||||
_Side Effect Test:_
|
||||
|
||||
- If I call `resetViewport(viewport)`, I expect `cornerstone.reset` to be called
|
||||
with `viewport`
|
||||
|
||||
#### When to use
|
||||
|
||||
Anything that is exposed as public API should have unit tests.
|
||||
|
||||
#### When to avoid
|
||||
|
||||
You're actually testing implementation details. You're testing implementation
|
||||
details if:
|
||||
|
||||
- Your test does something that the consumer of your code would never do.
|
||||
- IE. Using a private function
|
||||
- A refactor can break your tests
|
||||
|
||||
### Integration Tests
|
||||
|
||||
We write integration tests to gain confidence that several units work together.
|
||||
Generally, we want to mock as little as possible for these tests. In practice,
|
||||
this means only mocking network requests.
|
||||
|
||||
### End-to-End Tests
|
||||
|
||||
These are the most expensive tests to write and maintain. Largely because, when
|
||||
they fail, they have the largest number of potential points of failure. So why
|
||||
do we write them? Because they also buy us the most confidence.
|
||||
|
||||
#### When to use
|
||||
|
||||
Mission critical features and functionality, or to cover a large breadth of
|
||||
functionality until unit tests catch up. Unsure if we should have a test for
|
||||
feature `X` or scenario `Y`? Open an issue and let's discuss.
|
||||
|
||||
### General
|
||||
|
||||
- [Assert(js) Conf 2018 Talks][assert-js-talks]
|
||||
- [Write tests. Not too many. Mostly integration.][kent-talk] - Kent C. Dodds
|
||||
- [I see your point, but…][gleb-talk] - Gleb Bahmutov
|
||||
- [Static vs Unit vs Integration vs E2E Testing][kent-blog] - Kent C. Dodds
|
||||
(Blog)
|
||||
|
||||
### End-to-end Testing w/ Cypress
|
||||
|
||||
- [Getting Started](https://docs.cypress.io/guides/overview/why-cypress.html)
|
||||
- Be sure to check out `Getting Started` and `Core Concepts`
|
||||
- [Best Practices](https://docs.cypress.io/guides/references/best-practices.html)
|
||||
- [Example Recipes](https://docs.cypress.io/examples/examples/recipes.html)
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[eslint-rules]: https://eslint.org/docs/rules/
|
||||
[mini-pacs]: https://github.com/OHIF/viewer-testdata
|
||||
[typescript-docs]: https://www.typescriptlang.org/docs/home.html
|
||||
[flow-org]: https://flow.org/
|
||||
<!-- Talks -->
|
||||
[assert-js-talks]: https://www.youtube.com/playlist?list=PLZ66c9_z3umNSrKSb5cmpxdXZcIPNvKGw
|
||||
[kent-talk]: https://www.youtube.com/watch?v=Fha2bVoC8SE
|
||||
[gleb-talk]: https://www.youtube.com/watch?v=5FnalKRjpZk
|
||||
[kent-blog]: https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests
|
||||
<!-- Images -->
|
||||
[testing-trophy]: https://twitter.com/kentcdodds/status/960723172591992832?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E960723172591992832&ref_url=https%3A%2F%2Fkentcdodds.com%2Fblog%2Fwrite-tests
|
||||
[aaron-square]: https://twitter.com/Carofine247/status/966727489274961920
|
||||
[gleb-pyramid]: https://twitter.com/Carofine247/status/966764532046684160/photo/3
|
||||
[testing-pyramid]: https://dojo.ministryoftesting.com/dojo/lessons/the-mobile-test-pyramid
|
||||
[testing-dorito]: https://twitter.com/denvercoder/status/960752578198843392
|
||||
[testing-dorito-img]: https://pbs.twimg.com/media/DVVHXycUMAAcN-F?format=jpg&name=4096x4096
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
sidebar_position: 10
|
||||
sidebar_label: Global Types
|
||||
---
|
||||
|
||||
# Extending App Types and Services in Your Application
|
||||
|
||||
This documentation provides an overview and examples on how to use and extend `withAppTypes`, integrate custom properties, and add services in the global namespace of the application. This helps in enhancing the application's modularity and extensibility.
|
||||
|
||||
## Overview of `withAppTypes`
|
||||
|
||||
The `withAppTypes` function is a TypeScript utility that extends the base properties of components or modules with the application's core service and manager types. It allows for a more flexible and type-safe way to pass around core functionality and custom properties.
|
||||
|
||||
### Using `withAppTypes`
|
||||
|
||||
`withAppTypes` can be enhanced using generics to include custom properties. This is particularly useful for passing additional data or configurations specific to your component or service.
|
||||
|
||||
### Extending with Custom Properties
|
||||
|
||||
You can extend `withAppTypes` to include custom properties by defining an interface for the props you need. For example:
|
||||
|
||||
```typescript
|
||||
interface ColorbarProps {
|
||||
viewportId: string;
|
||||
displaySets: Array<any>;
|
||||
colorbarProperties: ColorbarProperties;
|
||||
}
|
||||
|
||||
export function Colorbar({
|
||||
viewportId,
|
||||
displaySets,
|
||||
commandsManager, // injected type
|
||||
servicesManager, // injected type
|
||||
colorbarProperties,
|
||||
}: withAppTypes<ColorbarProps>): ReactElement {
|
||||
// Component logic here
|
||||
}
|
||||
```
|
||||
|
||||
In this example, `ColorbarProps` is a custom interface that extends the application types through `withAppTypes`.
|
||||
|
||||
## Typing the custom extensions's new services
|
||||
|
||||
Extensions can define additional services that integrate seamlessly into the application's global service architecture, and will be available on the ServicesManager for use across the application.
|
||||
|
||||
### Adding the extension's services Types
|
||||
|
||||
Declare your service in the global namespace and use it across your application as demonstrated below:
|
||||
|
||||
`extensions/my-extension/src/types/whatever.ts`
|
||||
|
||||
```typescript
|
||||
declare global {
|
||||
namespace AppTypes {
|
||||
// only add if you need direct access to the service ex. AppTypes.MicroscopyService
|
||||
export type MicroscopyService = MicroscopyServiceType;
|
||||
// add to the global Services interface, and to withAppTypes
|
||||
export interface Services {
|
||||
microscopyService?: MicroscopyServiceType;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Doing the above adds the `microscopyService` to the global Services interface, which ServicesManager uses by default `public services: AppTypes.Services = {};` to type services, and is also used by withAppTypes to inject services into components.
|
||||
You will also get access to the seperate services via `AppTypes.YourServiceName` in your application.
|
||||
|
||||
|
||||
```typescript
|
||||
export function CustomComponent({
|
||||
servicesManager,
|
||||
}: withAppTypes<CustomComponentProps>): ReactElement {
|
||||
const { microscopyService } = servicesManager.services;
|
||||
microscopyService.someMethod(); // auto completation available
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
export function CustomComponent2(
|
||||
microscopyService: AppTypes.MicroscopyService,
|
||||
): ReactElement {
|
||||
microscopyService.someMethod(); // auto completation available
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
sidebar_label: Video Tutorials
|
||||
---
|
||||
|
||||
# Video Tutorials
|
||||
|
||||
## Creating, Linking and Publishing OHIF Modes and Extensions
|
||||
|
||||
The [OHIF CLI](./ohif-cli.md) facilitates the creation, linkage and publication
|
||||
of OHIF modes and extensions. The videos below walk through how to use the CLI for
|
||||
- creating modes and extensions
|
||||
- linking local modes and extensions
|
||||
- publishing modes and extensions to NPM
|
||||
- adding published modes and extensions to OHIF
|
||||
- submitting a mode to OHIF
|
||||
|
||||
The videos build on top of one another whereby the mode and extension created
|
||||
in each of the first two videos are published to NPM and then the published
|
||||
entities are added to OHIF.
|
||||
|
||||
### Creating and Linking a Mode
|
||||
|
||||
The first video demonstrates the creation and linkage of a mode.
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/884891676?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="Create and link a mode"></iframe>
|
||||
</div>
|
||||
|
||||
### Creating and Linking an Extension
|
||||
|
||||
The second video creates and links an extension. The mode from the first
|
||||
video is modified to reference the extension.
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/884891718?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="Create and link an extension"></iframe>
|
||||
</div>
|
||||
|
||||
### Publishing an Extension to NPM
|
||||
|
||||
The third video shows how the extension created in the second video can
|
||||
be published to NPM.
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/884891701?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="Publish an extension to NPM"></iframe>
|
||||
</div>
|
||||
|
||||
### Publishing a Mode to NPM
|
||||
|
||||
The fourth video shows how the mode created in the first video can be
|
||||
published to NPM.
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/884893445?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="Publish a mode to NPM"></iframe>
|
||||
</div>
|
||||
|
||||
### Adding a Mode from NPM
|
||||
|
||||
The fifth video adds the mode and extension published in NPM to OHIF. Note
|
||||
that since the mode references the extension both are added with one CLI
|
||||
command.
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/884893388?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="Add a mode from NPM"></iframe>
|
||||
</div>
|
||||
|
||||
### Submitting a Mode to OHIF
|
||||
|
||||
The sixth video demonstrates how a mode can be submitted to OHIF to have it
|
||||
appear in OHIF's mode gallery.
|
||||
<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
|
||||
<iframe src="https://player.vimeo.com/video/884893372?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="Submit a mode to OHIF"></iframe>
|
||||
</div>
|
||||
Reference in New Issue
Block a user