Compare commits
101
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7982cf4fb4 | ||
|
|
df6410b9d0 | ||
|
|
a034bdd478 | ||
|
|
cd4282129b | ||
|
|
a54d023c7f | ||
|
|
6d035c1679 | ||
|
|
1ff9beefcc | ||
|
|
52dcce875e | ||
|
|
da725a8923 | ||
|
|
4cae576a90 | ||
|
|
b59c8c277a | ||
|
|
2c5ae43341 | ||
|
|
3ba0e8f919 | ||
|
|
58fa26b5ac | ||
|
|
dabc948f4c | ||
|
|
e7ff3a3ac8 | ||
|
|
764b7a1054 | ||
|
|
2f13453bea | ||
|
|
26da6b0013 | ||
|
|
156b093965 | ||
|
|
54dacbb91b | ||
|
|
6d18e7f1fe | ||
|
|
08ff214ea6 | ||
|
|
cac911f08e | ||
|
|
36952c401a | ||
|
|
b3781ac692 | ||
|
|
2174f4f2fd | ||
|
|
d033bd5995 | ||
|
|
c455253c0e | ||
|
|
ec1946e379 | ||
|
|
ad325fd83f | ||
|
|
a4112c46a5 | ||
|
|
e73d009c21 | ||
|
|
f826341631 | ||
|
|
f8b52d0fee | ||
|
|
0e78836d55 | ||
|
|
40bf1a2efd | ||
|
|
02c732aa15 | ||
|
|
c5f532159b | ||
|
|
b1df019c49 | ||
|
|
54b70e5fa4 | ||
|
|
5802cf18eb | ||
|
|
210c2e8d2c | ||
|
|
da318c9c8c | ||
|
|
903c41d26f | ||
|
|
ba261a0d54 | ||
|
|
3398a894a3 | ||
|
|
5a13194203 | ||
|
|
a2cc477a1a | ||
|
|
2e7a59f7f8 | ||
|
|
83d7d59954 | ||
|
|
163fee8941 | ||
|
|
f547fdf832 | ||
|
|
ac347849d0 | ||
|
|
54e0e32e22 | ||
|
|
690156d4b6 | ||
|
|
3b5fdb678a | ||
|
|
e7604c4418 | ||
|
|
71f11a4856 | ||
|
|
ae5d0587db | ||
|
|
fbc06329e2 | ||
|
|
86732c8186 | ||
|
|
a34d47c850 | ||
|
|
f758741950 | ||
|
|
29a470103a | ||
|
|
104343aad5 | ||
|
|
d8b4a4d4c0 | ||
|
|
2fd60f3109 | ||
|
|
08ce30e69c | ||
|
|
546f6bfe68 | ||
|
|
8e1f15e031 | ||
|
|
0d5d804741 | ||
|
|
ca735fa070 | ||
|
|
3d425f54cc | ||
|
|
7bc9b45853 | ||
|
|
5bd3af0cca | ||
|
|
d4aee36542 | ||
|
|
2a281da19f | ||
|
|
4631218dcb | ||
|
|
8b3e5dffb1 | ||
|
|
ef6819cf40 | ||
|
|
2f104b5e91 | ||
|
|
f256ac5a7d | ||
|
|
3a4ee9e346 | ||
|
|
1a9cfea365 | ||
|
|
9055f19fb5 | ||
|
|
bcbc5e4bbf | ||
|
|
408ba36f4f | ||
|
|
091cab49e0 | ||
|
|
4a09f33446 | ||
|
|
4095629310 | ||
|
|
91d2d31846 | ||
|
|
ff2c1cb2f1 | ||
|
|
727c0d8ba6 | ||
|
|
4b3994e788 | ||
|
|
571dd5848f | ||
|
|
2d48d0aa37 | ||
|
|
562d63fa74 | ||
|
|
1a6246f99b | ||
|
|
ce1a62a961 | ||
|
|
dd6acb2d03 |
No files matched your search
+81
-78
@@ -11,10 +11,13 @@ version: 2.1
|
||||
|
||||
orbs:
|
||||
codecov: codecov/codecov@1.0.5
|
||||
cypress: cypress-io/cypress@1.8.0
|
||||
|
||||
defaults: &defaults
|
||||
docker:
|
||||
- image: circleci/node:10.16.0
|
||||
environment:
|
||||
TERM: xterm # Enable colors in term
|
||||
working_directory: ~/repo
|
||||
|
||||
jobs:
|
||||
@@ -47,12 +50,12 @@ jobs:
|
||||
|
||||
# RUN TESTS
|
||||
- run:
|
||||
name: "JavaScript Test Suite"
|
||||
name: 'JavaScript Test Suite'
|
||||
command: yarn run test:unit:ci
|
||||
|
||||
# PLATFORM/VIEWER
|
||||
- run:
|
||||
name: "VIEWER: Combine report output"
|
||||
name: 'VIEWER: Combine report output'
|
||||
command: |
|
||||
viewerCov="/home/circleci/repo/platform/viewer/coverage"
|
||||
touch "${viewerCov}/reports"
|
||||
@@ -61,12 +64,12 @@ jobs:
|
||||
cat "${viewerCov}/lcov.info" >>"${viewerCov}/reports"
|
||||
echo "\<<\<<\<< EOF" >> "${viewerCov}/reports"
|
||||
- codecov/upload:
|
||||
file: "/home/circleci/repo/platform/viewer/coverage/reports"
|
||||
flags: "viewer"
|
||||
file: '/home/circleci/repo/platform/viewer/coverage/reports'
|
||||
flags: 'viewer'
|
||||
|
||||
# PLATFORM/CORE
|
||||
- run:
|
||||
name: "CORE: Combine report output"
|
||||
name: 'CORE: Combine report output'
|
||||
command: |
|
||||
coreCov="/home/circleci/repo/platform/core/coverage"
|
||||
touch "${coreCov}/reports"
|
||||
@@ -75,8 +78,13 @@ jobs:
|
||||
cat "${coreCov}/lcov.info" >> "${coreCov}/reports"
|
||||
echo "\<<\<<\<< EOF" >> "${coreCov}/reports"
|
||||
- codecov/upload:
|
||||
file: "/home/circleci/repo/platform/core/coverage/reports"
|
||||
flags: "core"
|
||||
file: '/home/circleci/repo/platform/core/coverage/reports'
|
||||
flags: 'core'
|
||||
|
||||
# Persist :+1:
|
||||
- persist_to_workspace:
|
||||
root: ~/repo
|
||||
paths: .
|
||||
|
||||
MERGE_UNIT_TESTS:
|
||||
<<: *defaults
|
||||
@@ -107,12 +115,12 @@ jobs:
|
||||
|
||||
# RUN TESTS
|
||||
- run:
|
||||
name: "JavaScript Test Suite"
|
||||
name: 'JavaScript Test Suite'
|
||||
command: yarn run test:unit:ci
|
||||
|
||||
# PLATFORM/VIEWER
|
||||
- run:
|
||||
name: "VIEWER: Combine report output"
|
||||
name: 'VIEWER: Combine report output'
|
||||
command: |
|
||||
viewerCov="/home/circleci/repo/platform/viewer/coverage"
|
||||
touch "${viewerCov}/reports"
|
||||
@@ -121,12 +129,12 @@ jobs:
|
||||
cat "${viewerCov}/lcov.info" >>"${viewerCov}/reports"
|
||||
echo "\<<\<<\<< EOF" >> "${viewerCov}/reports"
|
||||
- codecov/upload:
|
||||
file: "/home/circleci/repo/platform/viewer/coverage/reports"
|
||||
flags: "viewer"
|
||||
file: '/home/circleci/repo/platform/viewer/coverage/reports'
|
||||
flags: 'viewer'
|
||||
|
||||
# PLATFORM/CORE
|
||||
- run:
|
||||
name: "CORE: Combine report output"
|
||||
name: 'CORE: Combine report output'
|
||||
command: |
|
||||
coreCov="/home/circleci/repo/platform/core/coverage"
|
||||
touch "${coreCov}/reports"
|
||||
@@ -135,37 +143,14 @@ jobs:
|
||||
cat "${coreCov}/lcov.info" >> "${coreCov}/reports"
|
||||
echo "\<<\<<\<< EOF" >> "${coreCov}/reports"
|
||||
- codecov/upload:
|
||||
file: "/home/circleci/repo/platform/core/coverage/reports"
|
||||
flags: "core"
|
||||
file: '/home/circleci/repo/platform/core/coverage/reports'
|
||||
flags: 'core'
|
||||
|
||||
# Persist :+1:
|
||||
- persist_to_workspace:
|
||||
root: ~/repo
|
||||
paths: .
|
||||
|
||||
e2e_test:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: cypress/base:8
|
||||
environment:
|
||||
## this enables colors in the output
|
||||
TERM: xterm
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/repo
|
||||
- restore_cache:
|
||||
name: Restore Yarn and Cypress Package Cache
|
||||
keys:
|
||||
# when lock file changes, use increasingly general patterns to restore cache
|
||||
- yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
- yarn-packages-v1-{{ .Branch }}-
|
||||
- yarn-packages-v1-
|
||||
# - run: $(yarn bin)/cypress run --record
|
||||
# Shouldn't be needed if we're using a package cache that contains Cypress
|
||||
# Could do a check here, if it doesn't exist, install cypress?
|
||||
- run: yarn install
|
||||
- run: yarn run test:e2e:ci
|
||||
|
||||
npm_publish:
|
||||
<<: *defaults
|
||||
steps:
|
||||
@@ -176,11 +161,15 @@ jobs:
|
||||
command:
|
||||
mkdir ~/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking
|
||||
no\n" > ~/.ssh/config
|
||||
# --no-ci argument is not ideal; however, semantic-rlease thinks we're
|
||||
# attempting to run it from a `pr`, which is not the case
|
||||
- run: git config --global user.email "danny.ri.brown+ohif-bot@gmail.com"
|
||||
- run: git config --global user.name "ohif-bot"
|
||||
- run:
|
||||
name: Publish using Semantic Release
|
||||
command: npx semantic-release --debug
|
||||
name: Authenticate with registry
|
||||
command:
|
||||
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/repo/.npmrc
|
||||
- run: npx lerna version
|
||||
- run: npx lerna publish from-package
|
||||
|
||||
# Persist :+1:
|
||||
- persist_to_workspace:
|
||||
root: ~/repo
|
||||
@@ -196,8 +185,8 @@ jobs:
|
||||
command:
|
||||
mkdir ~/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking
|
||||
no\n" > ~/.ssh/config
|
||||
- run: git config --global user.email "gh-pages@localhost"
|
||||
- run: git config --global user.name "npm gh-pages"
|
||||
- run: git config --global user.email "danny.ri.brown+ohif-bot@gmail.com"
|
||||
- run: git config --global user.name "ohif-bot"
|
||||
- run: yarn global add gh-pages
|
||||
- run:
|
||||
name: Generate Docs
|
||||
@@ -235,29 +224,14 @@ jobs:
|
||||
docker push ohif/$IMAGE_NAME:latest
|
||||
fi
|
||||
|
||||
build_demo_site:
|
||||
deploy_demo_site:
|
||||
<<: *defaults
|
||||
steps:
|
||||
# Download and cache dependencies
|
||||
- checkout
|
||||
- restore_cache:
|
||||
name: Restore Yarn Package Cache
|
||||
keys:
|
||||
# when lock file changes, use increasingly general patterns to restore cache
|
||||
- yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
- yarn-packages-v1-{{ .Branch }}-
|
||||
- yarn-packages-v1-
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: yarn install --frozen-lockfile
|
||||
- save_cache:
|
||||
name: Save Yarn Package Cache
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
- attach_workspace:
|
||||
at: ~/repo
|
||||
# Build & Test
|
||||
- run:
|
||||
name: "Build Demo Site, Upload SourceMaps, Send Deploy Notification"
|
||||
name: 'Build Demo Site, Upload SourceMaps, Send Deploy Notification'
|
||||
command: |
|
||||
yarn build:demo:ci
|
||||
perl -i -pe 's#</head>#`cat .circleci/rollbar.html` #e' build/index.html
|
||||
@@ -302,7 +276,7 @@ workflows:
|
||||
version: 2
|
||||
|
||||
# PULL REQUESTS
|
||||
pull_requests:
|
||||
PR_CHECKS:
|
||||
jobs:
|
||||
- PR_UNIT_TESTS:
|
||||
filters:
|
||||
@@ -311,33 +285,62 @@ workflows:
|
||||
- master
|
||||
- feature/*
|
||||
- hotfix/*
|
||||
# Cypress job added by `cypress-io` orb
|
||||
- cypress/run:
|
||||
pre-steps:
|
||||
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v' # Use yarn latest
|
||||
yarn: true
|
||||
store_artifacts: true
|
||||
start: yarn run dev
|
||||
wait-on: 'http://localhost:3000'
|
||||
no-workspace: true # Don't persist workspace
|
||||
working_directory: platform/viewer
|
||||
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
||||
post-steps:
|
||||
- store_test_results:
|
||||
path: cypress/results
|
||||
requires:
|
||||
- PR_UNIT_TESTS
|
||||
|
||||
# MERGE TO MASTER
|
||||
cut_release:
|
||||
RELEASE:
|
||||
jobs:
|
||||
- MERGE_UNIT_TESTS:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- e2e_test:
|
||||
# Cypress job added by `cypress-io` orb
|
||||
- cypress/run:
|
||||
pre-steps:
|
||||
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v' # Use yarn latest
|
||||
yarn: true
|
||||
record: true
|
||||
store_artifacts: true
|
||||
start: yarn run dev
|
||||
wait-on: 'http://localhost:3000'
|
||||
working_directory: platform/viewer
|
||||
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
||||
post-steps:
|
||||
- store_test_results:
|
||||
path: cypress/results
|
||||
requires:
|
||||
- MERGE_UNIT_TESTS
|
||||
# Update NPM
|
||||
- npm_publish:
|
||||
requires:
|
||||
- e2e_test
|
||||
- cypress/run
|
||||
# Update docs.ohif.org
|
||||
- docs_publish:
|
||||
requires:
|
||||
- e2e_test
|
||||
# - docs_publish:
|
||||
# requires:
|
||||
# - cypress/run
|
||||
# Update hub.docker.org
|
||||
- docker_publish:
|
||||
requires:
|
||||
- npm_publish
|
||||
# - docker_publish:
|
||||
# requires:
|
||||
# - npm_publish
|
||||
# Update viewer.ohif.org
|
||||
- build_demo_site:
|
||||
requires:
|
||||
- e2e_test
|
||||
- demo_site_publish:
|
||||
requires:
|
||||
- build_demo_site
|
||||
# - build_demo_site:
|
||||
# requires:
|
||||
# - cypress/run
|
||||
# - demo_site_publish:
|
||||
# requires:
|
||||
# - build_demo_site
|
||||
File renamed without changes.
@@ -4,7 +4,6 @@ about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: 'Bug Report :bug:'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Before Creating an issue**
|
||||
@@ -15,7 +14,7 @@ assignees: ''
|
||||
|
||||
**Describe the bug**
|
||||
|
||||
*A clear and concise description of what the bug is.*
|
||||
_A clear and concise description of what the bug is._
|
||||
|
||||
**Steps To Reproduce**
|
||||
|
||||
@@ -29,12 +28,12 @@ Please use code blocks to show formatted errors or code snippets
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
*A clear and concise description of what you expected to happen.*
|
||||
|
||||
_A clear and concise description of what you expected to happen._
|
||||
|
||||
**Environment**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
@@ -4,15 +4,16 @@ about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Awesome, do you have an idea? 😍
|
||||
<!-- ## Awesome, do you have an idea? 😍
|
||||
|
||||
If you have a **feature request, improvement or idea**, check [our official roadmap](https://github.com/OHIF/react-viewerbase/projects) to see if it is already planned!
|
||||
If you have a **feature request, improvement or idea**, check [our official roadmap](https://github.com/OHIF/react-viewerbase/projects) to see if it is already planned! -->
|
||||
|
||||
### 👉 [Go to Roadmap](https://github.com/OHIF/react-viewerbase/projects)
|
||||
<!-- ### 👉 [Go to Roadmap](https://github.com/OHIF/react-viewerbase/projects)
|
||||
|
||||
If your feature request isn't there, continue with this issue and we can discuss it 🤟
|
||||
If your feature request isn't there, continue with this issue and we can discuss
|
||||
it 🤟 -->
|
||||
|
||||
Please include the reasons why you think your change should be made, and any supporting evidence that helps us asses its value and priority.
|
||||
Please include the reasons why you think your change should be made, and any
|
||||
supporting evidence that helps us asses its value and priority.
|
||||
@@ -4,12 +4,15 @@ about: "I have a question \U0001F4AC"
|
||||
title: ''
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
We are a small team with limited resources. Your question is much more likely to be answered if it is [a good question](https://stackoverflow.com/help/how-to-ask)
|
||||
We are a small team with limited resources. Your question is much more likely to
|
||||
be answered if it is
|
||||
[a good question](https://stackoverflow.com/help/how-to-ask)
|
||||
|
||||
**Description**
|
||||
|
||||
|
||||
Questions can often be answered by our documentation. Unable to find an answer in our docs? We'll try to help. In the meantime, if you answer your own question, please respond with the answer here so that others may benefit as well. Better yet, open a PR to expand our docs ^_^
|
||||
Questions can often be answered by our documentation. Unable to find an answer
|
||||
in our docs? We'll try to help. In the meantime, if you answer your own
|
||||
question, please respond with the answer here so that others may benefit as
|
||||
well. Better yet, open a PR to expand our docs ^\_^
|
||||
@@ -8,6 +8,7 @@ docs/_book
|
||||
src/version.js
|
||||
junit.xml
|
||||
coverage/
|
||||
.docz/
|
||||
|
||||
# YALC (for Erik)
|
||||
.yalc
|
||||
@@ -28,3 +29,6 @@ docker/dcm4che/dcm4che-arc
|
||||
|
||||
# Cypress test results
|
||||
cypress/videos/
|
||||
|
||||
# Locize settings
|
||||
.locize
|
||||
@@ -3,79 +3,28 @@
|
||||
# Set directory to location of this script
|
||||
# https://stackoverflow.com/a/3355423/1867984
|
||||
cd "$(dirname "$0")"
|
||||
cd .. # Up to project root
|
||||
|
||||
# Helpful to verify which versions we're using
|
||||
yarn -v
|
||||
node -v
|
||||
|
||||
# Install GitBook CLI
|
||||
echo 'Installing Gitbook CLI'
|
||||
yarn global add gitbook-cli
|
||||
npm install -g gitbook-cli
|
||||
|
||||
echo 'Running Gitbook installation'
|
||||
# Generate all version's GitBook output
|
||||
# For each directory in /docs ...
|
||||
cd ./../docs/
|
||||
for D in *; do
|
||||
if [ -d "${D}" ]; then
|
||||
|
||||
echo "Generating output for: ${D}"
|
||||
cd "${D}"
|
||||
|
||||
# Clear previous output, generate new
|
||||
rm -rf _book
|
||||
node /opt/buildhome/.nvm/versions/node/v10.16.0/lib/node_modules/gitbook-cli/bin/gitbook.js install
|
||||
node /opt/buildhome/.nvm/versions/node/v10.16.0/lib/node_modules/gitbook-cli/bin/gitbook.js build
|
||||
cd ..
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
# Move CNAME File into `latest`
|
||||
cp CNAME ./latest/_book/CNAME
|
||||
|
||||
# Create a history folder in our latest version's output
|
||||
mkdir ./latest/_book/history
|
||||
|
||||
# Move each version's files to latest's history folder
|
||||
for D in *; do
|
||||
# If it's a directory
|
||||
if [ -d "${D}" ]; then
|
||||
# If the directory name starts with `v` (v1, v2, etc.)
|
||||
if [ "${D}" == v* ] ; then
|
||||
|
||||
echo "Moving ${D} to the latest version's history folder"
|
||||
|
||||
mkdir "./latest/_book/history/${D}"
|
||||
cp -v -r "./${D}/_book"/* "./latest/_book/history/${D}"
|
||||
|
||||
fi
|
||||
fi
|
||||
done
|
||||
cd ..
|
||||
|
||||
# Build and copy the PWA Viewer into the demo directory
|
||||
mkdir ./docs/latest/_book/demo/
|
||||
|
||||
# Install build deps and all monorepo package dependencies. Yarn Workspaces
|
||||
# should also symlink all projects appropriately
|
||||
yarn install --no-ignore-optional --pure-lockfile
|
||||
|
||||
# Navigate to our Viewer project
|
||||
cd ./platform/viewer/
|
||||
dir
|
||||
ls
|
||||
|
||||
# Create a Versions File
|
||||
# node -p -e '"export default "' + require(\"./../package.json\").version + '";"' > src/version.js
|
||||
yarn run version
|
||||
# Copy over wado-image-loader codecs and worker file
|
||||
cp ./../../node_modules/cornerstone-wado-image-loader/dist/*.min.js* public -v
|
||||
# Build using react-scripts
|
||||
# npx cross-env PUBLIC_URL=/demo REACT_APP_CONFIG=config/netlify.js react-scripts --max_old_space_size=4096 build
|
||||
# Build using WebPack
|
||||
# TODO: consume public/config correctly instead of hardcode
|
||||
npx webpack --config config/webpack.prod.js --mode production --env.production
|
||||
# Copy output to the folder that is our publish target
|
||||
npx cpx "dist/**/*" ./../../docs/latest/_book/demo --verbose
|
||||
# Build && Move PWA Output
|
||||
yarn run build:ci
|
||||
mkdir -p ./.netlify/www/pwa
|
||||
mv platform/viewer/dist/* .netlify/www/pwa -v
|
||||
|
||||
# Build && Move script output
|
||||
# yarn run build:package
|
||||
|
||||
echo 'Nothing left to see here. Go home, folks.'
|
||||
|
||||
# Build using react-scripts
|
||||
# npx cross-env PUBLIC_URL=/demo REACT_APP_CONFIG=config/netlify.js react-scripts --max_old_space_size=4096 build
|
||||
@@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>OHIF Viewer: Deploy Preview</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Index of Previews</h1>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/pwa">Progressive Web App</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
+74
-37
@@ -1,53 +1,75 @@
|
||||
const path = require("path");
|
||||
const ExtractCssChunks = require("extract-css-chunks-webpack-plugin");
|
||||
|
||||
const SRC_DIR = path.join(__dirname, "../src");
|
||||
const PUBLIC_DIR = path.join(__dirname, "../public");
|
||||
const DIST_DIR = path.join(__dirname, "../dist");
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
// const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||
|
||||
module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
return {
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`
|
||||
bundle: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
context: SRC_DIR,
|
||||
module: {
|
||||
rules: [
|
||||
/**
|
||||
* JSX
|
||||
*/
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
exclude: [/node_modules/, /packages\\extension/],
|
||||
loader: "babel-loader",
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: "upward",
|
||||
rootMode: 'upward',
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
'@babel/preset-env',
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
modules: false,
|
||||
targets: {
|
||||
ie: '11',
|
||||
},
|
||||
// https://babeljs.io/docs/en/babel-preset-env#usebuiltins
|
||||
useBuiltIns: 'usage',
|
||||
// https://babeljs.io/docs/en/babel-preset-env#corejs
|
||||
corejs: 3,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Stylus to CSS
|
||||
* CSS to CommonJS
|
||||
* Style nodes from JS Strings
|
||||
*/
|
||||
{
|
||||
test: /\.styl$/,
|
||||
use: [
|
||||
{ loader: 'style-loader' },
|
||||
{ loader: 'css-loader' },
|
||||
{ loader: 'stylus-loader' },
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
"style-loader",
|
||||
ExtractCssChunks.loader,
|
||||
{ loader: "css-loader", options: { importLoaders: 1 } },
|
||||
'style-loader',
|
||||
// ExtractCssChunks.loader,
|
||||
{ loader: 'css-loader', options: { importLoaders: 1 } },
|
||||
{
|
||||
loader: "postcss-loader",
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: "./postcss.config.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
path: './postcss.config.js',
|
||||
},
|
||||
plugins: () => [autoprefixer('last 2 version', 'ie >= 11')],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
/**
|
||||
* This allows us to include web workers in our bundle, and VTK.js
|
||||
@@ -59,10 +81,10 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
include: /vtk\.js[\/\\]Sources/,
|
||||
use: [
|
||||
{
|
||||
loader: "worker-loader",
|
||||
options: { inline: true, fallback: false }
|
||||
}
|
||||
]
|
||||
loader: 'worker-loader',
|
||||
options: { inline: true, fallback: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
/**
|
||||
* This is exclusively used by `vtk.js` to bundle glsl files.
|
||||
@@ -70,21 +92,36 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
{
|
||||
test: /\.glsl$/i,
|
||||
include: /vtk\.js[\/\\]Sources/,
|
||||
loader: "shader-loader"
|
||||
}
|
||||
]
|
||||
loader: 'shader-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
// Which directories to search when resolving modules
|
||||
modules: [
|
||||
path.resolve(__dirname, "../node_modules"),
|
||||
path.resolve(__dirname, "../../../node_modules"),
|
||||
SRC_DIR
|
||||
// Modules specific to this package
|
||||
path.resolve(__dirname, '../node_modules'),
|
||||
// Hoisted Yarn Workspace Modules
|
||||
path.resolve(__dirname, '../../../node_modules'),
|
||||
SRC_DIR,
|
||||
],
|
||||
// Attempt to resolve these extensions in order.
|
||||
extensions: [".js", ".jsx", ".json", "*"],
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
// symlinked resources are resolved to their real path, not their symlinked location
|
||||
symlinks: true
|
||||
}
|
||||
symlinks: true,
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||
'process.env.DEBUG': JSON.stringify(process.env.DEBUG),
|
||||
'process.env.APP_CONFIG': JSON.stringify(process.env.APP_CONFIG || ''),
|
||||
'process.env.PUBLIC_URL': JSON.stringify(process.env.PUBLIC_URL || ''),
|
||||
}),
|
||||
],
|
||||
// Fix: https://github.com/webpack-contrib/css-loader/issues/447#issuecomment-285598881
|
||||
// For issue in cornerstone-wado-image-loader
|
||||
node: {
|
||||
fs: 'empty',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -124,11 +124,12 @@ These commands are available from the root directory. Each project directory als
|
||||
| -------------------- | ------------------------------------------------------------- |
|
||||
| **Develop** | |
|
||||
| `dev` or `start` | Default development experience for Viewer |
|
||||
| `dev:<package-name>` | Replace with `core`, `ui`, `i18n`, `cornerstone`, `vtk`, etc. |
|
||||
| `dev:project <package-name>` | Replace with `core`, `ui`, `i18n`, `cornerstone`, `vtk`, etc. |
|
||||
| `test:unit` | Jest multi-project test runner; overall coverage |
|
||||
| **Deploy** | |
|
||||
| `build`* | Builds production output for our PWA Viewer |
|
||||
| `build:package`* | Builds commonjs bundles for all projects |
|
||||
| `build:package`* | Builds production `commonjs` output for our Viewer |
|
||||
| `build:package-all`* | Builds commonjs bundles for all projects |
|
||||
|
||||
|
||||
\* - For more information on our different builds, check out our [Deploy Docs][deployment-docs]
|
||||
|
||||
+30
-24
@@ -1,29 +1,35 @@
|
||||
const aliases = require("./aliases.config");
|
||||
const path = require("path");
|
||||
const aliases = require('./aliases.config');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
// https://babeljs.io/docs/en/options#babelrcroots
|
||||
// Also specified in .webpack/webpack.common.js
|
||||
// https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {
|
||||
ie: "11"
|
||||
}
|
||||
}
|
||||
ie: '11',
|
||||
},
|
||||
// https://babeljs.io/docs/en/babel-preset-env#usebuiltins
|
||||
useBuiltIns: 'usage',
|
||||
// https://babeljs.io/docs/en/babel-preset-env#corejs
|
||||
corejs: 3,
|
||||
},
|
||||
],
|
||||
"@babel/preset-react"
|
||||
'@babel/preset-react',
|
||||
],
|
||||
babelrcRoots: ["./platform/*", "./extensions/*"],
|
||||
// https://babeljs.io/docs/en/options#babelrcroots
|
||||
babelrcRoots: ['./platform/*', './extensions/*'],
|
||||
plugins: [
|
||||
"inline-react-svg",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-object-rest-spread",
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-transform-regenerator",
|
||||
"@babel/plugin-transform-runtime",
|
||||
'inline-react-svg',
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-transform-regenerator',
|
||||
'@babel/plugin-transform-runtime',
|
||||
[
|
||||
"module-resolver",
|
||||
'module-resolver',
|
||||
{
|
||||
// https://github.com/tleunen/babel-plugin-module-resolver/issues/338
|
||||
// There seem to be a bug with module-resolver with a mono-repo setup:
|
||||
@@ -33,18 +39,18 @@ module.exports = {
|
||||
// This will return undefined if aliases has no key for the sourcePath,
|
||||
// in which case module-resolver will fallback on its default behaviour.
|
||||
return aliases[sourcePath];
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
env: {
|
||||
debug: {
|
||||
sourceMaps: "inline",
|
||||
retainLines: true
|
||||
sourceMaps: 'inline',
|
||||
retainLines: true,
|
||||
},
|
||||
build: {
|
||||
ignore: ["**/*.test.jsx", "**/*.test.js", "__snapshots__", "__tests__"]
|
||||
}
|
||||
}
|
||||
ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'],
|
||||
},
|
||||
},
|
||||
// ignore: ["node_modules"]
|
||||
};
|
||||
@@ -1,11 +1,5 @@
|
||||
# Google Cloud Healthcare
|
||||
|
||||
> ATTENTION: The original documentation for this integration lives in the legacy
|
||||
> `version 1` Meteor documentation. You can
|
||||
> [find it here](/history/v1/connecting-to-image-archives/google-cloud-healthcare.html).
|
||||
> These docs will mirror the Meteor documentation until our `React`
|
||||
> implementation has been updated to work with Google Cloud Healthcare.
|
||||
|
||||
> The [Google Cloud Healthcare API](https://cloud.google.com/healthcare/) is a
|
||||
> powerful option for storing medical imaging data in the cloud.
|
||||
|
||||
@@ -16,10 +10,7 @@ store their data in the cloud. It offers an
|
||||
[almost-entirely complete DICOMWeb API](https://cloud.google.com/healthcare/docs/dicom)
|
||||
which requires tokens generated via the
|
||||
[OAuth 2.0 Sign In flow](https://developers.google.com/identity/sign-in/web/sign-in).
|
||||
Images can even be transcoded on the fly if this is desired. The Cloud
|
||||
Healthcare API is a very attractive option because it allows us to avoid
|
||||
deploying the Meteor server entirely. We can just deploy OHIF as a client-only
|
||||
static site application.
|
||||
Images can even be transcoded on the fly if this is desired.
|
||||
|
||||
## Setup a Google Cloud Healthcare Project
|
||||
|
||||
@@ -44,10 +35,10 @@ static site application.
|
||||
- Choose the "Web Application" type
|
||||
- Set up an
|
||||
[OAuth 2.0 Client ID](https://support.google.com/cloud/answer/6158849?hl=en)
|
||||
- Add your domain (e.g. `http://localhost:3000`) to Authorized JavaScript
|
||||
- Add your domain (e.g. `http://localhost:5000`) to Authorized JavaScript
|
||||
origins.
|
||||
- Add your domain, plus `_oauth/google` (e.g.
|
||||
`http://localhost:3000/_oauth/google`) to Authorized Redirect URIs.
|
||||
- Add your domain, plus `callback` (e.g.
|
||||
`http://localhost:5000/callback`) to Authorized Redirect URIs.
|
||||
- Save your Client ID for later.
|
||||
|
||||
- (Optional): Enable Public Datasets that are being hosted by Google:
|
||||
@@ -55,70 +46,26 @@ static site application.
|
||||
|
||||
## Run the viewer with your OAuth Client ID
|
||||
|
||||
1. Open the `config/oidc-googleCloud.json` file and change `YOURCLIENTID` to
|
||||
1. Open the `config/google.js` file and change `YOURCLIENTID` to
|
||||
your Client ID value.
|
||||
1. Run the OHIF Viewer using the oidc-googleCloud.json configuration file
|
||||
1. Run the OHIF Viewer using the config/google.js configuration file
|
||||
|
||||
```bash
|
||||
cd OHIFViewer
|
||||
METEOR_PACKAGE_DIRS="../Packages" meteor npm install
|
||||
METEOR_PACKAGE_DIRS="../Packages" meteor --settings ../config/oidc-googleCloud.json
|
||||
yarn install
|
||||
REACT_APP_CONFIG=config/google.js yarn run dev
|
||||
```
|
||||
|
||||
## Running via Docker
|
||||
|
||||
OHIF is also providing a Docker container which can connect to Google Cloud
|
||||
Healthcare with a Client ID which is provided at runtime. This is a very simple
|
||||
method to get up and running. Internally, the container is running
|
||||
[Nginx](https://nginx.org/) to serve the
|
||||
[Standalone Viewer](../standalone-viewer/usage.md).
|
||||
The OHIF Viewer Docker container can be connected to Google Cloud
|
||||
Healthcare by providing a Client ID at runtime. This is a very simple
|
||||
method to get up and running.
|
||||
|
||||
1. Install Docker (https://www.docker.com/)
|
||||
1. Run the Docker container, providing a Client ID as an environment variable.
|
||||
Client IDs look like `xyz.apps.googleusercontent.com`.
|
||||
|
||||
```bash
|
||||
docker run --env CLIENT_ID=$CLIENT_ID --publish 3000:80 ohif/viewer-google-cloud:latest
|
||||
```
|
||||
|
||||
## Building the ohif/viewer-google-cloud Docker Image
|
||||
|
||||
The
|
||||
[ohif/viewer-google-cloud](https://cloud.docker.com/u/ohif/repository/docker/ohif/viewer-google-cloud)
|
||||
Docker image is built as follows. The Dockerfile and nginx.conf are in the
|
||||
`/dockersupport/viewer-google-cloud` folder.
|
||||
|
||||
1. [Install Meteor](https://www.meteor.com/install)
|
||||
1. Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/OHIF/Viewers.git
|
||||
cd Viewers
|
||||
```
|
||||
|
||||
1. Install meteor-build-client-fixed2 so you can build the Standalone Viewer
|
||||
|
||||
```bash
|
||||
npm install -g meteor-build-client-fixed2
|
||||
```
|
||||
|
||||
1. Build the Standalone client-only OHIF Viewer
|
||||
|
||||
```bash
|
||||
cd OHIFViewer/
|
||||
METEOR_PACKAGE_DIRS="../Packages" meteor npm install
|
||||
METEOR_PACKAGE_DIRS="../Packages" meteor-build-client-fixed2 ../dockersupport/viewer-google-cloud/build -s ../config/oidc.json
|
||||
```
|
||||
|
||||
1. Build the Docker image
|
||||
|
||||
```bash
|
||||
cd ../dockersupport/viewer-google-cloud
|
||||
docker build -t ohif/viewer-google-cloud .
|
||||
```
|
||||
|
||||
1. Run the Docker image using an OAuth Client ID
|
||||
|
||||
```bash
|
||||
docker run --env CLIENT_ID={$someID}.apps.googleusercontent.com --publish 3000:80 ohif/viewer-google-cloud
|
||||
docker run --env CLIENT_ID=$CLIENT_ID --publish 5000:80 ohif/viewer:latest
|
||||
```
|
||||
@@ -88,7 +88,6 @@ _/public/config/default.js_
|
||||
```js
|
||||
window.config = {
|
||||
routerBasename: '/',
|
||||
relativeWebWorkerScriptsPath: '',
|
||||
servers: {
|
||||
dicomWeb: [
|
||||
{
|
||||
|
||||
@@ -50,8 +50,6 @@ include tags. Here's how it works:
|
||||
window.config = {
|
||||
// default: '/'
|
||||
routerBasename: '/',
|
||||
// default: ''
|
||||
relativeWebWorkerScriptsPath: '',
|
||||
servers: {
|
||||
dicomWeb: [
|
||||
{
|
||||
|
||||
@@ -24,7 +24,6 @@ _/public/config/default.js_
|
||||
```js
|
||||
window.config = {
|
||||
routerBasename: '/',
|
||||
relativeWebWorkerScriptsPath: '',
|
||||
servers: {
|
||||
dicomWeb: [
|
||||
{
|
||||
|
||||
@@ -104,7 +104,6 @@ like:
|
||||
```js
|
||||
window.config = {
|
||||
routerBasename: '/',
|
||||
relativeWebWorkerScriptsPath: '',
|
||||
servers: {
|
||||
dicomWeb: [
|
||||
{
|
||||
|
||||
@@ -1074,10 +1074,10 @@ gitbook-plugin-sitemap@^1.2.0:
|
||||
dependencies:
|
||||
sitemap "1.5.0"
|
||||
|
||||
gitbook-plugin-theme-cornerstone@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/gitbook-plugin-theme-cornerstone/-/gitbook-plugin-theme-cornerstone-1.1.3.tgz#320e1d688eaf27dbf8d580f285509b55984437fd"
|
||||
integrity sha512-fURj67XGQ5rZPj8LXbwEviMxLfWgN/s08t9Wnp1dQqffBUJwsLe00R/IeecOjsQHJ3Gvb8GjbXJ6qzIDGu5hPA==
|
||||
gitbook-plugin-theme-cornerstone@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/gitbook-plugin-theme-cornerstone/-/gitbook-plugin-theme-cornerstone-1.1.4.tgz#bc21b65acee2ac67e2ddb0986442ec448fe0c7fb"
|
||||
integrity sha512-BADgFyEKhkc0pPSBRwXa5VU2UoYQkd2cRwjrtjHyV6w4h/M7uyeWYFOcsgi2ju3rpHRCwF8lMg/TtDdAV8V1SQ==
|
||||
|
||||
gitbook-plugin-versions@^2.1.4:
|
||||
version "2.1.4"
|
||||
@@ -1608,9 +1608,9 @@ lodash.map@^4.4.0:
|
||||
integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=
|
||||
|
||||
lodash.merge@^4.4.0:
|
||||
version "4.6.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
|
||||
integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash.pad@^4.1.0:
|
||||
version "4.5.1"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
|
||||
//
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-development
|
||||
mode: 'development',
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-production
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifExtensionCornerstone',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,87 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.50.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.50.0-alpha.10...@ohif/extension-cornerstone@0.50.1) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.0.39-alpha.9...@ohif/extension-cornerstone@0.50.0-alpha.10) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.0.39-alpha.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.0.39-alpha.8...@ohif/extension-cornerstone@0.0.39-alpha.9) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.0.39-alpha.8 (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.39-alpha.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.0.39-alpha.6...@ohif/extension-cornerstone@0.0.39-alpha.7) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.39-alpha.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.0.39-alpha.5...@ohif/extension-cornerstone@0.0.39-alpha.6) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.39-alpha.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.0.39-alpha.4...@ohif/extension-cornerstone@0.0.39-alpha.5) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.39-alpha.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.0.39-alpha.3...@ohif/extension-cornerstone@0.0.39-alpha.4) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.39-alpha.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.0.39-alpha.2...@ohif/extension-cornerstone@0.0.39-alpha.3) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
return {
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
context: SRC_DIR,
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
symlinks: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: 'upward',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
ExtractCssChunks.loader,
|
||||
{ loader: 'css-loader', options: { importLoaders: 1 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: './postcss.config.js',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
||||
new ExtractCssChunks({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
// hot: true /* only necessary if hot reloading not function*/
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const common = require('./webpack.common');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = common(env, argv);
|
||||
|
||||
return merge(commonConfig, {
|
||||
mode: 'production',
|
||||
stats: {
|
||||
colors: false,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: true,
|
||||
chunkModules: true,
|
||||
modules: true,
|
||||
children: true,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifCornerstoneExtension',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
auxiliaryComment: 'Test Comment',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(gif|jpe?g|png|svg)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|woff2)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 50000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "0.0.39-alpha.2",
|
||||
"version": "0.50.1",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -8,8 +8,9 @@
|
||||
"main": "dist/index.umd.js",
|
||||
"module": "src/index.js",
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -19,19 +20,20 @@
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config config/webpack.prod.js -d",
|
||||
"dev": "webpack --config .webpack/webpack.dev.js --watch --debug --output-pathinfo",
|
||||
"dev:cornerstone": "yarn run dev",
|
||||
"build": "webpack --config .webpack/webpack.prod.js",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"dev": "webpack --config config/webpack.prod.js -w -d",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.11.1-alpha.0",
|
||||
"@ohif/ui": "^0.2.18-alpha.0",
|
||||
"@ohif/core": "^0.50.0",
|
||||
"@ohif/ui": "^0.50.0",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "^3.1.0",
|
||||
"cornerstone-wado-image-loader": "^2.2.3",
|
||||
"cornerstone-wado-image-loader": "^3.0.0",
|
||||
"dcmjs": "^0.3.8",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
@@ -43,10 +45,9 @@
|
||||
"redux": "^4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"classnames": "^2.2.6",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"react-cornerstone-viewport": "0.1.30"
|
||||
},
|
||||
"gitHead": "a5baa9228c0eda0df880136bde4420d78e6f8706"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,24 @@
|
||||
import CornerstoneViewport from "react-cornerstone-viewport";
|
||||
import OHIF from "@ohif/core";
|
||||
import { connect } from "react-redux";
|
||||
import throttle from "lodash.throttle";
|
||||
import CornerstoneViewport from 'react-cornerstone-viewport';
|
||||
import OHIF from '@ohif/core';
|
||||
import { connect } from 'react-redux';
|
||||
import throttle from 'lodash.throttle';
|
||||
|
||||
const { setViewportActive, setViewportSpecificData } = OHIF.redux.actions;
|
||||
const {
|
||||
onAdded,
|
||||
onRemoved,
|
||||
onModified,
|
||||
} = OHIF.measurements.MeasurementHandlers;
|
||||
|
||||
// TODO: Transition to enums for the action names so that we can ensure they stay up to date
|
||||
// everywhere they're used.
|
||||
const MEASUREMENT_ACTION_MAP = {
|
||||
added: onAdded,
|
||||
removed: onRemoved,
|
||||
modified: throttle(event => {
|
||||
return onModified(event);
|
||||
}, 300),
|
||||
};
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
let dataFromStore;
|
||||
@@ -37,7 +52,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
enableStackPrefetch: isActive,
|
||||
//stack: viewportSpecificData.stack,
|
||||
cineToolData: viewportSpecificData.cine,
|
||||
viewport: viewportSpecificData.viewport
|
||||
viewport: viewportSpecificData.viewport,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -64,28 +79,15 @@ const mapDispatchToProps = (dispatch, ownProps) => {
|
||||
dispatch(
|
||||
setViewportSpecificData(viewportIndex, {
|
||||
// TODO: Hack to make sure our plugin info is available from the outset
|
||||
plugin: "cornerstone",
|
||||
dom: enabledElement
|
||||
plugin: 'cornerstone',
|
||||
dom: enabledElement,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
onMeasurementsChanged: (event, action) => {
|
||||
const {
|
||||
onAdded,
|
||||
onRemoved,
|
||||
onModified
|
||||
} = OHIF.measurements.MeasurementHandlers;
|
||||
const actions = {
|
||||
added: onAdded,
|
||||
removed: onRemoved,
|
||||
modified: throttle(event => {
|
||||
return onModified(event);
|
||||
}, 300)
|
||||
};
|
||||
|
||||
return actions[action](event);
|
||||
}
|
||||
return MEASUREMENT_ACTION_MAP[action](event);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -202,6 +202,10 @@ class OHIFCornerstoneViewport extends Component {
|
||||
frameIndex
|
||||
} = displaySet;
|
||||
|
||||
if (!studyInstanceUid || !displaySetInstanceUid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sopClassUids && sopClassUids.length > 1) {
|
||||
console.warn(
|
||||
"More than one SOPClassUid in the same series is not yet supported."
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import cornerstoneTools from 'cornerstone-tools';
|
||||
import OHIF from '@ohif/core';
|
||||
const scroll = cornerstoneTools.import('util/scroll');
|
||||
|
||||
const actions = {
|
||||
rotateViewport: ({ viewports, rotation }) => {
|
||||
@@ -89,15 +91,76 @@ const actions = {
|
||||
// TODO
|
||||
console.warn('updateDisplaySet: ', direction);
|
||||
},
|
||||
clearAnnotations: () => {
|
||||
console.warn('clearAnnotations: not yet implemented');
|
||||
// const toolState =
|
||||
// cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
|
||||
// if (!toolState) return;
|
||||
// Object.keys(toolState).forEach(imageId => {
|
||||
// if (!cornerstoneImageId || cornerstoneImageId === imageId)
|
||||
// delete toolState[imageId];
|
||||
// });
|
||||
clearAnnotations: ({ viewports }) => {
|
||||
const element = _getActiveViewportEnabledElement(
|
||||
viewports.viewportSpecificData,
|
||||
viewports.activeViewportIndex
|
||||
);
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
const enabledElement = cornerstone.getEnabledElement(element);
|
||||
if (!enabledElement || !enabledElement.image) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
toolState,
|
||||
} = cornerstoneTools.globalImageIdSpecificToolStateManager;
|
||||
if (
|
||||
!toolState ||
|
||||
toolState.hasOwnProperty(enabledElement.image.imageId) === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const imageIdToolState = toolState[enabledElement.image.imageId];
|
||||
|
||||
const measurementsToRemove = [];
|
||||
|
||||
Object.keys(imageIdToolState).forEach(toolType => {
|
||||
const { data } = imageIdToolState[toolType];
|
||||
|
||||
data.forEach(measurementData => {
|
||||
const { _id, lesionNamingNumber, measurementNumber } = measurementData;
|
||||
if (!_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
measurementsToRemove.push({
|
||||
toolType,
|
||||
_id,
|
||||
lesionNamingNumber,
|
||||
measurementNumber,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
measurementsToRemove.forEach(measurementData => {
|
||||
OHIF.measurements.MeasurementHandlers.onRemoved({
|
||||
detail: {
|
||||
toolType: measurementData.toolType,
|
||||
measurementData,
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
nextImage: ({ viewports }) => {
|
||||
const enabledElement = _getActiveViewportEnabledElement(
|
||||
viewports.viewportSpecificData,
|
||||
viewports.activeViewportIndex
|
||||
);
|
||||
|
||||
scroll(enabledElement, 1);
|
||||
},
|
||||
previousImage: ({ viewports }) => {
|
||||
const enabledElement = _getActiveViewportEnabledElement(
|
||||
viewports.viewportSpecificData,
|
||||
viewports.activeViewportIndex
|
||||
);
|
||||
|
||||
scroll(enabledElement, -1);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -147,8 +210,21 @@ const definitions = {
|
||||
storeContexts: ['viewports'],
|
||||
options: {},
|
||||
},
|
||||
// TODO: Clear Annotations
|
||||
// TODO: Next/Previous image
|
||||
clearAnnotations: {
|
||||
commandFn: actions.clearAnnotations,
|
||||
storeContexts: ['viewports'],
|
||||
options: {},
|
||||
},
|
||||
nextImage: {
|
||||
commandFn: actions.nextImage,
|
||||
storeContexts: ['viewports'],
|
||||
options: {},
|
||||
},
|
||||
previousImage: {
|
||||
commandFn: actions.previousImage,
|
||||
storeContexts: ['viewports'],
|
||||
options: {},
|
||||
},
|
||||
// TODO: First/Last image
|
||||
// Next/Previous series/DisplaySet
|
||||
nextViewportDisplaySet: {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// -- ACTIVE_ROUTE::VIEWER
|
||||
// -- ACTIVE_VIEWPORT::CORNERSTONE
|
||||
// setToolActive commands should receive the button event that triggered
|
||||
// so we can do the "bind to this butyon" magic
|
||||
// so we can do the "bind to this button" magic
|
||||
|
||||
const TOOLBAR_BUTTON_TYPES = {
|
||||
COMMAND: 'command',
|
||||
@@ -98,6 +98,98 @@ const definitions = [
|
||||
behavior: 'CINE',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'More',
|
||||
label: 'More',
|
||||
icon: 'ellipse-circle',
|
||||
buttons: [
|
||||
{
|
||||
id: 'Magnify',
|
||||
label: 'Magnify',
|
||||
icon: 'circle',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Magnify' },
|
||||
},
|
||||
{
|
||||
id: 'WwwcRegion',
|
||||
label: 'ROI Window',
|
||||
icon: 'stop',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'WwwcRegion' },
|
||||
},
|
||||
{
|
||||
id: 'DragProbe',
|
||||
label: 'Probe',
|
||||
icon: 'dot-circle',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'DragProbe' },
|
||||
},
|
||||
{
|
||||
id: 'EllipticalRoi',
|
||||
label: 'Ellipse',
|
||||
icon: 'circle-o',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'EllipticalRoi' },
|
||||
},
|
||||
{
|
||||
id: 'RectangleRoi',
|
||||
label: 'Rectangle',
|
||||
icon: 'square-o',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'RectangleRoi' },
|
||||
},
|
||||
{
|
||||
id: 'Invert',
|
||||
label: 'Invert',
|
||||
icon: 'adjust',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'invertViewport',
|
||||
},
|
||||
{
|
||||
id: 'RotateRight',
|
||||
label: 'Rotate Right',
|
||||
icon: 'rotate-right',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'rotateViewportCW',
|
||||
},
|
||||
{
|
||||
id: 'FlipH',
|
||||
label: 'Flip H',
|
||||
icon: 'ellipse-h',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'flipViewportHorizontal',
|
||||
},
|
||||
{
|
||||
id: 'FlipV',
|
||||
label: 'Flip V',
|
||||
icon: 'ellipse-v',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'flipViewportVertical',
|
||||
},
|
||||
{
|
||||
id: 'Clear',
|
||||
label: 'Clear',
|
||||
icon: 'trash',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'clearAnnotations',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
|
||||
//
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-development
|
||||
mode: 'development',
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-production
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifExtensionDicomHtml',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,87 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.50.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.0-alpha.10...@ohif/extension-dicom-html@0.50.1) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.0.4-alpha.9...@ohif/extension-dicom-html@0.50.0-alpha.10) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.0.4-alpha.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.0.4-alpha.8...@ohif/extension-dicom-html@0.0.4-alpha.9) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.0.4-alpha.8 (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.4-alpha.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.0.4-alpha.6...@ohif/extension-dicom-html@0.0.4-alpha.7) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.4-alpha.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.0.4-alpha.5...@ohif/extension-dicom-html@0.0.4-alpha.6) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.4-alpha.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.0.4-alpha.4...@ohif/extension-dicom-html@0.0.4-alpha.5) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.4-alpha.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.0.4-alpha.3...@ohif/extension-dicom-html@0.0.4-alpha.4) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.4-alpha.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.0.4-alpha.2...@ohif/extension-dicom-html@0.0.4-alpha.3) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
return {
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
context: SRC_DIR,
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
symlinks: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: 'upward',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
ExtractCssChunks.loader,
|
||||
{ loader: 'css-loader', options: { importLoaders: 1 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: './postcss.config.js',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
||||
new ExtractCssChunks({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
// hot: true /* only necessary if hot reloading not function*/
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const common = require('./webpack.common');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = common(env, argv);
|
||||
|
||||
return merge(commonConfig, {
|
||||
mode: 'production',
|
||||
stats: {
|
||||
colors: false,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: true,
|
||||
chunkModules: true,
|
||||
modules: true,
|
||||
children: true,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifCornerstoneExtension',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
auxiliaryComment: 'Test Comment',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(gif|jpe?g|png|svg)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|woff2)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 50000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-html",
|
||||
"version": "0.0.4-alpha.2",
|
||||
"version": "0.50.1",
|
||||
"description": "OHIF extension for rendering structured reports to HTML",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -8,25 +8,9 @@
|
||||
"main": "dist/index.umd.js",
|
||||
"module": "src/index.js",
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "webpack --config config/webpack.prod.js -w -d",
|
||||
"build": "webpack --config config/webpack.prod.js -d",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.11.1-alpha.0",
|
||||
"dcmjs": "^0.3.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^15.0.0 || ^16.0.0",
|
||||
"react-dom": "^15.0.0 || ^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0"
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -35,5 +19,22 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "a5baa9228c0eda0df880136bde4420d78e6f8706"
|
||||
"scripts": {
|
||||
"dev": "webpack --config .webpack/webpack.dev.js --watch --debug --output-pathinfo",
|
||||
"dev:dicom-html": "yarn run dev",
|
||||
"build": "webpack --config .webpack/webpack.prod.js",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.50.0",
|
||||
"dcmjs": "^0.3.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^15.0.0 || ^16.0.0",
|
||||
"react-dom": "^15.0.0 || ^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
import { MODULE_TYPES, utils } from "@ohif/core";
|
||||
import { MODULE_TYPES, utils } from '@ohif/core';
|
||||
|
||||
// TODO: Should probably use dcmjs for this
|
||||
const SOP_CLASS_UIDS = {
|
||||
BASIC_TEXT_SR: "1.2.840.10008.5.1.4.1.1.88.11",
|
||||
ENHANCED_SR: "1.2.840.10008.5.1.4.1.1.88.22",
|
||||
COMPREHENSIVE_SR: "1.2.840.10008.5.1.4.1.1.88.33",
|
||||
PROCEDURE_LOG_STORAGE: "1.2.840.10008.5.1.4.1.1.88.40",
|
||||
MAMMOGRAPHY_CAD_SR: "1.2.840.10008.5.1.4.1.1.88.50",
|
||||
CHEST_CAD_SR: "1.2.840.10008.5.1.4.1.1.88.65",
|
||||
X_RAY_RADIATION_DOSE_SR: "1.2.840.10008.5.1.4.1.1.88.67"
|
||||
BASIC_TEXT_SR: '1.2.840.10008.5.1.4.1.1.88.11',
|
||||
ENHANCED_SR: '1.2.840.10008.5.1.4.1.1.88.22',
|
||||
COMPREHENSIVE_SR: '1.2.840.10008.5.1.4.1.1.88.33',
|
||||
PROCEDURE_LOG_STORAGE: '1.2.840.10008.5.1.4.1.1.88.40',
|
||||
MAMMOGRAPHY_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.50',
|
||||
CHEST_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.65',
|
||||
X_RAY_RADIATION_DOSE_SR: '1.2.840.10008.5.1.4.1.1.88.67',
|
||||
};
|
||||
|
||||
const sopClassUids = Object.values(SOP_CLASS_UIDS);
|
||||
@@ -16,23 +16,24 @@ const sopClassUids = Object.values(SOP_CLASS_UIDS);
|
||||
// TODO: Handle the case where there is more than one SOP Class Handler for the
|
||||
// same SOP Class
|
||||
const OHIFDicomHtmlSopClassHandler = {
|
||||
id: "OHIFDicomHtmlSopClassHandler",
|
||||
id: 'OHIFDicomHtmlSopClassHandler',
|
||||
type: MODULE_TYPES.SOP_CLASS_HANDLER,
|
||||
sopClassUids,
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient, authorizationHeaders) {
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
return {
|
||||
plugin: "html",
|
||||
plugin: 'html',
|
||||
modality: 'SR',
|
||||
displaySetInstanceUid: utils.guid(),
|
||||
wadoRoot: study.getData().wadoRoot,
|
||||
wadoUri: instance.getData().wadouri,
|
||||
sopInstanceUid: instance.getSOPInstanceUID(),
|
||||
seriesInstanceUid: series.getSeriesInstanceUID(),
|
||||
studyInstanceUid: study.getStudyInstanceUID(),
|
||||
authorizationHeaders
|
||||
authorizationHeaders,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default OHIFDicomHtmlSopClassHandler;
|
||||
@@ -0,0 +1,16 @@
|
||||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
|
||||
//
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-development
|
||||
mode: 'development',
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-production
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifExtensionDicomMicroscopy',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,87 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.50.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.50.0-alpha.10...@ohif/extension-dicom-microscopy@0.50.1) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.0.9-alpha.9...@ohif/extension-dicom-microscopy@0.50.0-alpha.10) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.0.9-alpha.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.0.9-alpha.8...@ohif/extension-dicom-microscopy@0.0.9-alpha.9) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.0.9-alpha.8 (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.9-alpha.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.0.9-alpha.6...@ohif/extension-dicom-microscopy@0.0.9-alpha.7) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.9-alpha.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.0.9-alpha.5...@ohif/extension-dicom-microscopy@0.0.9-alpha.6) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.9-alpha.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.0.9-alpha.4...@ohif/extension-dicom-microscopy@0.0.9-alpha.5) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.9-alpha.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.0.9-alpha.3...@ohif/extension-dicom-microscopy@0.0.9-alpha.4) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.9-alpha.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.0.9-alpha.2...@ohif/extension-dicom-microscopy@0.0.9-alpha.3) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
return {
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
context: SRC_DIR,
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
symlinks: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: 'upward',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
ExtractCssChunks.loader,
|
||||
{ loader: 'css-loader', options: { importLoaders: 1 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: './postcss.config.js',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
||||
new ExtractCssChunks({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
// hot: true /* only necessary if hot reloading not function*/
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const common = require('./webpack.common');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = common(env, argv);
|
||||
|
||||
return merge(commonConfig, {
|
||||
mode: 'production',
|
||||
stats: {
|
||||
colors: false,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: true,
|
||||
chunkModules: true,
|
||||
modules: true,
|
||||
children: true,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifCornerstoneExtension',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
auxiliaryComment: 'Test Comment',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(gif|jpe?g|png|svg)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|woff2)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 50000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-microscopy",
|
||||
"version": "0.0.9-alpha.2",
|
||||
"version": "0.50.1",
|
||||
"description": "OHIF extension for Dicom Microscopy",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -10,30 +10,31 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config config/webpack.prod.js -d",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"dev": "webpack --config config/webpack.prod.js -w -d",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "webpack --config .webpack/webpack.dev.js --watch --debug --output-pathinfo",
|
||||
"dev:dicom-microscopy": "yarn run dev",
|
||||
"build": "webpack --config .webpack/webpack.prod.js",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.11.1-alpha.0",
|
||||
"@ohif/core": "^0.50.0",
|
||||
"react": "^15.0.0 || ^16.0.0",
|
||||
"react-dom": "^15.0.0 || ^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"classnames": "^2.2.6",
|
||||
"dicom-microscopy-viewer": "^0.4.3"
|
||||
},
|
||||
"gitHead": "a5baa9228c0eda0df880136bde4420d78e6f8706"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import OHIF from "@ohif/core";
|
||||
import OHIF from '@ohif/core';
|
||||
|
||||
const { utils } = OHIF;
|
||||
|
||||
const SOP_CLASS_UIDS = {
|
||||
VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: "1.2.840.10008.5.1.4.1.1.77.1.6"
|
||||
VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6',
|
||||
};
|
||||
|
||||
const DicomMicroscopySopClassHandler = {
|
||||
id: "DicomMicroscopySopClassHandlerPlugin",
|
||||
id: 'DicomMicroscopySopClassHandlerPlugin',
|
||||
sopClassUids: [SOP_CLASS_UIDS.VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE],
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient) {
|
||||
const instance = series.getFirstInstance();
|
||||
@@ -15,14 +15,15 @@ const DicomMicroscopySopClassHandler = {
|
||||
// Note: We are passing the dicomweb client into each viewport!
|
||||
|
||||
return {
|
||||
plugin: "microscopy",
|
||||
plugin: 'microscopy',
|
||||
modality: 'SM',
|
||||
displaySetInstanceUid: utils.guid(),
|
||||
dicomWebClient,
|
||||
sopInstanceUid: instance.getSOPInstanceUID(),
|
||||
seriesInstanceUid: series.getSeriesInstanceUID(),
|
||||
studyInstanceUid: study.getStudyInstanceUID()
|
||||
studyInstanceUid: study.getStudyInstanceUID(),
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default DicomMicroscopySopClassHandler;
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import ReactResizeDetector from 'react-resize-detector';
|
||||
import { api } from 'dicom-microscopy-viewer';
|
||||
import debounce from 'lodash.debounce';
|
||||
|
||||
const microscopyViewer = api.VLWholeSlideMicroscopyImageViewer;
|
||||
|
||||
@@ -9,10 +10,16 @@ class DicomMicroscopyViewport extends Component {
|
||||
error: null,
|
||||
};
|
||||
|
||||
viewer = null;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.container = React.createRef();
|
||||
|
||||
this.debouncedResize = debounce(() => {
|
||||
if (this.viewer) this.viewer.resize();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// install the microscopy renderer into the web page.
|
||||
@@ -52,17 +59,18 @@ class DicomMicroscopyViewport extends Component {
|
||||
.then(metadata => {
|
||||
metadata = metadata.filter(m => m);
|
||||
|
||||
const viewer = new microscopyViewer({
|
||||
this.viewer = new microscopyViewer({
|
||||
client: dicomWebClient,
|
||||
metadata,
|
||||
retrieveRendered: false
|
||||
});
|
||||
|
||||
viewer.render({ container, retrieveRendered: true });
|
||||
this.viewer.render({ container });
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { studies, displaySet } = this.props.viewportData;
|
||||
const { displaySet } = this.props.viewportData;
|
||||
|
||||
this.installOpenLayersRenderer(this.container.current, displaySet);
|
||||
}
|
||||
@@ -71,6 +79,13 @@ class DicomMicroscopyViewport extends Component {
|
||||
const style = { width: '100%', height: '100%' };
|
||||
return (
|
||||
<div className={'DicomMicroscopyViewer'} style={style}>
|
||||
{ReactResizeDetector && (
|
||||
<ReactResizeDetector
|
||||
handleWidth
|
||||
handleHeight
|
||||
onResize={this.onWindowResize}
|
||||
/>
|
||||
)}
|
||||
{this.state.error ? (
|
||||
<h2>{JSON.stringify(this.state.error)}</h2>
|
||||
) : (
|
||||
@@ -79,6 +94,10 @@ class DicomMicroscopyViewport extends Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onWindowResize = () => {
|
||||
this.debouncedResize();
|
||||
};
|
||||
}
|
||||
|
||||
export default DicomMicroscopyViewport;
|
||||
@@ -0,0 +1,16 @@
|
||||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
|
||||
//
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-development
|
||||
mode: 'development',
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-production
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifExtensionDicomPdf',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,87 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.50.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.50.0-alpha.10...@ohif/extension-dicom-pdf@0.50.1) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.0.8-alpha.9...@ohif/extension-dicom-pdf@0.50.0-alpha.10) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.0.8-alpha.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.0.8-alpha.8...@ohif/extension-dicom-pdf@0.0.8-alpha.9) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.0.8-alpha.8 (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.8-alpha.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.0.8-alpha.6...@ohif/extension-dicom-pdf@0.0.8-alpha.7) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.8-alpha.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.0.8-alpha.5...@ohif/extension-dicom-pdf@0.0.8-alpha.6) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.8-alpha.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.0.8-alpha.4...@ohif/extension-dicom-pdf@0.0.8-alpha.5) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.8-alpha.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.0.8-alpha.3...@ohif/extension-dicom-pdf@0.0.8-alpha.4) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.8-alpha.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.0.8-alpha.2...@ohif/extension-dicom-pdf@0.0.8-alpha.3) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
return {
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
context: SRC_DIR,
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
symlinks: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: 'upward',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
ExtractCssChunks.loader,
|
||||
{ loader: 'css-loader', options: { importLoaders: 1 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: './postcss.config.js',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
||||
new ExtractCssChunks({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
// hot: true /* only necessary if hot reloading not function*/
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const common = require('./webpack.common');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = common(env, argv);
|
||||
|
||||
return merge(commonConfig, {
|
||||
mode: 'production',
|
||||
stats: {
|
||||
colors: false,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: true,
|
||||
chunkModules: true,
|
||||
modules: true,
|
||||
children: true,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifCornerstoneExtension',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
auxiliaryComment: 'Test Comment',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(gif|jpe?g|png|svg)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|woff2)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 50000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-pdf",
|
||||
"version": "0.0.8-alpha.2",
|
||||
"version": "0.50.1",
|
||||
"description": "OHIF extension for Dicom PDF",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -11,29 +11,31 @@
|
||||
"access": "public"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "webpack --config config/webpack.prod.js -w -d",
|
||||
"build": "webpack --config config/webpack.prod.js -d",
|
||||
"dev": "webpack --config .webpack/webpack.dev.js --watch --debug --output-pathinfo",
|
||||
"dev:dicom-pdf": "yarn run dev",
|
||||
"build": "webpack --config .webpack/webpack.prod.js",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.11.1-alpha.0",
|
||||
"@ohif/core": "^0.50.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^15.0.0 || ^16.0.0",
|
||||
"react-dom": "^15.0.0 || ^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"classnames": "^2.2.6",
|
||||
"lodash.isequal": "^4.5.0"
|
||||
},
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
import { MODULE_TYPES, utils } from "@ohif/core";
|
||||
import { MODULE_TYPES, utils } from '@ohif/core';
|
||||
|
||||
// TODO: Should probably use dcmjs for this
|
||||
const SOP_CLASS_UIDS = {
|
||||
ENCAPSULATED_PDF: "1.2.840.10008.5.1.4.1.1.104.1"
|
||||
ENCAPSULATED_PDF: '1.2.840.10008.5.1.4.1.1.104.1',
|
||||
};
|
||||
|
||||
const OHIFDicomPDFSopClassHandler = {
|
||||
id: "OHIFDicomPDFSopClassHandlerPlugin",
|
||||
id: 'OHIFDicomPDFSopClassHandlerPlugin',
|
||||
type: MODULE_TYPES.SOP_CLASS_HANDLER,
|
||||
sopClassUids: [SOP_CLASS_UIDS.ENCAPSULATED_PDF],
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient, authorizationHeaders) {
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
return {
|
||||
plugin: "pdf",
|
||||
plugin: 'pdf',
|
||||
modality: 'DOC',
|
||||
displaySetInstanceUid: utils.guid(),
|
||||
wadoRoot: study.getData().wadoRoot,
|
||||
wadoUri: instance.getData().wadouri,
|
||||
sopInstanceUid: instance.getSOPInstanceUID(),
|
||||
seriesInstanceUid: series.getSeriesInstanceUID(),
|
||||
studyInstanceUid: study.getStudyInstanceUID(),
|
||||
authorizationHeaders: authorizationHeaders
|
||||
authorizationHeaders: authorizationHeaders,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default OHIFDicomPDFSopClassHandler;
|
||||
@@ -0,0 +1,16 @@
|
||||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
|
||||
//
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-development
|
||||
mode: 'development',
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-production
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifExtensionVtk',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,87 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.50.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.0-alpha.10...@ohif/extension-vtk@0.50.1) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.1.4-alpha.9...@ohif/extension-vtk@0.50.0-alpha.10) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.1.4-alpha.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.1.4-alpha.8...@ohif/extension-vtk@0.1.4-alpha.9) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.1.4-alpha.8 (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.1.4-alpha.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.1.4-alpha.6...@ohif/extension-vtk@0.1.4-alpha.7) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.1.4-alpha.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.1.4-alpha.5...@ohif/extension-vtk@0.1.4-alpha.6) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.1.4-alpha.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.1.4-alpha.4...@ohif/extension-vtk@0.1.4-alpha.5) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.1.4-alpha.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.1.4-alpha.3...@ohif/extension-vtk@0.1.4-alpha.4) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.1.4-alpha.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.1.4-alpha.2...@ohif/extension-vtk@0.1.4-alpha.3) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
+20
-19
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-vtk",
|
||||
"version": "0.1.4-alpha.2",
|
||||
"version": "0.50.1",
|
||||
"description": "OHIF extension for VTK.js",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -11,23 +11,29 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --progress --colors --mode production",
|
||||
"dev": "webpack --config .webpack/webpack.dev.js --watch --debug --output-pathinfo",
|
||||
"dev:dicom-vtk": "yarn run dev",
|
||||
"build": "webpack --config .webpack/webpack.prod.js",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"dev": "webpack --watch --progress --colors --mode development",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^0.11.1-alpha.0",
|
||||
"@ohif/i18n": "^0.2.3",
|
||||
"@ohif/ui": "^0.2.18-alpha.0",
|
||||
"@ohif/core": "^0.50.0",
|
||||
"@ohif/i18n": "^0.50.0",
|
||||
"@ohif/ui": "^0.50.0",
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-wado-image-loader": "^2.2.3",
|
||||
"cornerstone-wado-image-loader": "^3.0.0",
|
||||
"dcmjs": "^0.4.7",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"i18next": "^17.0.3",
|
||||
@@ -41,15 +47,15 @@
|
||||
"redux": "^4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.4.5",
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"react-vtkjs-viewport": "0.0.9",
|
||||
"vtk.js": "^8.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohif/core": "^0.11.1-alpha.2",
|
||||
"@ohif/ui": "^0.2.18-alpha.2",
|
||||
"@ohif/core": "^0.50.1",
|
||||
"@ohif/ui": "^0.50.1",
|
||||
"cornerstone-tools": "^3.13.0",
|
||||
"cornerstone-wado-image-loader": "^2.2.3",
|
||||
"cornerstone-wado-image-loader": "^3.0.0",
|
||||
"dcmjs": "^0.4.7",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"gh-pages": "^2.0.1",
|
||||
@@ -58,10 +64,5 @@
|
||||
"react-i18next": "^10.11.0",
|
||||
"react-redux": "^7.1.0",
|
||||
"redux": "^4.0.1"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"gitHead": "a5baa9228c0eda0df880136bde4420d78e6f8706"
|
||||
}
|
||||
}
|
||||
@@ -189,6 +189,18 @@ class OHIFVTKViewport extends Component {
|
||||
volumeActor.setMapper(volumeMapper);
|
||||
volumeMapper.setInputData(data);
|
||||
|
||||
// TODO: Should look into implementing autoAdjustSampleDistance in vtk
|
||||
const sampleDistance =
|
||||
1.2 *
|
||||
Math.sqrt(
|
||||
data
|
||||
.getSpacing()
|
||||
.map((v) => v * v)
|
||||
.reduce((a, b) => a + b, 0)
|
||||
);
|
||||
|
||||
volumeMapper.setSampleDistance(sampleDistance);
|
||||
|
||||
volumeCache[displaySetInstanceUid] = volumeActor;
|
||||
|
||||
return volumeActor;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
vtkInteractorStyleMPRCrosshairs,
|
||||
vtkInteractorStyleMPRSlice,
|
||||
vtkInteractorStyleMPRWindowLevel,
|
||||
vtkInteractorStyleMPRSlice,
|
||||
vtkSVGCrosshairsWidget,
|
||||
vtkSVGWidgetManager,
|
||||
} from 'react-vtkjs-viewport';
|
||||
@@ -11,9 +11,13 @@ import setViewportToVTK from './utils/setViewportToVTK.js';
|
||||
import vtkCoordinate from 'vtk.js/Sources/Rendering/Core/Coordinate';
|
||||
import vtkMath from 'vtk.js/Sources/Common/Core/Math';
|
||||
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
|
||||
import Constants from 'vtk.js/Sources/Rendering/Core/VolumeMapper/Constants.js';
|
||||
|
||||
const { BlendMode } = Constants;
|
||||
|
||||
// TODO: Put this somewhere else
|
||||
let apis = {};
|
||||
let currentSlabThickness = 0.1;
|
||||
|
||||
function getCrosshairCallbackForIndex(index) {
|
||||
return ({ worldPos }) => {
|
||||
@@ -96,26 +100,24 @@ function _setView(api, sliceNormal, viewUp) {
|
||||
istyle.setSliceNormal(...sliceNormal);
|
||||
camera.setViewUp(...viewUp);
|
||||
|
||||
api.volumes[0].getMapper().setSampleDistance(5.0);
|
||||
api.volumes[0].getMapper().setMaximumSamplesPerRay(2000);
|
||||
|
||||
renderWindow.render();
|
||||
}
|
||||
|
||||
function switchMPRInteractors(api, istyle) {
|
||||
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||
const renderer = api.genericRenderWindow.getRenderer();
|
||||
const camera = renderer.getActiveCamera();
|
||||
const currentIStyle = renderWindow.getInteractor().getInteractorStyle();
|
||||
|
||||
let currentNormal;
|
||||
if (istyle.getSliceNormal) {
|
||||
currentNormal = istyle.getSliceNormal();
|
||||
if (currentIStyle.getSliceNormal && istyle.getSliceNormal) {
|
||||
currentNormal = currentIStyle.getSliceNormal();
|
||||
}
|
||||
|
||||
// TODO: This is a hacky workaround because disabling the vtkInteractorStyleMPRSlice is currently
|
||||
// broken. The camera.onModified is never removed. (https://github.com/Kitware/vtk-js/issues/1110)
|
||||
renderWindow
|
||||
.getInteractor()
|
||||
.getInteractorStyle()
|
||||
.setInteractor(null);
|
||||
let currentSlabThickness;
|
||||
if (currentIStyle.getSlabThickness && istyle.getSlabThickness) {
|
||||
currentSlabThickness = currentIStyle.getSlabThickness();
|
||||
}
|
||||
|
||||
renderWindow.getInteractor().setInteractorStyle(istyle);
|
||||
|
||||
@@ -126,6 +128,11 @@ function switchMPRInteractors(api, istyle) {
|
||||
if (currentNormal) {
|
||||
istyle.setSliceNormal(currentNormal);
|
||||
}
|
||||
|
||||
if (currentSlabThickness) {
|
||||
istyle.setSlabThickness(currentSlabThickness);
|
||||
}
|
||||
|
||||
istyle.setVolumeMapper(api.volumes[0]);
|
||||
}
|
||||
}
|
||||
@@ -152,14 +159,14 @@ const actions = {
|
||||
|
||||
_setView(api, [0, 1, 0], [0, 0, 1]);
|
||||
},
|
||||
enableRotateTool: async ({ viewports }) => {
|
||||
enableRotateTool: () => {
|
||||
apis.forEach(api => {
|
||||
const istyle = vtkInteractorStyleMPRSlice.newInstance();
|
||||
|
||||
switchMPRInteractors(api, istyle);
|
||||
});
|
||||
},
|
||||
enableCrosshairsTool: async ({ viewports }) => {
|
||||
enableCrosshairsTool: () => {
|
||||
apis.forEach((api, index) => {
|
||||
const istyle = vtkInteractorStyleMPRCrosshairs.newInstance();
|
||||
|
||||
@@ -168,13 +175,61 @@ const actions = {
|
||||
istyle.setCallback(getCrosshairCallbackForIndex(index));
|
||||
});
|
||||
},
|
||||
enableLevelTool: async ({ viewports }) => {
|
||||
enableLevelTool: () => {
|
||||
apis.forEach(api => {
|
||||
const istyle = vtkInteractorStyleMPRWindowLevel.newInstance();
|
||||
|
||||
switchMPRInteractors(api, istyle);
|
||||
});
|
||||
},
|
||||
setSlabThickness: slabThickness => {
|
||||
currentSlabThickness = slabThickness;
|
||||
|
||||
apis.forEach(api => {
|
||||
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||
const istyle = renderWindow.getInteractor().getInteractorStyle();
|
||||
|
||||
if (istyle.setSlabThickness) {
|
||||
istyle.setSlabThickness(currentSlabThickness);
|
||||
|
||||
// TODO: Do this inside the interactors in a setSlabThickness function instead
|
||||
const renderer = api.genericRenderWindow.getRenderer();
|
||||
const camera = renderer.getActiveCamera();
|
||||
const dist = camera.getDistance();
|
||||
const near = dist - currentSlabThickness / 2;
|
||||
const far = dist + currentSlabThickness / 2;
|
||||
|
||||
camera.setClippingRange(near, far);
|
||||
}
|
||||
|
||||
renderWindow.render();
|
||||
});
|
||||
},
|
||||
changeSlabThickness: ({ change }) => {
|
||||
currentSlabThickness += change;
|
||||
currentSlabThickness = Math.max(currentSlabThickness, 0.1);
|
||||
|
||||
apis.forEach(api => {
|
||||
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||
const istyle = renderWindow.getInteractor().getInteractorStyle();
|
||||
|
||||
if (istyle.setSlabThickness) {
|
||||
istyle.setSlabThickness(currentSlabThickness);
|
||||
}
|
||||
|
||||
renderWindow.render();
|
||||
});
|
||||
},
|
||||
setBlendMode: ({ blendMode }) => {
|
||||
apis.forEach(api => {
|
||||
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||
const istyle = renderWindow.getInteractor().getInteractorStyle();
|
||||
|
||||
api.volumes[0].getMapper().setBlendMode(blendMode);
|
||||
|
||||
renderWindow.render();
|
||||
});
|
||||
},
|
||||
mpr2d: async ({ viewports }) => {
|
||||
const displaySet =
|
||||
viewports.viewportSpecificData[viewports.activeViewportIndex];
|
||||
@@ -199,20 +254,11 @@ const actions = {
|
||||
});
|
||||
});*/
|
||||
|
||||
apis[0].volumes[0].getMapper().setSampleDistance(1.5);
|
||||
|
||||
apiByViewport.forEach((api, index) => {
|
||||
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||
const renderer = api.genericRenderWindow.getRenderer();
|
||||
const camera = renderer.getActiveCamera();
|
||||
|
||||
// TODO: This is a hacky workaround because disabling the vtkInteractorStyleMPRSlice is currently
|
||||
// broken. The camera.onModified is never removed. (https://github.com/Kitware/vtk-js/issues/1110)
|
||||
renderWindow
|
||||
.getInteractor()
|
||||
.getInteractorStyle()
|
||||
.setInteractor(null);
|
||||
|
||||
const istyle = vtkInteractorStyleMPRCrosshairs.newInstance();
|
||||
renderWindow.getInteractor().setInteractorStyle(istyle);
|
||||
|
||||
@@ -258,6 +304,8 @@ const actions = {
|
||||
},
|
||||
};
|
||||
|
||||
window.vtkActions = actions;
|
||||
|
||||
const definitions = {
|
||||
axial: {
|
||||
commandFn: actions.axial,
|
||||
@@ -276,19 +324,59 @@ const definitions = {
|
||||
},
|
||||
enableRotateTool: {
|
||||
commandFn: actions.enableRotateTool,
|
||||
storeContexts: ['viewports'],
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
},
|
||||
enableCrosshairsTool: {
|
||||
commandFn: actions.enableCrosshairsTool,
|
||||
storeContexts: ['viewports'],
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
},
|
||||
enableLevelTool: {
|
||||
commandFn: actions.enableLevelTool,
|
||||
storeContexts: ['viewports'],
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
},
|
||||
setBlendModeToComposite: {
|
||||
commandFn: actions.setBlendMode,
|
||||
storeContexts: [],
|
||||
options: { blendMode: BlendMode.COMPOSITE_BLEND },
|
||||
},
|
||||
setBlendModeToMaximumIntensity: {
|
||||
commandFn: actions.setBlendMode,
|
||||
storeContexts: [],
|
||||
options: { blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND },
|
||||
},
|
||||
setBlendModeToMinimumIntensity: {
|
||||
commandFn: actions.setBlendMode,
|
||||
storeContexts: [],
|
||||
options: { blendMode: BlendMode.MINIMUM_INTENSITY_BLEND },
|
||||
},
|
||||
setBlendModeToAverageIntensity: {
|
||||
commandFn: actions.setBlendMode,
|
||||
storeContexts: [],
|
||||
options: { blendMode: BlendMode.AVERAGE_INTENSITY_BLEND },
|
||||
},
|
||||
setSlabThickness: {
|
||||
// TODO: How do we pass in a function argument?
|
||||
commandFn: actions.setSlabThickness,
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
},
|
||||
increaseSlabThickness: {
|
||||
commandFn: actions.changeSlabThickness,
|
||||
storeContexts: [],
|
||||
options: {
|
||||
change: 3,
|
||||
},
|
||||
},
|
||||
decreaseSlabThickness: {
|
||||
commandFn: actions.changeSlabThickness,
|
||||
storeContexts: [],
|
||||
options: {
|
||||
change: -3,
|
||||
},
|
||||
},
|
||||
mpr2d: {
|
||||
commandFn: actions.mpr2d,
|
||||
storeContexts: ['viewports'],
|
||||
|
||||
@@ -31,6 +31,43 @@ const definitions = [
|
||||
commandName: 'enableRotateTool',
|
||||
commandOptions: {},
|
||||
},
|
||||
{
|
||||
id: 'setBlendModeToComposite',
|
||||
label: 'Disable MIP',
|
||||
icon: 'times',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'setBlendModeToComposite',
|
||||
commandOptions: {},
|
||||
},
|
||||
{
|
||||
id: 'setBlendModeToMaximumIntensity',
|
||||
label: 'Enable MIP',
|
||||
icon: 'soft-tissue',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'setBlendModeToMaximumIntensity',
|
||||
commandOptions: {},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'increaseSlabThickness',
|
||||
label: 'Increase Slab Thickness',
|
||||
icon: 'caret-up',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'increaseSlabThickness',
|
||||
commandOptions: {},
|
||||
},
|
||||
{
|
||||
id: 'decreaseSlabThickness',
|
||||
label: 'Decrease Slab Thickness',
|
||||
icon: 'caret-down',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'decreaseSlabThickness',
|
||||
commandOptions: {},
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const autoprefixer = require("autoprefixer");
|
||||
// const vtkHtmlRules = require('vtk.js/Utilities/config/dependency.js').webpack
|
||||
// .core.rules;
|
||||
// Optional if you want to load *.css and *.module.css files
|
||||
// var cssRules = require('vtk.js/Utilities/config/dependency.js').webpack.css.rules;
|
||||
const SRC_DIR = path.join(__dirname, "./src");
|
||||
const OUTPUT_DIR = path.join(__dirname, "./dist");
|
||||
|
||||
module.exports = {
|
||||
mode: "development",
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`
|
||||
},
|
||||
context: SRC_DIR,
|
||||
// ~~~ MODE
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
library: "ohifVtkExtension",
|
||||
libraryTarget: "umd",
|
||||
filename: "index.umd.js",
|
||||
auxiliaryComment: "Text VTK Extension Comment"
|
||||
},
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: true,
|
||||
chunkModules: true,
|
||||
modules: true,
|
||||
children: true,
|
||||
warnings: true
|
||||
},
|
||||
optimization: {
|
||||
minimize: false,
|
||||
sideEffects: true
|
||||
},
|
||||
// ~~~ END MODE
|
||||
resolve: {
|
||||
modules: [
|
||||
path.resolve(__dirname, "node_modules"),
|
||||
path.resolve(__dirname, "../../node_modules"),
|
||||
SRC_DIR
|
||||
],
|
||||
extensions: [".js", ".jsx", ".json", "*"],
|
||||
symlinks: true
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: "upward",
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
{
|
||||
test: /\.css$/,
|
||||
exclude: /\.module\.css$/,
|
||||
use: [
|
||||
"style-loader",
|
||||
"css-loader",
|
||||
{
|
||||
loader: "postcss-loader",
|
||||
options: {
|
||||
plugins: () => [autoprefixer("last 2 version", "ie >= 10")]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
{
|
||||
test: /\.glsl$/i,
|
||||
include: /vtk\.js[\/\\]Sources/,
|
||||
loader: "shader-loader"
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
include: /vtk\.js[\/\\]Sources/,
|
||||
use: [
|
||||
{
|
||||
loader: "worker-loader",
|
||||
options: { inline: true, fallback: false }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
// externals: [
|
||||
// {
|
||||
// cornerstone: {
|
||||
// commonjs: 'cornerstone',
|
||||
// commonjs2: 'cornerstone',
|
||||
// amd: 'cornerstone',
|
||||
// root: 'cornerstone',
|
||||
// },
|
||||
// 'cornerstone-math': {
|
||||
// commonjs: 'cornerstone-math',
|
||||
// commonjs2: 'cornerstone-math',
|
||||
// amd: 'cornerstone-math',
|
||||
// root: 'cornerstoneMath',
|
||||
// },
|
||||
// },
|
||||
// '@ohif/i18n',
|
||||
// '@ohif/core',
|
||||
// 'dcmjs',
|
||||
// 'react-viewerbase',
|
||||
// 'react', //: 'React',
|
||||
// 'react-dom', //: 'ReactDOM',
|
||||
// 'react-redux', //: 'ReactRedux',
|
||||
// 'react-resize-detector', //: 'ReactResizeDetector',
|
||||
// 'react-viewerbase', //: 'reactViewerbase',
|
||||
// 'prop-types', //: 'PropTypes'
|
||||
// /*/\b(vtk.js)/*/
|
||||
// ],
|
||||
};
|
||||
+3
-2
@@ -5,14 +5,15 @@
|
||||
"useWorkspaces": true,
|
||||
"command": {
|
||||
"publish": {
|
||||
"ignoreChanges": ["*.md"],
|
||||
"ignoreChanges": ["*.md", "*.yml", "*.spec.js", "*.test.js"],
|
||||
"message": "chore(release): publish"
|
||||
},
|
||||
"version": {
|
||||
"allowBranch": "master",
|
||||
"conventionalCommits": true,
|
||||
"createRelease": "github",
|
||||
"yes": true,
|
||||
"message": "chore(release): publish %s [skip ci]"
|
||||
"message": "chore(release): publish [skip ci]"
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
-3
@@ -13,6 +13,61 @@ yarn add --dev -W package-name
|
||||
|
||||
- Patch status for PRs (we care about threshold only)
|
||||
- Allows us to use multiproject test runner
|
||||
- Flags per project for merged coverage; easier to break down coverage per project
|
||||
- Remove all-contributors bot; install CLI per project and add per project commands
|
||||
-
|
||||
- Flags per project for merged coverage; easier to break down coverage per
|
||||
project
|
||||
- Remove all-contributors bot; install CLI per project and add per project
|
||||
commands
|
||||
- Verify all have "dev:package-name" command
|
||||
- Should we include `package.json` and `src` as output? (build from ESM)
|
||||
- Should we remove `dev:package-name` commands and suggest navigating to
|
||||
package root?
|
||||
- Fix broken peer dependencies?
|
||||
- Lingering core-js resolution issues when building for Viewer PWA (from project
|
||||
directory)
|
||||
|
||||
## ORBS
|
||||
|
||||
- Slack: https://circleci.com/orbs/registry/orb/circleci/slack
|
||||
- GCP: https://circleci.com/orbs/registry/orb/circleci/gcp-cli
|
||||
- Browser Tools: https://circleci.com/orbs/registry/orb/circleci/browser-tools
|
||||
- Multi-Repo: https://circleci.com/orbs/registry/orb/dnephin/multirepo
|
||||
- PR Comment: https://circleci.com/orbs/registry/orb/benjlevesque/pr-comment
|
||||
|
||||
Debug Note: `http://localhost:3000/webpack-dev-server`
|
||||
|
||||
NOTES:
|
||||
|
||||
# bumps pre-release version of all packages if any changes
|
||||
|
||||
- `npx lerna version prerelease`
|
||||
|
||||
# Releases based on package.json differences from NPM
|
||||
|
||||
- `npx lerna publish from-package --dist-tag canary`
|
||||
|
||||
Use Env options to set config:
|
||||
|
||||
- https://webpack.js.org/api/cli/#environment-options
|
||||
|
||||
## Bundling
|
||||
|
||||
- Extensions must bundle all assets into a single file for UMD
|
||||
- The umd build for Viewer must bundle all of it's assets, and baked-in
|
||||
extension assets
|
||||
- The "skinny" umd build for viewer only needs to bundle it's own assets
|
||||
- The PWA build for Viewer can code-split to it's heart's content
|
||||
- Don't load/bundle a font at any layer other than Application/Viewer
|
||||
- It gets to decide if it should be bundled/cached/external
|
||||
|
||||
* For ESM/Module builds
|
||||
* Not dissimilar from VTK.js consumption
|
||||
* jest --watchAll for individual packages?
|
||||
|
||||
WebPack 5: https://github.com/webpack/webpack/issues/6386#issue-291757876
|
||||
|
||||
Flattened ESM: Less efficient, not as great at code splitting? From source? More
|
||||
loaders, added complexity, slower builds, better output
|
||||
|
||||
Notes:
|
||||
|
||||
- Remove preBuild step in viewer after @3 wado image loader
|
||||
+7
-3
@@ -3,6 +3,10 @@
|
||||
# TOML Reference:
|
||||
# https://www.netlify.com/docs/netlify-toml-reference/
|
||||
#
|
||||
# We use Netlify for deploy previews and deploy previews only.
|
||||
# https://viewer.ohif.org is created using a different process that is
|
||||
# managed by CircleCI and deployed to our Google Hosting
|
||||
#
|
||||
|
||||
# Settings in the [build] context are global and are applied to all contexts
|
||||
# unless otherwise overridden by more specific contexts.
|
||||
@@ -33,7 +37,7 @@
|
||||
# inherit these settings.
|
||||
[context.deploy-preview]
|
||||
base = ""
|
||||
publish = "docs/latest/_book/"
|
||||
publish = ".netlify/www/"
|
||||
command = "yarn config set workspaces-experimental true && chmod +x .netlify/build-deploy-preview.sh && .netlify/build-deploy-preview.sh"
|
||||
|
||||
# Redirects and headers are GLOBAL for all builds – they do not get scoped to
|
||||
@@ -51,8 +55,8 @@
|
||||
status = 200
|
||||
|
||||
[[redirects]]
|
||||
from = "/demo/*"
|
||||
to = "/demo/index.html"
|
||||
from = "/pwa/*"
|
||||
to = "/pwa/index.html"
|
||||
status = 200
|
||||
|
||||
[[headers]]
|
||||
|
||||
+30
-23
@@ -6,21 +6,30 @@
|
||||
"extensions/*"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^10.0.0",
|
||||
"npm": "^6.0.0",
|
||||
"yarn": "^1.16.0"
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"scripts": {
|
||||
"cm": "npx git-cz",
|
||||
"dev": ".scripts/dev.sh",
|
||||
"build": "lerna run build:viewer",
|
||||
"build:package": "lerna run build:package --parallel",
|
||||
"dev": "lerna run dev:viewer --stream",
|
||||
"dev:project": ".scripts/dev.sh",
|
||||
"build": "lerna run build:viewer --stream",
|
||||
"build:ci": "lerna run build:viewer:ci --stream",
|
||||
"build:package": "lerna run build:viewer:package --stream",
|
||||
"build:package-all": "lerna run build:package --parallel --stream",
|
||||
"test": "yarn run test:unit && yarn run test:e2e:ci",
|
||||
"test:unit": "jest --collectCoverage",
|
||||
"test:unit:ci": "lerna run test:unit:ci --parallel",
|
||||
"test:unit:ci": "lerna run test:unit:ci --parallel --stream",
|
||||
"test:e2e:ci": "cd platform/viewer && yarn run test:e2e:ci",
|
||||
"see-changed": "lerna changed",
|
||||
"publish": "lerna publish --canary --dist-tag test"
|
||||
"release": "yarn run lerna:version && yarn run lerna:publish",
|
||||
"lerna:version": "npx lerna version prerelease --force-publish",
|
||||
"lerna:publish": "lerna publish from-package --canary --dist-tag canary"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"core-js": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.5.0",
|
||||
@@ -30,18 +39,23 @@
|
||||
"@babel/plugin-transform-runtime": "^7.5.0",
|
||||
"@babel/preset-env": "^7.5.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"babel-eslint": "^10.0.2",
|
||||
"babel-eslint": "9.x",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-inline-react-svg": "1.1.0",
|
||||
"babel-plugin-module-resolver": "^3.2.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^3.0.0",
|
||||
"eslint": "^6.0.1",
|
||||
"eslint-plugin-import": "^2.18.0",
|
||||
"css-loader": "^3.2.0",
|
||||
"eslint": "5.16.0",
|
||||
"eslint-config-react-app": "^4.0.1",
|
||||
"eslint-plugin-flowtype": "2.x",
|
||||
"eslint-plugin-import": "2.x",
|
||||
"eslint-plugin-jsx-a11y": "6.x",
|
||||
"eslint-plugin-node": "^9.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.14.2",
|
||||
"eslint-plugin-react": "7.x",
|
||||
"eslint-plugin-react-hooks": "1.5.0",
|
||||
"extract-css-chunks-webpack-plugin": "^4.5.4",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"husky": "^3.0.0",
|
||||
@@ -59,6 +73,7 @@
|
||||
"react-scripts": "^3.0.1",
|
||||
"redux-testkit": "^1.0.6",
|
||||
"shader-loader": "^1.3.1",
|
||||
"style-loader": "^1.0.0",
|
||||
"stylelint": "^10.1.0",
|
||||
"stylelint-config-recommended": "^2.2.0",
|
||||
"stylus": "^0.54.5",
|
||||
@@ -71,16 +86,8 @@
|
||||
"workbox-webpack-plugin": "^4.3.1",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,json,md,yml}": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
"resolutions": {
|
||||
"**/@babel/runtime": "7.5.5"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
|
||||
@@ -59,6 +59,34 @@
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "igoroctaviano",
|
||||
"name": "Igor Octaviano",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/13886933?v=4",
|
||||
"profile": "http://igoroctaviano.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dlwire",
|
||||
"name": "David Wire",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/1167291?v=4",
|
||||
"profile": "https://github.com/dlwire",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "pavertomato",
|
||||
"name": "Egor Lezhnin",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/878990?v=4",
|
||||
"profile": "http://egor.lezhn.in",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const common = require('./webpack.common');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
@@ -8,19 +8,21 @@ const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = common(env, argv);
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-production
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: false,
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: true,
|
||||
chunkModules: true,
|
||||
modules: true,
|
||||
children: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
@@ -32,7 +34,6 @@ module.exports = (env, argv) => {
|
||||
library: 'ohifCore',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
auxiliaryComment: 'Test Comment',
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,87 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.50.1](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.0-alpha.10...@ohif/core@0.50.1) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.10](https://github.com/OHIF/Viewers/compare/@ohif/core@0.11.1-alpha.9...@ohif/core@0.50.0-alpha.10) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.11.1-alpha.9](https://github.com/OHIF/Viewers/compare/@ohif/core@0.11.1-alpha.8...@ohif/core@0.11.1-alpha.9) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.11.1-alpha.8 (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.11.1-alpha.7](https://github.com/OHIF/Viewers/compare/@ohif/core@0.11.1-alpha.6...@ohif/core@0.11.1-alpha.7) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.11.1-alpha.6](https://github.com/OHIF/Viewers/compare/@ohif/core@0.11.1-alpha.5...@ohif/core@0.11.1-alpha.6) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.11.1-alpha.5](https://github.com/OHIF/Viewers/compare/@ohif/core@0.11.1-alpha.4...@ohif/core@0.11.1-alpha.5) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.11.1-alpha.4](https://github.com/OHIF/Viewers/compare/@ohif/core@0.11.1-alpha.3...@ohif/core@0.11.1-alpha.4) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.11.1-alpha.3](https://github.com/OHIF/Viewers/compare/@ohif/core@0.11.1-alpha.2...@ohif/core@0.11.1-alpha.3) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
return {
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
context: SRC_DIR,
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
symlinks: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: 'upward',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
||||
new ExtractCssChunks({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
// hot: true /* only necessary if hot reloading not function*/
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
+18
-19
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/core",
|
||||
"version": "0.11.1-alpha.2",
|
||||
"version": "0.50.1",
|
||||
"description": "Generic business logic for web-based medical imaging applications",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -11,40 +11,39 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "yarn run dev",
|
||||
"dev": "jest --watch",
|
||||
"dev": "jest --watchAll",
|
||||
"dev:core": "yarn run dev",
|
||||
"test:unit": "jest --watch",
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage",
|
||||
"build": "webpack --config config/webpack.prod.js -d",
|
||||
"build": "webpack --config .webpack/webpack.prod.js",
|
||||
"build:package": "yarn run build",
|
||||
"lint": "eslint -c .eslintrc --fix src && prettier --single-quote --write src/**/*.{js,jsx,json,css}",
|
||||
"prepublishOnly": "yarn run build"
|
||||
"prepublishOnly": "yarn run build",
|
||||
"start": "yarn run dev",
|
||||
"test:unit": "jest --watchAll",
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"cornerstone-core": "^2.2.8",
|
||||
"cornerstone-tools": "^3.9.0",
|
||||
"cornerstone-wado-image-loader": "^2.2.3",
|
||||
"cornerstone-wado-image-loader": "^3.0.0",
|
||||
"dicom-parser": "^1.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"ajv": "^6.10.0",
|
||||
"dicomweb-client": "^0.4.2",
|
||||
"dicomweb-client": "^0.5.2",
|
||||
"isomorphic-base64": "^1.0.2",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.merge": "^4.6.1",
|
||||
"mousetrap": "^1.6.3",
|
||||
"validate.js": "^0.12.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"gitHead": "a5baa9228c0eda0df880136bde4420d78e6f8706"
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ export default function getAttribute(element, defaultValue) {
|
||||
|
||||
function convertToInt(input) {
|
||||
function padFour(input) {
|
||||
var l = input.length;
|
||||
const l = input.length;
|
||||
|
||||
if (l == 0) return '0000';
|
||||
if (l == 1) return '000' + input;
|
||||
@@ -33,9 +33,9 @@ function convertToInt(input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
var output = '';
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
for (var j = 0; j < input[i].length; j++) {
|
||||
let output = '';
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
for (let j = 0; j < input[i].length; j++) {
|
||||
output += padFour(input[i].charCodeAt(j).toString(16));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import getAttribute from './getAttribute';
|
||||
|
||||
describe('getAttribute', () => {
|
||||
it('should return a default value if element is null or undefined', () => {
|
||||
const defaultValue = '0000';
|
||||
const nullElement = null;
|
||||
const undefinedElement = undefined;
|
||||
|
||||
expect(getAttribute(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getAttribute(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
});
|
||||
|
||||
it('should return a default value if element.Value is null, undefined or not present', () => {
|
||||
const defaultValue = '0000';
|
||||
const nullElement = {
|
||||
id: 0,
|
||||
Value: null,
|
||||
};
|
||||
const undefinedElement = {
|
||||
id: 0,
|
||||
Value: undefined,
|
||||
};
|
||||
const noValuePresentElement = {
|
||||
id: 0,
|
||||
};
|
||||
|
||||
expect(getAttribute(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getAttribute(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getAttribute(noValuePresentElement, defaultValue)).toEqual(
|
||||
defaultValue
|
||||
);
|
||||
});
|
||||
|
||||
it('should return 48 for element with value 0', () => {
|
||||
const returnValue = 48;
|
||||
const element = {
|
||||
Value: '0',
|
||||
};
|
||||
expect(getAttribute(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return 3211313 for element with value 11', () => {
|
||||
const returnValue = 3211313;
|
||||
const element = {
|
||||
Value: '11',
|
||||
};
|
||||
expect(getAttribute(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return 2.4923405222191973e+35 for element with value 00280009', () => {
|
||||
const returnValue = 2.4923405222191973e35;
|
||||
const element = {
|
||||
id: 0,
|
||||
Value: '00280009',
|
||||
};
|
||||
expect(getAttribute(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return 2949169 for element with value -1', () => {
|
||||
const returnValue = 2949169;
|
||||
const element = {
|
||||
id: 0,
|
||||
Value: '-1',
|
||||
};
|
||||
expect(getAttribute(element, null)).toEqual(returnValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import getAuthorizationHeader from './getAuthorizationHeader';
|
||||
import user from './../user';
|
||||
|
||||
jest.mock('./../user.js');
|
||||
|
||||
describe('getAuthorizationHeader', () => {
|
||||
it('should return a HTTP Basic Auth when server contains requestOptions.auth', () => {
|
||||
const validServer = {
|
||||
requestOptions: {
|
||||
auth: {
|
||||
user: 'dummy_user',
|
||||
password: 'dummy_password',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const expectedAuthorizationHeader = {
|
||||
Authorization: `Basic ${btoa(validServer.requestOptions.auth)}`,
|
||||
};
|
||||
|
||||
const authentication = getAuthorizationHeader(validServer);
|
||||
|
||||
expect(authentication).toEqual(expectedAuthorizationHeader);
|
||||
});
|
||||
|
||||
it('should return a HTTP Basic Auth when server contains requestOptions.auth even though there is no password', () => {
|
||||
const validServerWithoutPassword = {
|
||||
requestOptions: {
|
||||
auth: {
|
||||
user: 'dummy_user',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const expectedAuthorizationHeader = {
|
||||
Authorization: `Basic ${btoa(
|
||||
validServerWithoutPassword.requestOptions.auth
|
||||
)}`,
|
||||
};
|
||||
|
||||
const authentication = getAuthorizationHeader(validServerWithoutPassword);
|
||||
|
||||
expect(authentication).toEqual(expectedAuthorizationHeader);
|
||||
});
|
||||
|
||||
it('should return a HTTP Basic Auth when server contains requestOptions.auth even though there is no username', () => {
|
||||
const validServerWithoutPassword = {
|
||||
requestOptions: {
|
||||
auth: {
|
||||
user: 'dummy_user',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const expectedAuthorizationHeader = {
|
||||
Authorization: `Basic ${btoa(
|
||||
validServerWithoutPassword.requestOptions.auth
|
||||
)}`,
|
||||
};
|
||||
|
||||
const authentication = getAuthorizationHeader(validServerWithoutPassword);
|
||||
|
||||
expect(authentication).toEqual(expectedAuthorizationHeader);
|
||||
});
|
||||
|
||||
it('should return an empty object when there is no either server.requestOptions.auth or accessToken', () => {
|
||||
const authentication = getAuthorizationHeader({});
|
||||
|
||||
expect(authentication).toEqual({});
|
||||
});
|
||||
|
||||
it('should return an Authorization with accessToken when server is not defined and there is an accessToken', () => {
|
||||
user.getAccessToken.mockImplementationOnce(() => 'MOCKED_TOKEN');
|
||||
|
||||
const authentication = getAuthorizationHeader({});
|
||||
const exptecteHeaderBasedOnUserAccessToekn = {
|
||||
Authorization: 'Bearer MOCKED_TOKEN',
|
||||
};
|
||||
|
||||
expect(authentication).toEqual(exptecteHeaderBasedOnUserAccessToekn);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
export default function getModalities(modality, modalitiesInStudy) {
|
||||
var modalities = {};
|
||||
let modalities = {};
|
||||
if (modality) {
|
||||
modalities = modality;
|
||||
}
|
||||
@@ -7,8 +7,8 @@ export default function getModalities(modality, modalitiesInStudy) {
|
||||
if (modalitiesInStudy) {
|
||||
// Find vr in modalities
|
||||
if (modalities.vr && modalities.vr === modalitiesInStudy.vr) {
|
||||
for (var i = 0; i < modalitiesInStudy.Value.length; i++) {
|
||||
var value = modalitiesInStudy.Value[i];
|
||||
for (let i = 0; i < modalitiesInStudy.Value.length; i++) {
|
||||
const value = modalitiesInStudy.Value[i];
|
||||
if (modalities.Value.indexOf(value) === -1) {
|
||||
modalities.Value.push(value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import getModalities from './getModalities';
|
||||
|
||||
describe('getModalities', () => {
|
||||
test('should return an empty object when modality and modalitiesInStudy are not present', () => {
|
||||
const modality = null;
|
||||
const modalitiesInStudy = null;
|
||||
|
||||
expect(getModalities(modality, modalitiesInStudy)).toEqual({});
|
||||
});
|
||||
|
||||
test('should return an empty object when modality and modalitiesInStudy are not present', () => {
|
||||
const modality = null;
|
||||
const modalitiesInStudy = null;
|
||||
|
||||
expect(getModalities(modality, modalitiesInStudy)).toEqual({});
|
||||
});
|
||||
|
||||
test('should return modalities in Study when modality is not defined', () => {
|
||||
const modality = null;
|
||||
|
||||
const modalitiesInStudy = {
|
||||
Value: ['MOCKED_VALUE'],
|
||||
vr: 'MOCKED_VALUE',
|
||||
};
|
||||
|
||||
expect(getModalities(modality, modalitiesInStudy)).toEqual(
|
||||
modalitiesInStudy
|
||||
);
|
||||
});
|
||||
|
||||
test('should return only the modalitues that exists in modalitiesInStudy', () => {
|
||||
const modality = {
|
||||
Value: ['DESIRED_VALUE'],
|
||||
vr: 'DESIRED_VR',
|
||||
};
|
||||
|
||||
const modalitiesInStudy = {
|
||||
Value: ['DESIRED_VALUE', 'NOT_DESIRED_VALUE'],
|
||||
vr: 'DESIRED_VR',
|
||||
};
|
||||
|
||||
expect(getModalities(modality, modalitiesInStudy)).toEqual(modality);
|
||||
});
|
||||
|
||||
test('should return the seek modality when the desired modality does not exist in modalitiesInStudy', () => {
|
||||
const modality = {
|
||||
Value: ['DESIRED_VALUE'],
|
||||
vr: 'DESIRED_VR',
|
||||
};
|
||||
|
||||
const modalitiesInStudy = {
|
||||
Value: ['NOT_DESIRED_VALUE'],
|
||||
vr: 'DESIRED_VR',
|
||||
};
|
||||
|
||||
expect(getModalities(modality, modalitiesInStudy)).toEqual(modality);
|
||||
});
|
||||
|
||||
test('should return the seek modality when the desired modality does not exist in modalitiesInStudy VR', () => {
|
||||
const modality = {
|
||||
Value: ['DESIRED_VALUE'],
|
||||
vr: 'DESIRED_VR',
|
||||
};
|
||||
|
||||
const modalitiesInStudy = {
|
||||
Value: ['NOT_DESIRED_VALUE'],
|
||||
vr: 'ANOTHER_VR',
|
||||
};
|
||||
|
||||
expect(getModalities(modality, modalitiesInStudy)).toEqual(
|
||||
modalitiesInStudy
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import getName from './getName';
|
||||
|
||||
describe('getName', () => {
|
||||
it('should return a default value if element is null or undefined', () => {
|
||||
const defaultValue = 'DEFAULT_NAME';
|
||||
const nullElement = null;
|
||||
const undefinedElement = undefined;
|
||||
|
||||
expect(getName(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getName(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
});
|
||||
|
||||
it('should return a default value if element.Value is null, undefined or not present', () => {
|
||||
const defaultValue = 'DEFAULT_NAME';
|
||||
const nullElement = {
|
||||
id: 0,
|
||||
Value: null,
|
||||
};
|
||||
const undefinedElement = {
|
||||
id: 0,
|
||||
Value: undefined,
|
||||
};
|
||||
const noValuePresentElement = {
|
||||
id: 0,
|
||||
};
|
||||
|
||||
expect(getName(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getName(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getName(noValuePresentElement, defaultValue)).toEqual(defaultValue);
|
||||
});
|
||||
|
||||
it('should return A for element when Alphabetic is [A, B, C, D]', () => {
|
||||
const returnValue = 'A';
|
||||
const element = {
|
||||
Value: [
|
||||
{ Alphabetic: 'A' },
|
||||
{ Alphabetic: 'B' },
|
||||
{ Alphabetic: 'C' },
|
||||
{ Alphabetic: 'D' },
|
||||
],
|
||||
};
|
||||
expect(getName(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return FIRST for element when Alphabetic is [FIRST, SECOND]', () => {
|
||||
const returnValue = 'FIRST';
|
||||
const element = {
|
||||
Value: [{ Alphabetic: 'FIRST' }, { Alphabetic: 'SECOND' }],
|
||||
};
|
||||
expect(getName(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return element.value[0] for element with not Alphabetic and when there is at least on element.Value', () => {
|
||||
const returnValue = {
|
||||
anyOtherProperty: 'FIRST',
|
||||
};
|
||||
const element = {
|
||||
Value: [{ anyOtherProperty: 'FIRST' }, { Alphabetic: 'SECOND' }],
|
||||
};
|
||||
expect(getName(element, null)).toEqual(returnValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import getNumber from './getNumber';
|
||||
|
||||
describe('getNumber', () => {
|
||||
it('should return a default value if element is null or undefined', () => {
|
||||
const defaultValue = 1.0;
|
||||
const nullElement = null;
|
||||
const undefinedElement = undefined;
|
||||
|
||||
expect(getNumber(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getNumber(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
});
|
||||
|
||||
it('should return a default value if element.Value is null, undefined or not present', () => {
|
||||
const defaultValue = 1.0;
|
||||
const nullElement = {
|
||||
id: 0,
|
||||
Value: null,
|
||||
};
|
||||
const undefinedElement = {
|
||||
id: 0,
|
||||
Value: undefined,
|
||||
};
|
||||
const noValuePresentElement = {
|
||||
id: 0,
|
||||
};
|
||||
|
||||
expect(getNumber(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getNumber(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getNumber(noValuePresentElement, defaultValue)).toEqual(
|
||||
defaultValue
|
||||
);
|
||||
});
|
||||
|
||||
it('should return 2.0 for element when element.Value[0] = 2', () => {
|
||||
const returnValue = 2.0;
|
||||
const element = {
|
||||
Value: ['2'],
|
||||
};
|
||||
expect(getNumber(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return -1.0 for element when element.Value[0] is -1', () => {
|
||||
const returnValue = -1.0;
|
||||
const element = {
|
||||
Value: ['-1'],
|
||||
};
|
||||
expect(getNumber(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return -1.0 for element when element.Value is [-1, 2, 5, -10] ', () => {
|
||||
const returnValue = -1.0;
|
||||
const element = {
|
||||
Value: ['-1', '2', '5', '-10'],
|
||||
};
|
||||
expect(getNumber(element, null)).toEqual(returnValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import getString from './getString';
|
||||
|
||||
describe('getString', () => {
|
||||
it('should return a default value if element is null or undefined', () => {
|
||||
const defaultValue = ['A', 'B', 'C'].join('\\');
|
||||
const nullElement = null;
|
||||
const undefinedElement = undefined;
|
||||
|
||||
expect(getString(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getString(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
});
|
||||
|
||||
it('should return a default value if element.Value is null, undefined or not present', () => {
|
||||
const defaultValue = ['A', 'B', 'C'].join('\\');
|
||||
const nullElement = {
|
||||
id: 0,
|
||||
Value: null,
|
||||
};
|
||||
const undefinedElement = {
|
||||
id: 0,
|
||||
Value: undefined,
|
||||
};
|
||||
const noValuePresentElement = {
|
||||
id: 0,
|
||||
};
|
||||
|
||||
expect(getString(nullElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getString(undefinedElement, defaultValue)).toEqual(defaultValue);
|
||||
expect(getString(noValuePresentElement, defaultValue)).toEqual(
|
||||
defaultValue
|
||||
);
|
||||
});
|
||||
|
||||
it('should return A,B,C,D for element when element.Value[0] = [A, B, C, D]', () => {
|
||||
const returnValue = ['A', 'B', 'C'].join('\\');
|
||||
const element = {
|
||||
Value: ['A', 'B', 'C'],
|
||||
};
|
||||
expect(getString(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return 1,4,5,6 for element when element.Value[0] is [1, 4, 5, 6]', () => {
|
||||
const returnValue = [1, 4, 5, 6].join('\\');
|
||||
const element = {
|
||||
Value: [1, 4, 5, 6],
|
||||
};
|
||||
expect(getString(element, null)).toEqual(returnValue);
|
||||
});
|
||||
|
||||
it('should return A,1,3,R,7,-1 for element when element.Value is [-1, 2, 5, -10] ', () => {
|
||||
const returnValue = ['A', '1', '3', 'R', '7', '-1'].join('\\');
|
||||
const element = {
|
||||
Value: ['A', '1', '3', 'R', '7', '-1'],
|
||||
};
|
||||
expect(getString(element, null)).toEqual(returnValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import * as DICOMWeb from './index.js';
|
||||
|
||||
describe('Top level exports', () => {
|
||||
test('should export the modules getAttribute, getAuthorizationHeader, getModalities, getName, getNumber, getString', () => {
|
||||
const expectedExports = [
|
||||
'getAttribute',
|
||||
'getAuthorizationHeader',
|
||||
'getModalities',
|
||||
'getName',
|
||||
'getNumber',
|
||||
'getString',
|
||||
].sort();
|
||||
|
||||
const exports = Object.keys(DICOMWeb.default).sort();
|
||||
|
||||
expect(exports).toEqual(expectedExports);
|
||||
});
|
||||
});
|
||||
@@ -635,7 +635,17 @@ function _getDisplaySetFromSopClassModule(
|
||||
headers,
|
||||
});
|
||||
|
||||
return plugin.getDisplaySetFromSeries(series, study, dicomWebClient, headers);
|
||||
let displaySet = plugin.getDisplaySetFromSeries(
|
||||
series,
|
||||
study,
|
||||
dicomWebClient,
|
||||
headers
|
||||
);
|
||||
if (displaySet && !displaySet.modality) {
|
||||
const instance = series.getFirstInstance();
|
||||
displaySet.modality = instance.getRawValue('x00080060');
|
||||
}
|
||||
return displaySet;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,9 @@ import getImageIdForImagePath from '../lib/getImageIdForImagePath';
|
||||
import guid from '../../utils/guid';
|
||||
import studyMetadataManager from '../../utils/studyMetadataManager';
|
||||
|
||||
const configuration = {};
|
||||
const configuration = {
|
||||
measurementTools: [],
|
||||
};
|
||||
|
||||
export default class MeasurementApi {
|
||||
static Instance;
|
||||
|
||||
@@ -32,6 +32,14 @@ export const MaxTargetsSchema = {
|
||||
minItems: 1,
|
||||
uniqueItems: true,
|
||||
},
|
||||
isNodal: {
|
||||
label: 'Filter to evaluate only nodal or extranodal measurements',
|
||||
type: 'boolean'
|
||||
},
|
||||
message: {
|
||||
label: 'Message to be displayed in case of nonconformity',
|
||||
type: 'string',
|
||||
}
|
||||
},
|
||||
required: ['limit'],
|
||||
};
|
||||
@@ -43,6 +51,7 @@ export const MaxTargetsSchema = {
|
||||
* newTarget: Flag to evaluate only new targets (must be evaluated on both)
|
||||
* locationIn: Filter to evaluate only measurements with the specified locations
|
||||
* locationNotIn: Filter to evaluate only measurements without the specified locations
|
||||
* isNodal: Filter to evaluate only nodal or extranodal measurements
|
||||
* message: Message to be displayed in case of nonconformity
|
||||
*/
|
||||
export class MaxTargetsCriterion extends BaseCriterion {
|
||||
@@ -56,16 +65,31 @@ export class MaxTargetsCriterion extends BaseCriterion {
|
||||
const newTargetNumbers = this.getNewTargetNumbers(data);
|
||||
const measurementNumbers = [];
|
||||
data.targets.forEach(target => {
|
||||
const { location, measurementNumber, isSplitLesion } = target.measurement;
|
||||
if (isSplitLesion) return;
|
||||
if (options.newTarget && !newTargetNumbers.has(measurementNumber)) return;
|
||||
const { location, measurementNumber, isSplitLesion, isNodal } = target.measurement;
|
||||
|
||||
if (isSplitLesion)
|
||||
return;
|
||||
|
||||
if (typeof isNodal === 'boolean' && typeof options.isNodal === 'boolean' && options.isNodal !== isNodal)
|
||||
return;
|
||||
|
||||
if (options.newTarget && !newTargetNumbers.has(measurementNumber))
|
||||
return;
|
||||
|
||||
if (options.locationIn && options.locationIn.indexOf(location) === -1)
|
||||
return;
|
||||
|
||||
if (options.locationNotIn && options.locationNotIn.indexOf(location) > -1)
|
||||
return;
|
||||
|
||||
measurementNumbers.push(measurementNumber);
|
||||
});
|
||||
|
||||
let lesionType = '';
|
||||
if (typeof options.isNodal === 'boolean') {
|
||||
lesionType = options.isNodal ? 'nodal ' : 'extranodal ';
|
||||
}
|
||||
|
||||
let message;
|
||||
if (measurementNumbers.length > options.limit) {
|
||||
const increment = options.newTarget ? 'new ' : '';
|
||||
@@ -73,7 +97,7 @@ export class MaxTargetsCriterion extends BaseCriterion {
|
||||
const amount = options.limit === 0 ? '' : `more than ${options.limit}`;
|
||||
message =
|
||||
options.message ||
|
||||
`The study should not have ${amount} ${increment}target${plural}.`;
|
||||
`The study should not have ${amount} ${increment}${lesionType}target${plural}.`;
|
||||
}
|
||||
|
||||
return this.generateResponse(message);
|
||||
|
||||
@@ -12,6 +12,14 @@ export const MaxTargetsPerOrganSchema = {
|
||||
label: 'Flag to evaluate only new targets',
|
||||
type: 'boolean',
|
||||
},
|
||||
isNodal: {
|
||||
label: 'Filter to evaluate only nodal or extranodal measurements',
|
||||
type: 'boolean'
|
||||
},
|
||||
message: {
|
||||
label: 'Message to be displayed in case of nonconformity',
|
||||
type: 'string',
|
||||
}
|
||||
},
|
||||
required: ['limit'],
|
||||
};
|
||||
@@ -22,6 +30,8 @@ export const MaxTargetsPerOrganSchema = {
|
||||
* Options:
|
||||
* limit: Max targets allowed in study
|
||||
* newTarget: Flag to evaluate only new targets (must be evaluated on both)
|
||||
* isNodal: Filter to evaluate only nodal or extranodal measurements
|
||||
* message: Message to be displayed in case of nonconformity
|
||||
*/
|
||||
export class MaxTargetsPerOrganCriterion extends BaseCriterion {
|
||||
constructor(...props) {
|
||||
@@ -36,9 +46,13 @@ export class MaxTargetsPerOrganCriterion extends BaseCriterion {
|
||||
const newTargetNumbers = this.getNewTargetNumbers(data);
|
||||
data.targets.forEach(target => {
|
||||
const { measurement } = target;
|
||||
const { location, measurementNumber, isSplitLesion } = measurement;
|
||||
const { location, measurementNumber, isSplitLesion, isNodal } = measurement;
|
||||
|
||||
if (isSplitLesion) return;
|
||||
if (isSplitLesion)
|
||||
return;
|
||||
|
||||
if (typeof isNodal === 'boolean' && typeof options.isNodal === 'boolean' && options.isNodal !== isNodal)
|
||||
return;
|
||||
|
||||
if (!targetsPerOrgan[location]) {
|
||||
targetsPerOrgan[location] = new Set();
|
||||
@@ -59,7 +73,7 @@ export class MaxTargetsPerOrganCriterion extends BaseCriterion {
|
||||
message =
|
||||
options.message ||
|
||||
`Each organ should not have more than ${
|
||||
options.limit
|
||||
options.limit
|
||||
} ${increment}targets.`;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ export const MeasurementsLengthSchema = {
|
||||
minItems: 1,
|
||||
uniqueItems: true,
|
||||
},
|
||||
isNodal: {
|
||||
label: 'Filter to evaluate only nodal or extranodal measurements',
|
||||
type: 'boolean'
|
||||
},
|
||||
message: {
|
||||
label: 'Message to be displayed in case of nonconformity',
|
||||
type: 'string',
|
||||
@@ -89,6 +93,7 @@ export const MeasurementsLengthSchema = {
|
||||
* modalityNotIn: Filter to evaluate only measurements without the specified modalities
|
||||
* locationIn: Filter to evaluate only measurements with the specified locations
|
||||
* locationNotIn: Filter to evaluate only measurements without the specified locations
|
||||
* isNodal: Filter to evaluate only nodal or extranodal measurements
|
||||
* message: Message to be displayed in case of nonconformity
|
||||
*/
|
||||
export class MeasurementsLengthCriterion extends BaseCriterion {
|
||||
@@ -107,7 +112,7 @@ export class MeasurementsLengthCriterion extends BaseCriterion {
|
||||
const { metadata, measurement } = item;
|
||||
const { location } = measurement;
|
||||
|
||||
let { longestDiameter, shortestDiameter } = measurement;
|
||||
let { longestDiameter, shortestDiameter, isNodal } = measurement;
|
||||
if (measurement.childToolsCount) {
|
||||
const child = measurement.bidirectional;
|
||||
longestDiameter = (child && child.longestDiameter) || 0;
|
||||
@@ -118,6 +123,8 @@ export class MeasurementsLengthCriterion extends BaseCriterion {
|
||||
const modality = (metadata.getRawValue('x00080060') || '').toUpperCase();
|
||||
|
||||
// Stop here if the measurement does not match the modality and location filters
|
||||
if (typeof isNodal === 'boolean' && typeof options.isNodal === 'boolean' && options.isNodal !== isNodal)
|
||||
return;
|
||||
if (options.locationIn && options.locationIn.indexOf(location) === -1)
|
||||
return;
|
||||
if (options.modalityIn && options.modalityIn.indexOf(modality) === -1)
|
||||
|
||||
@@ -9,7 +9,11 @@ const studySearchPromises = new Map();
|
||||
* @returns {Promise} resolved with an array of studies information or rejected with an error
|
||||
*/
|
||||
export default function searchStudies(server, filter) {
|
||||
const promiseKey = JSON.stringify(filter);
|
||||
const promiseKeyObj = {
|
||||
qidoRoot: server.qidoRoot,
|
||||
filter,
|
||||
};
|
||||
const promiseKey = JSON.stringify(promiseKeyObj);
|
||||
if (studySearchPromises.has(promiseKey)) {
|
||||
return studySearchPromises.get(promiseKey);
|
||||
} else {
|
||||
|
||||
@@ -42,6 +42,7 @@ function getQIDOQueryParams(filter, serverSupportsQIDOIncludeField) {
|
||||
ModalitiesInStudy: filter.modalitiesInStudy,
|
||||
limit: filter.limit,
|
||||
offset: filter.offset,
|
||||
fuzzymatching: filter.fuzzymatching,
|
||||
includefield: serverSupportsQIDOIncludeField ? commaSeparatedFields : 'all',
|
||||
};
|
||||
|
||||
|
||||
@@ -164,9 +164,10 @@ function getPaletteColor(server, instance, tag, lutDescriptor) {
|
||||
return byteArray[position] + byteArray[position + 1] * 256;
|
||||
};
|
||||
|
||||
const arrayBufferToPaletteColorLUT = arraybuffer => {
|
||||
const byteArray = new Uint8Array(arraybuffer);
|
||||
const lut = [];
|
||||
const arrayBufferToPaletteColorLUT = result => {
|
||||
const arraybuffer = result[0]
|
||||
const byteArray = new Uint8Array(arraybuffer)
|
||||
const lut = []
|
||||
|
||||
for (let i = 0; i < numLutEntries; i++) {
|
||||
if (bits === 16) {
|
||||
@@ -390,6 +391,7 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
||||
DICOMWeb.getString(instance['00181065'])
|
||||
),
|
||||
sliceThickness: DICOMWeb.getNumber(instance['00180050']),
|
||||
spacingBetweenSlices: DICOMWeb.getString(instance['00180088']),
|
||||
lossyImageCompression: DICOMWeb.getString(instance['00282110']),
|
||||
derivationDescription: DICOMWeb.getString(instance['00282111']),
|
||||
lossyImageCompressionRatio: DICOMWeb.getString(instance['00282112']),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export default function absoluteUrl(path) {
|
||||
const absoluteUrl = path => {
|
||||
let absolutePath = '/';
|
||||
|
||||
if (!path) return absolutePath;
|
||||
|
||||
// TODO: Find another way to get root url
|
||||
const absoluteUrl = window.location.origin;
|
||||
const absoluteUrlParts = absoluteUrl.split('/');
|
||||
@@ -13,4 +15,6 @@ export default function absoluteUrl(path) {
|
||||
}
|
||||
|
||||
return absolutePath.replace(/\/\/+/g, '/');
|
||||
}
|
||||
};
|
||||
|
||||
export default absoluteUrl;
|
||||
@@ -0,0 +1,51 @@
|
||||
import absoluteUrl from './absoluteUrl';
|
||||
|
||||
describe('absoluteUrl', () => {
|
||||
test('should return /path_1/path_2/path_3/path_to_destination when the window.location.origin is http://dummy.com/path_1/path_2 and the path is /path_3/path_to_destination', () => {
|
||||
let global = {
|
||||
window: Object.create(window),
|
||||
};
|
||||
const url = 'http://dummy.com/path_1/path_2';
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
origin: url,
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
const absoluteUrlOutput = absoluteUrl('/path_3/path_to_destination');
|
||||
expect(absoluteUrlOutput).toEqual(
|
||||
'/path_1/path_2/path_3/path_to_destination'
|
||||
);
|
||||
});
|
||||
|
||||
test('should return / when the path is not defined', () => {
|
||||
const absoluteUrlOutput = absoluteUrl(undefined);
|
||||
expect(absoluteUrlOutput).toBe('/');
|
||||
});
|
||||
|
||||
test('should return the original path when there path in the window.origin after the domain and port', () => {
|
||||
global.window = Object.create(window);
|
||||
const url = 'http://dummy.com';
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
origin: url,
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
const absoluteUrlOutput = absoluteUrl('path_1/path_2/path_3');
|
||||
expect(absoluteUrlOutput).toEqual('/path_1/path_2/path_3');
|
||||
});
|
||||
|
||||
test('should be able to return the absolute path even when the path contains duplicates', () => {
|
||||
global.window = Object.create(window);
|
||||
const url = 'http://dummy.com';
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
origin: url,
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
const absoluteUrlOutput = absoluteUrl('path_1/path_1/path_1');
|
||||
expect(absoluteUrlOutput).toEqual('/path_1/path_1/path_1');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import addServers from './addServers';
|
||||
|
||||
describe('addServers', () => {
|
||||
const servers = {
|
||||
dicomWeb: [
|
||||
{
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
qidoSupportsIncludeField: true,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
requestOptions: {
|
||||
requestFromBrowser: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
oidc: [
|
||||
{
|
||||
authority: 'http://127.0.0.1/auth/realms/ohif',
|
||||
client_id: 'ohif-viewer',
|
||||
redirect_uri: 'http://127.0.0.1/callback',
|
||||
response_type: 'code',
|
||||
scope: 'openid',
|
||||
post_logout_redirect_uri: '/logout-redirect.html',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const store = {
|
||||
dispatch: jest.fn(),
|
||||
};
|
||||
|
||||
test('should be able to add a server and dispatch to the store successfuly', () => {
|
||||
addServers(servers, store);
|
||||
expect(store.dispatch).toBeCalledWith({
|
||||
server: {
|
||||
authority: 'http://127.0.0.1/auth/realms/ohif',
|
||||
client_id: 'ohif-viewer',
|
||||
post_logout_redirect_uri: '/logout-redirect.html',
|
||||
redirect_uri: 'http://127.0.0.1/callback',
|
||||
response_type: 'code',
|
||||
scope: 'openid',
|
||||
type: 'oidc',
|
||||
},
|
||||
type: 'ADD_SERVER',
|
||||
});
|
||||
expect(store.dispatch).toBeCalledWith({
|
||||
server: {
|
||||
imageRendering: 'wadors',
|
||||
name: 'DCM4CHEE',
|
||||
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
qidoSupportsIncludeField: true,
|
||||
requestOptions: { requestFromBrowser: true },
|
||||
thumbnailRendering: 'wadors',
|
||||
type: 'dicomWeb',
|
||||
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
},
|
||||
type: 'ADD_SERVER',
|
||||
});
|
||||
});
|
||||
|
||||
test('should throw an error if servers list is not defined', () => {
|
||||
expect(() => addServers(undefined, store)).toThrowError(
|
||||
new Error('The servers and store must be defined')
|
||||
);
|
||||
});
|
||||
|
||||
test('should throw an error if store is not defined', () => {
|
||||
expect(() => addServers(servers, undefined)).toThrowError(
|
||||
new Error('The servers and store must be defined')
|
||||
);
|
||||
});
|
||||
|
||||
test('should throw an error when both server and store are not defined', () => {
|
||||
expect(() => addServers(undefined, undefined)).toThrowError(
|
||||
new Error('The servers and store must be defined')
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,9 @@
|
||||
// TODO: figure out where else to put this function
|
||||
export default function addServers(servers, store) {
|
||||
const addServers = (servers, store) => {
|
||||
if (!servers || !store) {
|
||||
throw new Error('The servers and store must be defined');
|
||||
}
|
||||
|
||||
Object.keys(servers).forEach(serverType => {
|
||||
const endpoints = servers[serverType];
|
||||
endpoints.forEach(endpoint => {
|
||||
@@ -12,4 +16,6 @@ export default function addServers(servers, store) {
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default addServers;
|
||||
@@ -6,10 +6,10 @@ function getWADORSImageUrl(instance, frame) {
|
||||
}
|
||||
|
||||
// We need to sum 1 because WADO-RS frame number is 1-based
|
||||
frame = (frame || 0) + 1;
|
||||
frame = frame ? parseInt(frame) + 1 : 1;
|
||||
|
||||
// Replaces /frame/1 by /frame/{frame}
|
||||
wadorsuri = wadorsuri.replace(/(%2Fframes%2F)(\d+)/, `$1${frame}`);
|
||||
wadorsuri = wadorsuri.replace(/frames\/(\d+)/, `frames/${frame}`);
|
||||
|
||||
return wadorsuri;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ function getWADORSImageUrl(instance, frame) {
|
||||
* Obtain an imageId for Cornerstone based on the WADO-RS scheme
|
||||
*
|
||||
* @param {object} instanceMetada metadata object (InstanceMetadata)
|
||||
* @param {(string\|number)} [frame] the frame number
|
||||
* @returns {string} The imageId to be used by Cornerstone
|
||||
*/
|
||||
export default function getWADORSImageId(instance, frame) {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import getWADORSImageId from './getWADORSImageId';
|
||||
|
||||
describe('getWADORSImageId', () => {
|
||||
it('should always return undefined if the instance has no `wadorsuri` property', () => {
|
||||
const frame = '42';
|
||||
const instance = {};
|
||||
|
||||
expect(getWADORSImageId(instance)).toBeUndefined();
|
||||
expect(getWADORSImageId(instance, frame)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should always prepend the `wadorsuri` with `wadors:`', () => {
|
||||
const frame = '42';
|
||||
const instance = {
|
||||
wadorsuri: 'wadorsuri',
|
||||
};
|
||||
|
||||
expect(getWADORSImageId(instance)).toEqual('wadors:wadorsuri');
|
||||
expect(getWADORSImageId(instance, frame)).toEqual('wadors:wadorsuri');
|
||||
});
|
||||
|
||||
describe('with no frame provided', () => {
|
||||
it('should replace `frames/:number` with `frames/1`', () => {
|
||||
const instance = {
|
||||
wadorsuri: 'frames/42',
|
||||
};
|
||||
|
||||
expect(getWADORSImageId(instance)).toEqual('wadors:frames/1');
|
||||
});
|
||||
|
||||
it('should work on a real wadorsuri', () => {
|
||||
const instance = {
|
||||
wadorsuri:
|
||||
'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs/studies/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.1/series/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.2/instances/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.8/frames/22',
|
||||
};
|
||||
|
||||
expect(getWADORSImageId(instance)).toEqual(
|
||||
'wadors:https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs/studies/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.1/series/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.2/instances/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.8/frames/1'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a frame provided', () => {
|
||||
it('should replace `frames/:number` with the argument frame plus one', () => {
|
||||
const frame = '42';
|
||||
const instance = {
|
||||
wadorsuri: 'frames/1',
|
||||
};
|
||||
|
||||
expect(getWADORSImageId(instance, frame)).toEqual('wadors:frames/43');
|
||||
});
|
||||
|
||||
it('should work on a real wadorsuri', () => {
|
||||
const frame = '42';
|
||||
const instance = {
|
||||
wadorsuri:
|
||||
'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs/studies/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.1/series/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.2/instances/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.8/frames/22',
|
||||
};
|
||||
|
||||
expect(getWADORSImageId(instance, frame)).toEqual(
|
||||
'wadors:https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs/studies/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.1/series/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.2/instances/1.3.6.1.4.1.25403.52237031786.3872.20100510032220.8/frames/43'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,24 +3,26 @@
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
export default function guid() {
|
||||
function s4() {
|
||||
const guid = () => {
|
||||
const getFourRandomValues = () => {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
};
|
||||
return (
|
||||
s4() +
|
||||
s4() +
|
||||
getFourRandomValues() +
|
||||
getFourRandomValues() +
|
||||
'-' +
|
||||
s4() +
|
||||
getFourRandomValues() +
|
||||
'-' +
|
||||
s4() +
|
||||
getFourRandomValues() +
|
||||
'-' +
|
||||
s4() +
|
||||
getFourRandomValues() +
|
||||
'-' +
|
||||
s4() +
|
||||
s4() +
|
||||
s4()
|
||||
getFourRandomValues() +
|
||||
getFourRandomValues() +
|
||||
getFourRandomValues()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default guid;
|
||||
@@ -0,0 +1,46 @@
|
||||
import guid from './guid';
|
||||
|
||||
describe('guid', () => {
|
||||
Math.random = jest.fn(() => 0.4677647565236618);
|
||||
const guidValue = guid();
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should return 77bf77bf-77bf-77bf-77bf-77bf77bf77bf when the random value is fixed on 0.4677647565236618', () => {
|
||||
expect(guidValue).toBe('77bf77bf-77bf-77bf-77bf-77bf77bf77bf');
|
||||
});
|
||||
|
||||
test('should always return a guid of size 36', () => {
|
||||
expect(guidValue.length).toBe(36);
|
||||
});
|
||||
|
||||
test('should always return a guid with five sequences', () => {
|
||||
expect(guidValue.split('-').length).toBe(5);
|
||||
});
|
||||
|
||||
test('should always return a guid with four dashes', () => {
|
||||
expect(guidValue.split('-').length - 1).toBe(4);
|
||||
});
|
||||
|
||||
test('should return the first sequence with length of eigth', () => {
|
||||
expect(guidValue.split('-')[0].length).toBe(8);
|
||||
});
|
||||
|
||||
test('should return the second sequence with length of four', () => {
|
||||
expect(guidValue.split('-')[1].length).toBe(4);
|
||||
});
|
||||
|
||||
test('should return the third sequence with length of four', () => {
|
||||
expect(guidValue.split('-')[2].length).toBe(4);
|
||||
});
|
||||
|
||||
test('should return the fourth sequence with length of four', () => {
|
||||
expect(guidValue.split('-')[3].length).toBe(4);
|
||||
});
|
||||
|
||||
test('should return the last sequence with length of twelve', () => {
|
||||
expect(guidValue.split('-')[4].length).toBe(12);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import * as utils from './index.js';
|
||||
|
||||
describe('Top level exports', () => {
|
||||
test('should export the modules ', () => {
|
||||
const expectedExports = [
|
||||
'guid',
|
||||
'ObjectPath',
|
||||
'absoluteUrl',
|
||||
'addServers',
|
||||
'sortBy',
|
||||
'writeScript',
|
||||
'StackManager',
|
||||
'studyMetadataManager',
|
||||
// Updates WADO-RS metaDataManager
|
||||
'updateMetaDataManager',
|
||||
'DICOMTagDescriptions',
|
||||
].sort();
|
||||
|
||||
const exports = Object.keys(utils.default).sort();
|
||||
|
||||
expect(exports).toEqual(expectedExports);
|
||||
});
|
||||
});
|
||||
@@ -1,76 +1,62 @@
|
||||
import { sopClassDictionary } from './sopClassDictionary';
|
||||
|
||||
const imagesTypes = [
|
||||
sopClassDictionary.ComputedRadiographyImageStorage,
|
||||
sopClassDictionary.DigitalXRayImageStorageForPresentation,
|
||||
sopClassDictionary.DigitalXRayImageStorageForProcessing,
|
||||
sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation,
|
||||
sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing,
|
||||
sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation,
|
||||
sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing,
|
||||
sopClassDictionary.CTImageStorage,
|
||||
sopClassDictionary.EnhancedCTImageStorage,
|
||||
sopClassDictionary.LegacyConvertedEnhancedCTImageStorage,
|
||||
sopClassDictionary.UltrasoundMultiframeImageStorage,
|
||||
sopClassDictionary.MRImageStorage,
|
||||
sopClassDictionary.EnhancedMRImageStorage,
|
||||
sopClassDictionary.EnhancedMRColorImageStorage,
|
||||
sopClassDictionary.LegacyConvertedEnhancedMRImageStorage,
|
||||
sopClassDictionary.UltrasoundImageStorage,
|
||||
sopClassDictionary.SecondaryCaptureImageStorage,
|
||||
sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage,
|
||||
sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage,
|
||||
sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage,
|
||||
sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage,
|
||||
sopClassDictionary.XRayAngiographicImageStorage,
|
||||
sopClassDictionary.EnhancedXAImageStorage,
|
||||
sopClassDictionary.XRayRadiofluoroscopicImageStorage,
|
||||
sopClassDictionary.EnhancedXRFImageStorage,
|
||||
sopClassDictionary.XRay3DAngiographicImageStorage,
|
||||
sopClassDictionary.XRay3DCraniofacialImageStorage,
|
||||
sopClassDictionary.BreastTomosynthesisImageStorage,
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForPresentation,
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForProcessing,
|
||||
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation,
|
||||
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing,
|
||||
sopClassDictionary.NuclearMedicineImageStorage,
|
||||
sopClassDictionary.VLEndoscopicImageStorage,
|
||||
sopClassDictionary.VideoEndoscopicImageStorage,
|
||||
sopClassDictionary.VLMicroscopicImageStorage,
|
||||
sopClassDictionary.VideoMicroscopicImageStorage,
|
||||
sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage,
|
||||
sopClassDictionary.VLPhotographicImageStorage,
|
||||
sopClassDictionary.VideoPhotographicImageStorage,
|
||||
sopClassDictionary.OphthalmicPhotography8BitImageStorage,
|
||||
sopClassDictionary.OphthalmicPhotography16BitImageStorage,
|
||||
sopClassDictionary.OphthalmicTomographyImageStorage,
|
||||
sopClassDictionary.VLWholeSlideMicroscopyImageStorage,
|
||||
sopClassDictionary.PositronEmissionTomographyImageStorage,
|
||||
sopClassDictionary.EnhancedPETImageStorage,
|
||||
sopClassDictionary.LegacyConvertedEnhancedPETImageStorage,
|
||||
sopClassDictionary.RTImageStorage,
|
||||
];
|
||||
|
||||
/**
|
||||
* Checks whether dicom files with specified SOP Class UID have image data
|
||||
* @param {string} sopClassUid - SOP Class UID to be checked
|
||||
* @returns {boolean} - true if it has image data
|
||||
*/
|
||||
export function isImage(sopClassUid) {
|
||||
if (
|
||||
sopClassUid === sopClassDictionary.ComputedRadiographyImageStorage ||
|
||||
sopClassUid === sopClassDictionary.DigitalXRayImageStorageForPresentation ||
|
||||
sopClassUid === sopClassDictionary.DigitalXRayImageStorageForProcessing ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing ||
|
||||
sopClassUid === sopClassDictionary.CTImageStorage ||
|
||||
sopClassUid === sopClassDictionary.EnhancedCTImageStorage ||
|
||||
sopClassUid === sopClassDictionary.LegacyConvertedEnhancedCTImageStorage ||
|
||||
sopClassUid === sopClassDictionary.UltrasoundMultiframeImageStorage ||
|
||||
sopClassUid === sopClassDictionary.MRImageStorage ||
|
||||
sopClassUid === sopClassDictionary.EnhancedMRImageStorage ||
|
||||
sopClassUid === sopClassDictionary.EnhancedMRColorImageStorage ||
|
||||
sopClassUid === sopClassDictionary.LegacyConvertedEnhancedMRImageStorage ||
|
||||
sopClassUid === sopClassDictionary.UltrasoundImageStorage ||
|
||||
sopClassUid === sopClassDictionary.SecondaryCaptureImageStorage ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage ||
|
||||
sopClassUid === sopClassDictionary.XRayAngiographicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.EnhancedXAImageStorage ||
|
||||
sopClassUid === sopClassDictionary.XRayRadiofluoroscopicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.EnhancedXRFImageStorage ||
|
||||
sopClassUid === sopClassDictionary.XRay3DAngiographicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.XRay3DCraniofacialImageStorage ||
|
||||
sopClassUid === sopClassDictionary.BreastTomosynthesisImageStorage ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForPresentation ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForProcessing ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing ||
|
||||
sopClassUid === sopClassDictionary.NuclearMedicineImageStorage ||
|
||||
sopClassUid === sopClassDictionary.VLEndoscopicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.VideoEndoscopicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.VLMicroscopicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.VideoMicroscopicImageStorage ||
|
||||
sopClassUid ===
|
||||
sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.VLPhotographicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.VideoPhotographicImageStorage ||
|
||||
sopClassUid === sopClassDictionary.OphthalmicPhotography8BitImageStorage ||
|
||||
sopClassUid === sopClassDictionary.OphthalmicPhotography16BitImageStorage ||
|
||||
sopClassUid === sopClassDictionary.OphthalmicTomographyImageStorage ||
|
||||
sopClassUid === sopClassDictionary.VLWholeSlideMicroscopyImageStorage ||
|
||||
sopClassUid === sopClassDictionary.PositronEmissionTomographyImageStorage ||
|
||||
sopClassUid === sopClassDictionary.EnhancedPETImageStorage ||
|
||||
sopClassUid === sopClassDictionary.LegacyConvertedEnhancedPETImageStorage ||
|
||||
sopClassUid === sopClassDictionary.RTImageStorage
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
export const isImage = sopClassUid => {
|
||||
if (!sopClassUid) return false;
|
||||
return imagesTypes.indexOf(sopClassUid) !== -1;
|
||||
};
|
||||
@@ -0,0 +1,333 @@
|
||||
import { sopClassDictionary } from './sopClassDictionary';
|
||||
import { isImage } from './isImage';
|
||||
|
||||
describe('isImage', () => {
|
||||
test('should return true when the image is of type sopClassDictionary.ComputedRadiographyImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.ComputedRadiographyImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.DigitalXRayImageStorageForPresentation', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.DigitalXRayImageStorageForPresentation
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.DigitalXRayImageStorageForProcessing', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.DigitalXRayImageStorageForProcessing
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.CTImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.CTImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.EnhancedCTImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.EnhancedCTImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.LegacyConvertedEnhancedCTImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.LegacyConvertedEnhancedCTImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.UltrasoundMultiframeImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.UltrasoundMultiframeImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.MRImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.MRImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.EnhancedMRImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.EnhancedMRImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.EnhancedMRColorImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.EnhancedMRColorImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.LegacyConvertedEnhancedMRImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.LegacyConvertedEnhancedMRImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.UltrasoundImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.UltrasoundImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.SecondaryCaptureImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.SecondaryCaptureImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.XRayAngiographicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.XRayAngiographicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.EnhancedXAImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.EnhancedXAImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.XRayRadiofluoroscopicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.XRayRadiofluoroscopicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.EnhancedXRFImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.EnhancedXRFImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.XRay3DAngiographicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.XRay3DAngiographicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.XRay3DCraniofacialImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.XRay3DCraniofacialImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.BreastTomosynthesisImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.BreastTomosynthesisImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.BreastProjectionXRayImageStorageForPresentation', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForPresentation
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.BreastProjectionXRayImageStorageForProcessing', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.BreastProjectionXRayImageStorageForProcessing
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.NuclearMedicineImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.NuclearMedicineImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VLEndoscopicImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.VLEndoscopicImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VideoEndoscopicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.VideoEndoscopicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VLMicroscopicImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.VLMicroscopicImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VideoMicroscopicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.VideoMicroscopicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VLPhotographicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.VLPhotographicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VideoPhotographicImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.VideoPhotographicImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.OphthalmicPhotography8BitImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.OphthalmicPhotography8BitImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.OphthalmicPhotography16BitImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.OphthalmicPhotography16BitImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.OphthalmicTomographyImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.OphthalmicTomographyImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.VLWholeSlideMicroscopyImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.VLWholeSlideMicroscopyImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.PositronEmissionTomographyImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.PositronEmissionTomographyImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.EnhancedPETImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.EnhancedPETImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.LegacyConvertedEnhancedPETImageStorage', () => {
|
||||
const isImageStatus = isImage(
|
||||
sopClassDictionary.LegacyConvertedEnhancedPETImageStorage
|
||||
);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return true when the image is of type sopClassDictionary.RTImageStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.RTImageStorage);
|
||||
expect(isImageStatus).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false when the image is of type sopClassDictionary.SpatialFiducialsStorage', () => {
|
||||
const isImageStatus = isImage(sopClassDictionary.SpatialFiducialsStorage);
|
||||
expect(isImageStatus).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false when the image is undefined', () => {
|
||||
const isImageStatus = isImage(undefined);
|
||||
expect(isImageStatus).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false when the image is null', () => {
|
||||
const isImageStatus = isImage(null);
|
||||
expect(isImageStatus).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
import objectPath from './objectPath';
|
||||
|
||||
describe('objectPath', () => {
|
||||
test('should return false when the supplied argument is not a real JavaScript Object instance such as undefined', () => {
|
||||
expect(objectPath.isValidObject(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
test('should return false when the supplied argument is not a real JavaScript Object instance such as null', () => {
|
||||
expect(objectPath.isValidObject(null)).toBe(false);
|
||||
});
|
||||
|
||||
test('should return true when the supplied argument is a real JavaScript Object instance', () => {
|
||||
expect(objectPath.isValidObject({})).toBe(true);
|
||||
});
|
||||
|
||||
test('should return [path1, path2, path3] when the path is path1.path2.path3', () => {
|
||||
const path = 'path1.path2.path3';
|
||||
const expectedPathComponents = objectPath.getPathComponents(path);
|
||||
expect(expectedPathComponents).toEqual(['path1', 'path2', 'path3']);
|
||||
});
|
||||
|
||||
test('should return null when the path is not a string', () => {
|
||||
const path = 20;
|
||||
const expectedPathComponents = objectPath.getPathComponents(path);
|
||||
expect(expectedPathComponents).toEqual(null);
|
||||
});
|
||||
|
||||
test('should return [path1path2path3] when the path is path1path2path3', () => {
|
||||
const path = 'path1path2path3';
|
||||
const expectedPathComponents = objectPath.getPathComponents(path);
|
||||
expect(expectedPathComponents).toEqual(['path1path2path3']);
|
||||
});
|
||||
|
||||
test('should return the property obj.myProperty when the object contains myProperty', () => {
|
||||
const searchObject = {
|
||||
obj: {
|
||||
myProperty: 'MOCK_VALUE',
|
||||
},
|
||||
};
|
||||
const path = 'obj.myProperty';
|
||||
const expectedPathComponents = objectPath.get(searchObject, path);
|
||||
expect(expectedPathComponents).toEqual(searchObject.obj.myProperty);
|
||||
});
|
||||
|
||||
test('should return undefined when the object does not contain a property', () => {
|
||||
const searchObject = {
|
||||
obj: {
|
||||
myProperty: 'MOCK_VALUE',
|
||||
},
|
||||
};
|
||||
const path = 'obj.unknownProperty';
|
||||
const expectedPathComponents = objectPath.get(searchObject, path);
|
||||
expect(expectedPathComponents).toEqual(undefined);
|
||||
});
|
||||
|
||||
test('should return undefined when the object is not a valid object', () => {
|
||||
const searchObject = undefined;
|
||||
const path = 'obj.unknownProperty';
|
||||
const expectedPathComponents = objectPath.get(searchObject, path);
|
||||
expect(expectedPathComponents).toEqual(undefined);
|
||||
});
|
||||
|
||||
test('should return undefined when the inner object is not a valid object', () => {
|
||||
const searchObject = {
|
||||
obj: {
|
||||
myProperty: null,
|
||||
},
|
||||
};
|
||||
const path = 'obj.unknownProperty';
|
||||
const expectedPathComponents = objectPath.get(searchObject, path);
|
||||
expect(expectedPathComponents).toEqual(undefined);
|
||||
});
|
||||
|
||||
test('should set the property obj.myProperty when the object does not contain myProperty', () => {
|
||||
const searchObject = {
|
||||
obj: {
|
||||
anyProperty: 'MOCK_VALUE',
|
||||
},
|
||||
};
|
||||
const newValue = 'NEW_VALUE';
|
||||
const path = 'obj.myProperty';
|
||||
const output = objectPath.set(searchObject, path, newValue);
|
||||
expect(output).toBe(true);
|
||||
expect(searchObject.obj.myProperty).toEqual(newValue);
|
||||
});
|
||||
|
||||
test('should return false when the object which is being set is not in a valid path', () => {
|
||||
const searchObject = {
|
||||
obj: {
|
||||
myProperty: 'MOCK_VALUE',
|
||||
},
|
||||
};
|
||||
const path = undefined;
|
||||
const newValue = 'NEW_VALUE';
|
||||
|
||||
const output = objectPath.set(searchObject, path, newValue);
|
||||
expect(output).toEqual(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
const path = require('path');
|
||||
const merge = require('webpack-merge');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
|
||||
//
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-development
|
||||
mode: 'development',
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.common.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
// https://webpack.js.org/configuration/mode/#mode-production
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifI18n',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,98 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.50.1](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.50.0-alpha.11...@ohif/i18n@0.50.1) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.11](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.50.0-alpha.10...@ohif/i18n@0.50.0-alpha.11) (2019-08-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update i18n locales to include Japanese ([da725a8](https://github.com/OHIF/Viewers/commit/da725a8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [0.50.0-alpha.10](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.2.3-alpha.9...@ohif/i18n@0.50.0-alpha.10) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.3-alpha.9](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.2.3-alpha.8...@ohif/i18n@0.2.3-alpha.9) (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.2.3-alpha.8 (2019-08-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.2.3-alpha.7](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.2.3-alpha.6...@ohif/i18n@0.2.3-alpha.7) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.2.3-alpha.6](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.2.3-alpha.5...@ohif/i18n@0.2.3-alpha.6) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.2.3-alpha.5](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.2.3-alpha.4...@ohif/i18n@0.2.3-alpha.5) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.2.3-alpha.4](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.2.3-alpha.3...@ohif/i18n@0.2.3-alpha.4) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.2.3-alpha.3](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.2.3-alpha.2...@ohif/i18n@0.2.3-alpha.3) (2019-08-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/i18n
|
||||
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file. See
|
||||
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractCssChunks = require('extract-css-chunks-webpack-plugin');
|
||||
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
return {
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
context: SRC_DIR,
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
symlinks: true,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Find babel.config.js in monorepo root
|
||||
// https://babeljs.io/docs/en/options#rootmode
|
||||
rootMode: 'upward',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
// Do not transform ES6 modules to another format.
|
||||
// Webpack will take care of that.
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
ExtractCssChunks.loader,
|
||||
{ loader: 'css-loader', options: { importLoaders: 1 } },
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
config: {
|
||||
path: './postcss.config.js',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
||||
new ExtractCssChunks({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
// hot: true /* only necessary if hot reloading not function*/
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const common = require('./webpack.common');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = common(env, argv);
|
||||
|
||||
return merge(commonConfig, {
|
||||
mode: 'production',
|
||||
stats: {
|
||||
colors: false,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: true,
|
||||
chunkModules: true,
|
||||
modules: true,
|
||||
children: true,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'ohifCornerstoneExtension',
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
auxiliaryComment: 'Test Comment',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(gif|jpe?g|png|svg)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|woff2)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 50000,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
Loaded 100 of 306 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user