Compare commits
125
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a4b97b4e8 | ||
|
|
c79c0c301d | ||
|
|
ff5060f276 | ||
|
|
dafb26b34b | ||
|
|
c4f9d5e750 | ||
|
|
cf40a8388c | ||
|
|
d596ab5c3d | ||
|
|
72198eee7d | ||
|
|
057f68a9b4 | ||
|
|
034ca64d6b | ||
|
|
4a0901aee9 | ||
|
|
d0ec9cf0e0 | ||
|
|
71bea0d4d8 | ||
|
|
e607ed2aa0 | ||
|
|
4939f43509 | ||
|
|
c80ea17cc2 | ||
|
|
aa7dc1e2c1 | ||
|
|
e7e1a8a6cd | ||
|
|
e66c27affb | ||
|
|
ae26904885 | ||
|
|
8bb730318a | ||
|
|
69b96478cb | ||
|
|
816666df7b | ||
|
|
e375a4ab11 | ||
|
|
7f4d71e412 | ||
|
|
a90605c82d | ||
|
|
5b523c2afa | ||
|
|
5551f817e3 | ||
|
|
a9ca3fa026 | ||
|
|
89380353d2 | ||
|
|
edb86fad55 | ||
|
|
395a1be3fb | ||
|
|
65d852b9e4 | ||
|
|
e797a3a141 | ||
|
|
246936f90b | ||
|
|
c57298475a | ||
|
|
6a5ebb3e25 | ||
|
|
291b23aee1 | ||
|
|
72427fe2ff | ||
|
|
882d04c9bf | ||
|
|
d1a24bc9d9 | ||
|
|
16a87fa75f | ||
|
|
6fdac4d605 | ||
|
|
6192502fe0 | ||
|
|
2341b32638 | ||
|
|
45aeaec916 | ||
|
|
66b84ae9c2 | ||
|
|
bc28fe26ac | ||
|
|
7f642a05da | ||
|
|
66a0aadcce | ||
|
|
808af7ee96 | ||
|
|
10b5e071f4 | ||
|
|
fe1969b071 | ||
|
|
16b2a8295f | ||
|
|
d33bb4210d | ||
|
|
ab681b9929 | ||
|
|
f52daca5e5 | ||
|
|
4afc88c0e5 | ||
|
|
f519f8609c | ||
|
|
e27d5b58a4 | ||
|
|
a18b292a9d | ||
|
|
7bd1507a89 | ||
|
|
a634177578 | ||
|
|
fe4d71ad0b | ||
|
|
f723546e6b | ||
|
|
348b8949d4 | ||
|
|
26e037dee7 | ||
|
|
26be96783d | ||
|
|
029ba1fb4a | ||
|
|
56d658f02d | ||
|
|
64921b905f | ||
|
|
d00d7daf41 | ||
|
|
144a173306 | ||
|
|
e40cbae113 | ||
|
|
698d274c64 | ||
|
|
c221dd86d2 | ||
|
|
a8c3d1b9a2 | ||
|
|
6cce8e6720 | ||
|
|
e8dbe3e1b6 | ||
|
|
ac5dbda3b2 | ||
|
|
bf77b3959a | ||
|
|
c6a6bce0b8 | ||
|
|
3f9decc6d5 | ||
|
|
1b1ff8068d | ||
|
|
eb1a900b13 | ||
|
|
e8938111d5 | ||
|
|
73122e717c | ||
|
|
300fe06b60 | ||
|
|
37e5387cf0 | ||
|
|
7c2860789d | ||
|
|
df35b1bc06 | ||
|
|
0460a487ec | ||
|
|
0195a3d860 | ||
|
|
2740e34ad3 | ||
|
|
61d2caef96 | ||
|
|
a88f37595d | ||
|
|
42d80a3e60 | ||
|
|
51143ffe35 | ||
|
|
76f7b00b65 | ||
|
|
64ca61745b | ||
|
|
ababe63a55 | ||
|
|
6c2217f2e5 | ||
|
|
cf9bec3ffa | ||
|
|
32bc47d315 | ||
|
|
1fb98884d2 | ||
|
|
7f8f9dc073 | ||
|
|
c6f89495b2 | ||
|
|
bad987a06b | ||
|
|
c73abb518f | ||
|
|
d12d01215e | ||
|
|
86adb5113a | ||
|
|
5220cd371c | ||
|
|
16b063a504 | ||
|
|
d0d75987f7 | ||
|
|
7c4ee734fa | ||
|
|
a187783e0d | ||
|
|
ada05b01a7 | ||
|
|
1a44d78277 | ||
|
|
691a073b86 | ||
|
|
5a54564bff | ||
|
|
94b625d4e6 | ||
|
|
8f730a5124 | ||
|
|
0ff4d90878 | ||
|
|
a047994e3d | ||
|
|
672ad2d0e7 |
No files matched your search
+104
-103
@@ -9,9 +9,11 @@ version: 2.1
|
|||||||
# create pull request previews and to update `https://docs.ohif.org`
|
# create pull request previews and to update `https://docs.ohif.org`
|
||||||
###
|
###
|
||||||
|
|
||||||
|
## https://github.com/cypress-io/circleci-orb
|
||||||
|
##
|
||||||
orbs:
|
orbs:
|
||||||
codecov: codecov/codecov@1.0.5
|
codecov: codecov/codecov@1.0.5
|
||||||
cypress: cypress-io/cypress@1.8.0
|
cypress: cypress-io/cypress@1.10.0
|
||||||
|
|
||||||
defaults: &defaults
|
defaults: &defaults
|
||||||
docker:
|
docker:
|
||||||
@@ -21,13 +23,11 @@ defaults: &defaults
|
|||||||
working_directory: ~/repo
|
working_directory: ~/repo
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
PR_UNIT_TESTS:
|
CHECKOUT:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# Enable yarn workspaces
|
# Enable yarn workspaces
|
||||||
- run: yarn config set workspaces-experimental true
|
- run: yarn config set workspaces-experimental true
|
||||||
|
|
||||||
# Checkout code and ALL Git Tags
|
# Checkout code and ALL Git Tags
|
||||||
- checkout:
|
- checkout:
|
||||||
post:
|
post:
|
||||||
@@ -47,6 +47,16 @@ jobs:
|
|||||||
paths:
|
paths:
|
||||||
- ~/.cache ## Cache yarn and Cypress
|
- ~/.cache ## Cache yarn and Cypress
|
||||||
key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||||
|
# Persist :+1:
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: ~/repo
|
||||||
|
paths: .
|
||||||
|
|
||||||
|
UNIT_TESTS:
|
||||||
|
<<: *defaults
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: ~/repo
|
||||||
|
|
||||||
# RUN TESTS
|
# RUN TESTS
|
||||||
- run:
|
- run:
|
||||||
@@ -86,72 +96,7 @@ jobs:
|
|||||||
root: ~/repo
|
root: ~/repo
|
||||||
paths: .
|
paths: .
|
||||||
|
|
||||||
MERGE_UNIT_TESTS:
|
NPM_PUBLISH:
|
||||||
<<: *defaults
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Enable yarn workspaces
|
|
||||||
- run: yarn config set workspaces-experimental true
|
|
||||||
|
|
||||||
# Checkout code and ALL Git Tags
|
|
||||||
- checkout:
|
|
||||||
post:
|
|
||||||
- git fetch --all
|
|
||||||
- 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:
|
|
||||||
name: Install Dependencies
|
|
||||||
command: yarn install --frozen-lockfile
|
|
||||||
- save_cache:
|
|
||||||
name: Save Yarn Package Cache
|
|
||||||
paths:
|
|
||||||
- ~/.cache ## Cache yarn and Cypress
|
|
||||||
key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
|
||||||
|
|
||||||
# RUN TESTS
|
|
||||||
- run:
|
|
||||||
name: 'JavaScript Test Suite'
|
|
||||||
command: yarn run test:unit:ci
|
|
||||||
|
|
||||||
# PLATFORM/VIEWER
|
|
||||||
- run:
|
|
||||||
name: 'VIEWER: Combine report output'
|
|
||||||
command: |
|
|
||||||
viewerCov="/home/circleci/repo/platform/viewer/coverage"
|
|
||||||
touch "${viewerCov}/reports"
|
|
||||||
cat "${viewerCov}/clover.xml" >> "${viewerCov}/reports"
|
|
||||||
echo "\<<\<<\<< EOF" >> "${viewerCov}/reports"
|
|
||||||
cat "${viewerCov}/lcov.info" >>"${viewerCov}/reports"
|
|
||||||
echo "\<<\<<\<< EOF" >> "${viewerCov}/reports"
|
|
||||||
- codecov/upload:
|
|
||||||
file: '/home/circleci/repo/platform/viewer/coverage/reports'
|
|
||||||
flags: 'viewer'
|
|
||||||
|
|
||||||
# PLATFORM/CORE
|
|
||||||
- run:
|
|
||||||
name: 'CORE: Combine report output'
|
|
||||||
command: |
|
|
||||||
coreCov="/home/circleci/repo/platform/core/coverage"
|
|
||||||
touch "${coreCov}/reports"
|
|
||||||
cat "${coreCov}/clover.xml" >> "${coreCov}/reports"
|
|
||||||
echo "\<<\<<\<< EOF" >> "${coreCov}/reports"
|
|
||||||
cat "${coreCov}/lcov.info" >> "${coreCov}/reports"
|
|
||||||
echo "\<<\<<\<< EOF" >> "${coreCov}/reports"
|
|
||||||
- codecov/upload:
|
|
||||||
file: '/home/circleci/repo/platform/core/coverage/reports'
|
|
||||||
flags: 'core'
|
|
||||||
|
|
||||||
# Persist :+1:
|
|
||||||
- persist_to_workspace:
|
|
||||||
root: ~/repo
|
|
||||||
paths: .
|
|
||||||
|
|
||||||
npm_publish:
|
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
@@ -175,7 +120,7 @@ jobs:
|
|||||||
root: ~/repo
|
root: ~/repo
|
||||||
paths: .
|
paths: .
|
||||||
|
|
||||||
docs_publish:
|
DOCS_PUBLISH:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
@@ -192,7 +137,7 @@ jobs:
|
|||||||
- run: chmod +x ~/repo/.circleci/build-and-publish-docs.sh
|
- run: chmod +x ~/repo/.circleci/build-and-publish-docs.sh
|
||||||
- run: ~/repo/.circleci/build-and-publish-docs.sh
|
- run: ~/repo/.circleci/build-and-publish-docs.sh
|
||||||
|
|
||||||
docker_publish:
|
DOCKER_PUBLISH:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
@@ -204,13 +149,13 @@ jobs:
|
|||||||
command: |
|
command: |
|
||||||
# This file will exist if a new version was published by
|
# This file will exist if a new version was published by
|
||||||
# our `semantic-release` command in the previous job
|
# our `semantic-release` command in the previous job
|
||||||
if [[ ! -e tmp/updated-version.txt ]]; then
|
if [[ ! -e platform/viewer/success_version.txt ]]; then
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
# Remove npm config
|
# Remove npm config
|
||||||
rm -f ./.npmrc
|
rm -f ./.npmrc
|
||||||
# Set our version number using vars
|
# Set our version number using vars
|
||||||
export IMAGE_VERSION=$(cat tmp/updated-version.txt)
|
export IMAGE_VERSION=$(cat platform/viewer/success_version.txt)
|
||||||
export IMAGE_VERSION_FULL=v$IMAGE_VERSION.${CIRCLE_BUILD_NUM}
|
export IMAGE_VERSION_FULL=v$IMAGE_VERSION.${CIRCLE_BUILD_NUM}
|
||||||
echo $IMAGE_VERSION
|
echo $IMAGE_VERSION
|
||||||
echo $IMAGE_VERSION_FULL
|
echo $IMAGE_VERSION_FULL
|
||||||
@@ -221,7 +166,7 @@ jobs:
|
|||||||
docker push ohif/$IMAGE_NAME:latest
|
docker push ohif/$IMAGE_NAME:latest
|
||||||
fi
|
fi
|
||||||
|
|
||||||
viewer_demo_build:
|
VIEWER_DEMO_BUILD:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
@@ -230,7 +175,7 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: 'Build Demo Site'
|
name: 'Build Demo Site'
|
||||||
command: yarn run build:demo
|
command: yarn run build:demo
|
||||||
no_output_timeout: 30m
|
no_output_timeout: 45m
|
||||||
- run:
|
- run:
|
||||||
name: 'Upload SourceMaps, Send Deploy Notification'
|
name: 'Upload SourceMaps, Send Deploy Notification'
|
||||||
command: |
|
command: |
|
||||||
@@ -246,7 +191,7 @@ jobs:
|
|||||||
root: ~/repo
|
root: ~/repo
|
||||||
paths: .
|
paths: .
|
||||||
|
|
||||||
viewer_demo_publish:
|
VIEWER_DEMO_PUBLISH:
|
||||||
working_directory: ~/repo
|
working_directory: ~/repo
|
||||||
docker:
|
docker:
|
||||||
- image: google/cloud-sdk
|
- image: google/cloud-sdk
|
||||||
@@ -272,71 +217,127 @@ workflows:
|
|||||||
# PULL REQUESTS
|
# PULL REQUESTS
|
||||||
PR_CHECKS:
|
PR_CHECKS:
|
||||||
jobs:
|
jobs:
|
||||||
- PR_UNIT_TESTS:
|
- CHECKOUT:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
ignore:
|
ignore:
|
||||||
- master
|
- master
|
||||||
- feature/*
|
- feature/*
|
||||||
- hotfix/*
|
- hotfix/*
|
||||||
# Cypress job added by `cypress-io` orb
|
- UNIT_TESTS:
|
||||||
|
requires:
|
||||||
|
- CHECKOUT
|
||||||
|
# E2E: PWA
|
||||||
- cypress/run:
|
- cypress/run:
|
||||||
|
name: 'E2E: PWA'
|
||||||
pre-steps:
|
pre-steps:
|
||||||
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
||||||
add wait-on' # Use yarn latest
|
add wait-on' # Use yarn latest
|
||||||
yarn: true
|
yarn: true
|
||||||
store_artifacts: true
|
store_artifacts: false
|
||||||
start: yarn run dev
|
|
||||||
wait-on: 'http://localhost:3000'
|
|
||||||
no-workspace: true # Don't persist workspace
|
|
||||||
working_directory: platform/viewer
|
working_directory: platform/viewer
|
||||||
|
build: yarn run build:e2e
|
||||||
|
start: yarn run test:e2e:dist
|
||||||
|
wait-on: 'http://localhost:3000'
|
||||||
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
||||||
|
no-workspace: true # Don't persist workspace
|
||||||
post-steps:
|
post-steps:
|
||||||
- store_test_results:
|
- store_artifacts:
|
||||||
path: cypress/results
|
path: platform/viewer/cypress/screenshots
|
||||||
requires:
|
requires:
|
||||||
- PR_UNIT_TESTS
|
- UNIT_TESTS
|
||||||
|
# E2E: script-tag
|
||||||
|
- cypress/run:
|
||||||
|
name: 'E2E: Script Tag'
|
||||||
|
pre-steps:
|
||||||
|
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
||||||
|
add wait-on' # Use yarn latest
|
||||||
|
yarn: true
|
||||||
|
store_artifacts: false
|
||||||
|
working_directory: platform/viewer
|
||||||
|
build: yarn run build:package
|
||||||
|
start: yarn run test:e2e:dist
|
||||||
|
wait-on: 'http://localhost:3000'
|
||||||
|
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
||||||
|
no-workspace: true # Don't persist workspace
|
||||||
|
post-steps:
|
||||||
|
- store_artifacts:
|
||||||
|
path: platform/viewer/cypress/screenshots
|
||||||
|
requires:
|
||||||
|
- UNIT_TESTS
|
||||||
|
|
||||||
# MERGE TO MASTER
|
# MERGE TO MASTER
|
||||||
RELEASE:
|
RELEASE:
|
||||||
jobs:
|
jobs:
|
||||||
- MERGE_UNIT_TESTS:
|
- CHECKOUT:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only: master
|
||||||
# Cypress job added by `cypress-io` orb
|
- UNIT_TESTS:
|
||||||
|
requires:
|
||||||
|
- CHECKOUT
|
||||||
|
# E2E: PWA + Persist
|
||||||
- cypress/run:
|
- cypress/run:
|
||||||
|
name: 'E2E: PWA'
|
||||||
pre-steps:
|
pre-steps:
|
||||||
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
||||||
add wait-on' # Use yarn latest
|
add wait-on' # Use yarn latest
|
||||||
yarn: true
|
yarn: true
|
||||||
record: true
|
record: true
|
||||||
store_artifacts: true
|
store_artifacts: true
|
||||||
start: yarn run dev
|
|
||||||
wait-on: 'http://localhost:3000'
|
|
||||||
working_directory: platform/viewer
|
working_directory: platform/viewer
|
||||||
|
build: yarn run build:e2e
|
||||||
|
start: yarn run test:e2e:dist
|
||||||
|
wait-on: 'http://localhost:3000'
|
||||||
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
||||||
|
no-workspace: true # Don't persist workspace
|
||||||
post-steps:
|
post-steps:
|
||||||
|
- store_artifacts:
|
||||||
|
path: platform/viewer/cypress/screenshots
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: cypress/results
|
path: cypress/results
|
||||||
requires:
|
requires:
|
||||||
- MERGE_UNIT_TESTS
|
- UNIT_TESTS
|
||||||
|
# E2E: script-tag
|
||||||
|
- cypress/run:
|
||||||
|
name: 'E2E: Script Tag'
|
||||||
|
pre-steps:
|
||||||
|
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
||||||
|
add wait-on' # Use yarn latest
|
||||||
|
yarn: true
|
||||||
|
store_artifacts: false
|
||||||
|
working_directory: platform/viewer
|
||||||
|
build: yarn run build:package
|
||||||
|
start: yarn run test:e2e:dist
|
||||||
|
wait-on: 'http://localhost:3000'
|
||||||
|
cache-key: 'yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}'
|
||||||
|
no-workspace: true # Don't persist workspace
|
||||||
|
post-steps:
|
||||||
|
- store_artifacts:
|
||||||
|
path: platform/viewer/cypress/screenshots
|
||||||
|
- store_test_results:
|
||||||
|
path: cypress/results
|
||||||
|
requires:
|
||||||
|
- UNIT_TESTS
|
||||||
# Update NPM
|
# Update NPM
|
||||||
- npm_publish:
|
- NPM_PUBLISH:
|
||||||
requires:
|
requires:
|
||||||
- cypress/run
|
- 'E2E: Script Tag'
|
||||||
|
- 'E2E: PWA'
|
||||||
# Update docs.ohif.org
|
# Update docs.ohif.org
|
||||||
- docs_publish:
|
- DOCS_PUBLISH:
|
||||||
requires:
|
requires:
|
||||||
- cypress/run
|
- 'E2E: Script Tag'
|
||||||
# Update hub.docker.org
|
- 'E2E: PWA'
|
||||||
# - docker_publish:
|
- VIEWER_DEMO_BUILD:
|
||||||
# requires:
|
requires:
|
||||||
# - npm_publish
|
- 'E2E: Script Tag'
|
||||||
|
- 'E2E: PWA'
|
||||||
# Update viewer.ohif.org
|
# Update viewer.ohif.org
|
||||||
- viewer_demo_build:
|
- VIEWER_DEMO_PUBLISH:
|
||||||
requires:
|
requires:
|
||||||
- cypress/run
|
- VIEWER_DEMO_BUILD
|
||||||
- viewer_demo_publish:
|
# Update hub.docker.org
|
||||||
|
- DOCKER_PUBLISH:
|
||||||
requires:
|
requires:
|
||||||
- viewer_demo_build
|
- NPM_PUBLISH
|
||||||
+3
-1
@@ -8,11 +8,13 @@ coverage:
|
|||||||
status:
|
status:
|
||||||
project:
|
project:
|
||||||
default:
|
default:
|
||||||
threshold: 0.10%
|
threshold: 0.5%
|
||||||
core:
|
core:
|
||||||
flags: core
|
flags: core
|
||||||
|
threshold: 0.5%
|
||||||
viewer:
|
viewer:
|
||||||
flags: viewer
|
flags: viewer
|
||||||
|
threshold: 0.5%
|
||||||
patch: off
|
patch: off
|
||||||
flags:
|
flags:
|
||||||
core:
|
core:
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
location / {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# If CLIENT_ID is specified, use the google.js configuration with the modified ID
|
||||||
|
if [ ! -z "$CLIENT_ID" ]
|
||||||
|
then
|
||||||
|
echo "Google Cloud Healthcare $CLIENT_ID has been provided: "
|
||||||
|
echo $CLIENT_ID
|
||||||
|
echo "Updating config..."
|
||||||
|
|
||||||
|
# - Use SED to replace the CLIENT_ID that is currently in google.js
|
||||||
|
sed -i -e "s/YOURCLIENTID.apps.googleusercontent.com/$CLIENT_ID/g" /usr/share/nginx/html/google.js
|
||||||
|
|
||||||
|
# - Copy google.js to overwrite app-config.js
|
||||||
|
cp /usr/share/nginx/html/google.js /usr/share/nginx/html/app-config.js
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Starting Nginx to serve the OHIF Viewer..."
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Reduces size of context and hides
|
||||||
|
# files from Docker (can't COPY or ADD these)
|
||||||
|
|
||||||
|
# Output
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Root
|
||||||
|
README.md
|
||||||
|
Dockerfile
|
||||||
|
dockerfile
|
||||||
|
|
||||||
|
# Misc. Config
|
||||||
|
.git
|
||||||
|
.DS_Store
|
||||||
|
.gitignore
|
||||||
|
.vscode
|
||||||
|
.circleci
|
||||||
|
|
||||||
|
# Unnecessary things to pull into container
|
||||||
|
.circleci/
|
||||||
|
.github/
|
||||||
|
.netlify/
|
||||||
|
.scripts/
|
||||||
|
.vscode/
|
||||||
|
coverage/
|
||||||
|
docs/
|
||||||
+3
-3
@@ -7,13 +7,13 @@ daysUntilStale: 21
|
|||||||
daysUntilClose: 7
|
daysUntilClose: 7
|
||||||
# Issues with these labels will never be considered stale
|
# Issues with these labels will never be considered stale
|
||||||
exemptLabels:
|
exemptLabels:
|
||||||
- 'Story 🙌'
|
- 'Story :raised_hands:'
|
||||||
- 'Bug: Verified 🐛'
|
- 'Bug: Verified :bug:'
|
||||||
- 'Task: CI/Tooling 🤖'
|
- 'Task: CI/Tooling 🤖'
|
||||||
- 'Task: Docs 📖'
|
- 'Task: Docs 📖'
|
||||||
- 'Task: Docs :book:'
|
- 'Task: Docs :book:'
|
||||||
- 'Task: Refactor 🛠'
|
- 'Task: Refactor 🛠'
|
||||||
- 'Task: Tests 🔬'
|
- 'Task: Tests :microscope:'
|
||||||
- 'PR: Awaiting Review 👀'
|
- 'PR: Awaiting Review 👀'
|
||||||
- 'Triage 🏳️'
|
- 'Triage 🏳️'
|
||||||
- 'Announcement 🎉'
|
- 'Announcement 🎉'
|
||||||
|
|||||||
+2
-2
@@ -28,7 +28,7 @@ example/deps/
|
|||||||
docker/dcm4che/dcm4che-arc
|
docker/dcm4che/dcm4che-arc
|
||||||
|
|
||||||
# Cypress test results
|
# Cypress test results
|
||||||
cypress/videos/
|
videos/
|
||||||
|
|
||||||
# Locize settings
|
# Locize settings
|
||||||
.locize
|
.locize
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Specific to our deploy-preview
|
||||||
|
# Our docs are published using CircleCI + GitBook
|
||||||
|
# Confgure redirects using netlify.toml
|
||||||
|
|
||||||
|
# PWA Demo
|
||||||
|
/pwa/* /pwa/index.html 200
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
# This dockerfile is used to publish the `ohif/viewer` image on dockerhub.
|
||||||
|
#
|
||||||
|
# It's a good example of how to build our static application and package it
|
||||||
|
# with a web server capable of hosting it as static content.
|
||||||
|
#
|
||||||
|
# docker build
|
||||||
|
# --------------
|
||||||
|
# If you would like to use this dockerfile to build and tag an image, make sure
|
||||||
|
# you set the context to the project's root directory:
|
||||||
|
# https://docs.docker.com/engine/reference/commandline/build/
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# SUMMARY
|
||||||
|
# --------------
|
||||||
|
# This dockerfile has two stages:
|
||||||
|
#
|
||||||
|
# 1. Building the React application for production
|
||||||
|
# 2. Setting up our Nginx (Alpine Linux) image w/ step one's output
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# Stage 1: Build the application
|
||||||
|
# docker build -t ohif/viewer:latest .
|
||||||
|
FROM node:10.16.3-slim as builder
|
||||||
|
|
||||||
|
RUN mkdir /usr/src/app
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Copy Files
|
||||||
|
COPY .docker /usr/src/app/.docker
|
||||||
|
COPY .webpack /usr/src/app/.webpack
|
||||||
|
COPY extensions /usr/src/app/extensions
|
||||||
|
COPY platform /usr/src/app/platform
|
||||||
|
COPY .browserslistrc /usr/src/app/.browserslistrc
|
||||||
|
COPY aliases.config.js /usr/src/app/aliases.config.js
|
||||||
|
COPY babel.config.js /usr/src/app/babel.config.js
|
||||||
|
COPY lerna.json /usr/src/app/lerna.json
|
||||||
|
COPY package.json /usr/src/app/package.json
|
||||||
|
COPY postcss.config.js /usr/src/app/postcss.config.js
|
||||||
|
COPY yarn.lock /usr/src/app/yarn.lock
|
||||||
|
|
||||||
|
# Run the install before copying the rest of the files
|
||||||
|
RUN yarn config set workspaces-experimental true
|
||||||
|
RUN yarn install
|
||||||
|
|
||||||
|
ENV PATH /usr/src/app/node_modules/.bin:$PATH
|
||||||
|
# ENV GENERATE_SOURCEMAP=false
|
||||||
|
# ENV REACT_APP_CONFIG=config/default.js
|
||||||
|
|
||||||
|
RUN yarn run build
|
||||||
|
|
||||||
|
# Stage 2: Bundle the built application into a Docker container
|
||||||
|
# which runs Nginx using Alpine Linux
|
||||||
|
FROM nginx:1.15.5-alpine
|
||||||
|
RUN apk add --no-cache bash
|
||||||
|
RUN rm -rf /etc/nginx/conf.d
|
||||||
|
COPY .docker/Viewer-v2.x /etc/nginx/conf.d
|
||||||
|
COPY .docker/Viewer-v2.x/entrypoint.sh /usr/src/
|
||||||
|
RUN chmod 777 /usr/src/entrypoint.sh
|
||||||
|
COPY --from=builder /usr/src/app/platform/viewer/dist /usr/share/nginx/html
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
ENTRYPOINT ["/usr/src/entrypoint.sh"]
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -123,8 +123,7 @@ window.config = {
|
|||||||
`window.OHIFStandaloneViewer.installViewer(window.config);`
|
`window.OHIFStandaloneViewer.installViewer(window.config);`
|
||||||
|
|
||||||
This exact setup is demonstrated in this
|
This exact setup is demonstrated in this
|
||||||
[CodeSandbox](https://codesandbox.io/s/ohif-viewer-script-tag-usage-c4u4t) and
|
[CodeSandbox](https://codesandbox.io/s/viewer-script-tag-tprch) and in our
|
||||||
in our
|
|
||||||
[Embedding The Viewer](https://docs.ohif.org/deployment/recipes/embedded-viewer.html)
|
[Embedding The Viewer](https://docs.ohif.org/deployment/recipes/embedded-viewer.html)
|
||||||
deployment recipe.
|
deployment recipe.
|
||||||
|
|
||||||
@@ -133,7 +132,7 @@ deployment recipe.
|
|||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
- [Yarn 1.17.3+](https://yarnpkg.com/en/docs/install)
|
- [Yarn 1.17.3+](https://yarnpkg.com/en/docs/install)
|
||||||
- [Node 8+](https://nodejs.org/en/)
|
- [Node 10+](https://nodejs.org/en/)
|
||||||
- Yarn Workspaces should be enabled on your machine:
|
- Yarn Workspaces should be enabled on your machine:
|
||||||
- `yarn config set workspaces-experimental true`
|
- `yarn config set workspaces-experimental true`
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Netlify redirects
|
||||||
|
# SPA rules for our docs
|
||||||
|
/* /index.html 200
|
||||||
@@ -160,6 +160,7 @@ An extension can register a Toolbar Module by providing a `getToolbarModule()`
|
|||||||
method that returns a React Component. The component does not receive any props.
|
method that returns a React Component. The component does not receive any props.
|
||||||
If you want to modify or react to state, you will need to connect to the redux
|
If you want to modify or react to state, you will need to connect to the redux
|
||||||
store.
|
store.
|
||||||
|
The given toolbar must determine its set of elements and the context of them. The set of elements will be listed on toolbar `definitions`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -170,6 +171,31 @@ Toolbar components are rendered in the `ToolbarRow` component.
|
|||||||
For a complete example implementation,
|
For a complete example implementation,
|
||||||
[check out the OHIFCornerstoneViewport's Toolbar Module](https://github.com/OHIF/Viewers/blob/master/extensions/cornerstone/src/toolbarModule.js).
|
[check out the OHIFCornerstoneViewport's Toolbar Module](https://github.com/OHIF/Viewers/blob/master/extensions/cornerstone/src/toolbarModule.js).
|
||||||
|
|
||||||
|
##### Toolbar Custom Component
|
||||||
|
|
||||||
|
Toolbar elements can define its own custom react component to be consumed when rendering it. So far, it accepts `Functional` and `Class` Components. For that, you just need to expose your `CustomToolbarComponent` as the value of key `CustomComponent`. In case the property `CustomComponent` is not present, a default toolbar component will be used to render it. See bellow
|
||||||
|
|
||||||
|
```js
|
||||||
|
definitions: [
|
||||||
|
...
|
||||||
|
{
|
||||||
|
id: 'Custom',
|
||||||
|
label: 'Custom',
|
||||||
|
icon: 'custom-icon',
|
||||||
|
CustomComponent: CustomToolbarComponent,
|
||||||
|
}
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
```
|
||||||
|
`CustomComponent` components will receive the following props:
|
||||||
|
- parentContext: parent context. (In most of the cases it will be a ToolbarRow instance)
|
||||||
|
- toolbarClickCallback: callback method when clicking on toolbar
|
||||||
|
- button: its own definition object
|
||||||
|
- key: react key prop
|
||||||
|
- activeButtons: list of active elements
|
||||||
|
- isActive: if current
|
||||||
|
|
||||||
#### SopClassHandler
|
#### SopClassHandler
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -10,7 +10,15 @@ minimum, you may want to read the following documentation:
|
|||||||
- [Essentials: Getting Started](./essentials/getting-started.md)
|
- [Essentials: Getting Started](./essentials/getting-started.md)
|
||||||
- [Advanced: Architecture](./advanced/architecture.md)
|
- [Advanced: Architecture](./advanced/architecture.md)
|
||||||
|
|
||||||
### When changes impact multiple repositories
|
Pull requests that are:
|
||||||
|
|
||||||
|
- Small
|
||||||
|
- [Well tested](./testing.md)
|
||||||
|
- Decoupled
|
||||||
|
|
||||||
|
Are much more likely to get reviewed and merged in a timely manner.
|
||||||
|
|
||||||
|
## When changes impact multiple repositories
|
||||||
|
|
||||||
While this can be tricky, we've tried to reduce how often this situation crops
|
While this can be tricky, we've tried to reduce how often this situation crops
|
||||||
up this with our [recent switch to a monorepo][monorepo]. Our maintained
|
up this with our [recent switch to a monorepo][monorepo]. Our maintained
|
||||||
@@ -22,7 +30,7 @@ package outside of the monorepo is most common with extension development. Let's
|
|||||||
demonstrate how to accomplish this with two commonly forked extension
|
demonstrate how to accomplish this with two commonly forked extension
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
||||||
#### `cornerstone-tools`
|
### `cornerstone-tools`
|
||||||
|
|
||||||
On your local file system:
|
On your local file system:
|
||||||
|
|
||||||
@@ -47,7 +55,12 @@ On your local file system:
|
|||||||
As you make changed to `cornerstone-tools`, and it's output is rebuilt, you
|
As you make changed to `cornerstone-tools`, and it's output is rebuilt, you
|
||||||
should see the following behavior:
|
should see the following behavior:
|
||||||
|
|
||||||
<!-- Insert GIF here -->
|
<div style="text-align: center;">
|
||||||
|
<a href="/assets/img/cornerstone-tools-link.gif">
|
||||||
|
<img src="/assets/img/cornerstone-tools-link.gif" alt="Example of linked cornerstone-tools package" style="margin: 0 auto; max-width: 500px;" />
|
||||||
|
</a>
|
||||||
|
<div><i>example of linked cornerstone-tools package</i></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
If you wish to stop using your local package, run the following commands in the
|
If you wish to stop using your local package, run the following commands in the
|
||||||
`ohif/viewers` repository root:
|
`ohif/viewers` repository root:
|
||||||
@@ -55,9 +68,27 @@ If you wish to stop using your local package, run the following commands in the
|
|||||||
- `yarn unlink cornerstone-tools`
|
- `yarn unlink cornerstone-tools`
|
||||||
- `yarn install --force`
|
- `yarn install --force`
|
||||||
|
|
||||||
#### `react-vtkjs-viewport`
|
### `react-vtkjs-viewport`
|
||||||
|
|
||||||
...
|
On your local file system:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# code/my-projects/
|
||||||
|
.
|
||||||
|
├── ohif/react-vtkjs-viewport
|
||||||
|
└── ohif/viewers
|
||||||
|
```
|
||||||
|
|
||||||
|
- Open a terminal/shell
|
||||||
|
- Navigate to `ohif/react-vtkjs-viewport`
|
||||||
|
- `yarn install`
|
||||||
|
- [`yarn link`](https://yarnpkg.com/en/docs/cli/link)
|
||||||
|
- `yarn run start`
|
||||||
|
- Open a new terminal/shell
|
||||||
|
- Navigate to `ohif/viewers`.
|
||||||
|
- `yarn install`
|
||||||
|
- [`yarn link react-vtkjs-viewport`](https://yarnpkg.com/en/docs/cli/link)
|
||||||
|
- `yarn run dev`
|
||||||
|
|
||||||
#### Other linkage notes
|
#### Other linkage notes
|
||||||
|
|
||||||
|
|||||||
@@ -205,5 +205,5 @@ Please feel free to suggest or contribute your own recipes.
|
|||||||
[host-static-assets]: https://www.netlify.com/blog/2016/05/18/9-reasons-your-site-should-be-static/
|
[host-static-assets]: https://www.netlify.com/blog/2016/05/18/9-reasons-your-site-should-be-static/
|
||||||
[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||||
[code-flows]: https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660
|
[code-flows]: https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660
|
||||||
[code-sandbox]: https://codesandbox.io/s/ohif-viewer-script-tag-usage-b3st9
|
[code-sandbox]: https://codesandbox.io/s/viewer-script-tag-tprch
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
@@ -19,9 +19,6 @@ _With Git:_
|
|||||||
```bash
|
```bash
|
||||||
# Clone the remote repository to your local machine
|
# Clone the remote repository to your local machine
|
||||||
git clone https://github.com/OHIF/Viewers.git
|
git clone https://github.com/OHIF/Viewers.git
|
||||||
|
|
||||||
# Make sure the local code reflects the `react` version of the OHIF Viewer
|
|
||||||
git checkout react
|
|
||||||
```
|
```
|
||||||
|
|
||||||
More on: _[`git clone`](https://git-scm.com/docs/git-clone),
|
More on: _[`git clone`](https://git-scm.com/docs/git-clone),
|
||||||
@@ -29,7 +26,7 @@ More on: _[`git clone`](https://git-scm.com/docs/git-clone),
|
|||||||
|
|
||||||
_From .zip:_
|
_From .zip:_
|
||||||
|
|
||||||
[OHIF/Viewers: react.zip](https://github.com/OHIF/Viewers/archive/react.zip)
|
[OHIF/Viewers: react.zip](https://github.com/OHIF/Viewers/archive/master.zip)
|
||||||
|
|
||||||
### Restore Dependencies & Build
|
### Restore Dependencies & Build
|
||||||
|
|
||||||
@@ -37,20 +34,24 @@ Open your terminal, and navigate to the directory containing the source files.
|
|||||||
Next run these commands:
|
Next run these commands:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
// If you haven't already, enable yarn workspaces
|
||||||
|
yarn config set workspaces-experimental true
|
||||||
|
|
||||||
// Restore dependencies
|
// Restore dependencies
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
// Build source code for production
|
// Build source code for production
|
||||||
yarn run build:web
|
yarn run build
|
||||||
```
|
```
|
||||||
|
|
||||||
If everything worked as expected, you should have a new `build/` directory in
|
If everything worked as expected, you should have a new `dist/` directory in the
|
||||||
the project's folder. It should roughly resemble the following:
|
project's folder. It should roughly resemble the following:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
build
|
dist/
|
||||||
├── config/
|
├── app-config.js
|
||||||
├── static/
|
├── app.bundle.js
|
||||||
|
├── app.css
|
||||||
├── index.html
|
├── index.html
|
||||||
├── manifest.json
|
├── manifest.json
|
||||||
├── service-worker.js
|
├── service-worker.js
|
||||||
@@ -64,60 +65,15 @@ how to configure the project for your own imaging archive below.
|
|||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
> This step assumes you have an imaging archive. If you need assistance setting
|
The configuration for our viewer is in the `<root>platform/viewer/public/config`
|
||||||
> one up, check out the [`Data Source` Guide](./../../essentials/data-source.md)
|
directory. Our build process knows which configuration file to use based on the
|
||||||
> or a deployment recipe that contains an open source Image Archive
|
`APP_CONFIG` environment variable. By default, its value is
|
||||||
|
[`config/default.js`][default-config]. The majority of the viewer's features,
|
||||||
|
and registered extension's features, are configured using this file.
|
||||||
|
|
||||||
#### How it Works
|
The easiest way to apply your own configuration is to modify the `default.js`
|
||||||
|
file. For more advanced cofiguration options, check out our
|
||||||
The configuration for our project is in the `/public/config` directory. Our
|
[configuration essentials guide](/essentials/configuration.md).
|
||||||
build process knows which configuration file to use based on the `APP_CONFIG`
|
|
||||||
environment variable. By default, its value is
|
|
||||||
[`default.js`](https://github.com/OHIF/Viewers/blob/master/platform/viewer/public/config/default.js).
|
|
||||||
When we build, the `%APP_CONFIG%` value in
|
|
||||||
our[`/public/index.html`](https://github.com/OHIF/Viewers/blob/master/platform/viewer/public/index.html)
|
|
||||||
file is substituted for the correct configuration file's name. This sets
|
|
||||||
the`window.config` equal to our configuration file's value.
|
|
||||||
|
|
||||||
#### How do I configure my project?
|
|
||||||
|
|
||||||
The simplest way is to update the existing default config:
|
|
||||||
|
|
||||||
_/public/config/default.js_
|
|
||||||
|
|
||||||
```js
|
|
||||||
window.config = {
|
|
||||||
routerBasename: '/',
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also create a new config file and specify its path relative to the build
|
|
||||||
output's root by setting the `APP_CONFIG` environment variable. You can set the
|
|
||||||
value of this environment variable a few different ways:
|
|
||||||
|
|
||||||
- [Add a temporary environment variable in your shell](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#adding-temporary-environment-variables-in-your-shell)
|
|
||||||
- [Add environment specific variables in `.env` file(s)](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#adding-development-environment-variables-in-env)
|
|
||||||
- Using the `cross-env` package in an npm script:
|
|
||||||
- `"build": "cross-env APP_CONFIG=config/my-config.js react-scripts build"`
|
|
||||||
|
|
||||||
After updating the configuration, `yarn run build:web` to generate updated build
|
|
||||||
output.
|
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
@@ -141,7 +97,7 @@ _Advanced_
|
|||||||
### Testing Build Output Locally
|
### Testing Build Output Locally
|
||||||
|
|
||||||
A quick way to test your build output locally is to spin up a small webserver.
|
A quick way to test your build output locally is to spin up a small webserver.
|
||||||
You can do this by running the following commands in the `build/` output
|
You can do this by running the following commands in the `dist/` output
|
||||||
directory:
|
directory:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -162,8 +118,7 @@ web application. For a starting point, check out this repository's own use of:
|
|||||||
|
|
||||||
- [CircleCI][circleci]: [config.yaml][circleci-config]
|
- [CircleCI][circleci]: [config.yaml][circleci-config]
|
||||||
- [Netlify][netlify]: [netlify.toml][netlify.toml] |
|
- [Netlify][netlify]: [netlify.toml][netlify.toml] |
|
||||||
[generateStaticSite.sh][generatestaticsite.sh]
|
[build-deploy-preview.sh][build-deploy-preview.sh]
|
||||||
- [Semantic-Release][semantic-release]: [.releaserc][releaserc]
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
@@ -173,10 +128,8 @@ web application. For a starting point, check out this repository's own use of:
|
|||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
<!-- prettier-ignore-start -->
|
||||||
[circleci]: https://circleci.com/gh/OHIF/Viewers
|
[circleci]: https://circleci.com/gh/OHIF/Viewers
|
||||||
[circleci-config]: https://github.com/OHIF/Viewers/blob/react/.circleci/config.yml
|
[circleci-config]: https://github.com/OHIF/Viewers/blob/master/.circleci/config.yml
|
||||||
[netlify]: https://app.netlify.com/sites/ohif/deploys
|
[netlify]: https://app.netlify.com/sites/ohif/deploys
|
||||||
[netlify.toml]: https://github.com/OHIF/Viewers/blob/react/netlify.toml
|
[netlify.toml]: https://github.com/OHIF/Viewers/blob/master/netlify.toml
|
||||||
[generateStaticSite.sh]: https://github.com/OHIF/Viewers/blob/react/generateStaticSite.sh
|
[build-deploy-preview.sh]: https://github.com/OHIF/Viewers/blob/master/.netlify/build-deploy-preview.sh
|
||||||
[semantic-release]: https://semantic-release.gitbook.io/semantic-release/
|
|
||||||
[releaserc]: https://github.com/OHIF/Viewers/blob/react/.releaserc
|
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
@@ -16,16 +16,6 @@ include tags. Here's how it works:
|
|||||||
<code>Google Font: Roboto</code>
|
<code>Google Font: Roboto</code>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a href="https://unpkg.com/react@16/umd/react.production.min.js">
|
|
||||||
<code>react@16.8.6</code>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js">
|
|
||||||
<code>react-dom@16.8.6</code>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<a href="https://unpkg.com/@ohif/viewer">
|
<a href="https://unpkg.com/@ohif/viewer">
|
||||||
<code>@ohif/viewer@latest</code>
|
<code>@ohif/viewer@latest</code>
|
||||||
@@ -53,28 +43,64 @@ window.config = {
|
|||||||
qidoSupportsIncludeField: true,
|
qidoSupportsIncludeField: true,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
<ol start="5"><li>
|
<ol start="3"><li>
|
||||||
Render the viewer in the web page's target <code>div</code>
|
Render the viewer in the web page's target <code>div</code>
|
||||||
</li></ol>
|
</li></ol>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Made available by the `@ohif/viewer` script included in step 1
|
// Made available by the `@ohif/viewer` script included in step 1
|
||||||
var Viewer = window.OHIFStandaloneViewer.App;
|
var containerId = 'id-of-div-to-render-component-to';
|
||||||
var app = React.createElement(Viewer, window.config, null);
|
var componentRenderedOrUpdatedCallback = function() {
|
||||||
|
console.log('OHIF Viewer rendered/updated');
|
||||||
ReactDOM.render(app, document.getElementById('ohif-viewer-target'));
|
};
|
||||||
|
window.OHIFViewer.installViewer(
|
||||||
|
window.config,
|
||||||
|
containerId,
|
||||||
|
componentRenderedOrUpdatedCallback
|
||||||
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Tips & Tricks
|
You can see a live example of this recipe in [this CodeSandbox][code-sandbox].
|
||||||
|
|
||||||
|
## Add Extensions
|
||||||
|
|
||||||
|
The UMD build of the OHIF Viewer is a "light weight" build that only contains
|
||||||
|
the core extensions required for basic 2D image viewing. It's possible to add
|
||||||
|
other extensions at runtime.
|
||||||
|
|
||||||
|
This only requires us to include a single script tag, and add it using the
|
||||||
|
`extensions` key to our config. In this practical example, we register our
|
||||||
|
popular whole slide microscopy extension:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script
|
||||||
|
src="https://unpkg.com/@ohif/extension-dicom-microscopy@0.50.5/dist/index.umd.js"
|
||||||
|
crossorigin
|
||||||
|
></script>
|
||||||
|
|
||||||
|
<!-- --->
|
||||||
|
<script>
|
||||||
|
window.config = {
|
||||||
|
// ...
|
||||||
|
extensions: [OHIFExtDicomMicroscopy],
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
You can see an example of a slide microscopy study in the viewer [with the
|
||||||
|
extension enabled here][whole-slide-ext-demo] ([source code][ext-code-sandbox])
|
||||||
|
and [without it here][whole-slide-base-demo] ([source code][code-sandbox]).
|
||||||
|
|
||||||
|
You can read more about extensions and how to create your own in our
|
||||||
|
[extensions guide](/advanced/extensions.md).
|
||||||
|
|
||||||
|
#### FAQ
|
||||||
|
|
||||||
> I'm having trouble getting this to work. Where can I go for help?
|
> I'm having trouble getting this to work. Where can I go for help?
|
||||||
|
|
||||||
@@ -94,8 +120,22 @@ Good. Now `embed` that new page using an
|
|||||||
This should produce the expected result while also protecting your page from any
|
This should produce the expected result while also protecting your page from any
|
||||||
globally defined styles/scripts.
|
globally defined styles/scripts.
|
||||||
|
|
||||||
|
> We're trying to embed the OHIF Viewer into an existing React App, but seeing
|
||||||
|
> react-dom and react conflicts. What can we do?
|
||||||
|
|
||||||
|
`installViewer` is a convenience method that pulls in some dependencies that may
|
||||||
|
not be compatible with existing `react` apps. `@ohif/viewer` also exports `App`
|
||||||
|
which is a react component that takes the `configuration` outlined above as
|
||||||
|
props. You can use it as a reusable component, and to avoid `react` version
|
||||||
|
conflict issues.
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
LINKS
|
LINKS
|
||||||
-->
|
-->
|
||||||
|
|
||||||
[code-sandbox]: https://codesandbox.io/s/ohif-viewer-script-tag-usage-b3st9
|
<!-- prettier-ignore-start -->
|
||||||
|
[code-sandbox]: https://codesandbox.io/s/viewer-script-tag-tprch
|
||||||
|
[whole-slide-base-demo]: https://tprch.csb.app/viewer/1.2.392.200140.2.1.1.1.2.799008771.2020.1519719354.757
|
||||||
|
[ext-code-sandbox]: https://codesandbox.io/s/viewer-script-tag-microscopy-extension-44unk
|
||||||
|
[whole-slide-ext-demo]: https://44unk.csb.app/viewer/1.2.392.200140.2.1.1.1.2.799008771.2448.1519719572.518
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
@@ -121,11 +121,7 @@ likely want to update:
|
|||||||
|
|
||||||
#### OHIF Viewer
|
#### OHIF Viewer
|
||||||
|
|
||||||
The OHIF Viewer's configuration is imported from a static `.js` file and made
|
The OHIF Viewer's configuration is imported from a static `.js` file. The configuration we use is set to a specific file when we build the viewer, and determined by the env variable: `APP_CONFIG`. You can see where we set its value in the `dockerfile` for this solution:
|
||||||
available globally at `window.config`. The configuration we use is set to a
|
|
||||||
specific file when we build the viewer, and determined by the env variable:
|
|
||||||
`APP_CONFIG`. You can see where we set its value in the `dockerfile` for this
|
|
||||||
solution:
|
|
||||||
|
|
||||||
`ENV APP_CONFIG=config/docker_openresty-orthanc.js`
|
`ENV APP_CONFIG=config/docker_openresty-orthanc.js`
|
||||||
|
|
||||||
|
|||||||
@@ -122,11 +122,7 @@ likely want to update:
|
|||||||
|
|
||||||
#### OHIF Viewer
|
#### OHIF Viewer
|
||||||
|
|
||||||
The OHIF Viewer's configuration is imported from a static `.js` file and made
|
The OHIF Viewer's configuration is imported from a static `.js` file. The configuration we use is set to a specific file when we build the viewer, and determined by the env variable: `APP_CONFIG`. You can see where we set its value in the `dockerfile` for this solution:
|
||||||
available globally at `window.config`. The configuration we use is set to a
|
|
||||||
specific file when we build the viewer, and determined by the env variable:
|
|
||||||
`APP_CONFIG`. You can see where we set its value in the `dockerfile` for this
|
|
||||||
solution:
|
|
||||||
|
|
||||||
`ENV APP_CONFIG=config/docker_openresty-orthanc-keycloak.js`
|
`ENV APP_CONFIG=config/docker_openresty-orthanc-keycloak.js`
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,6 @@ window.config = {
|
|||||||
qidoSupportsIncludeField: true,
|
qidoSupportsIncludeField: true,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||||
@@ -29,9 +30,15 @@ module.exports = (env, argv) => {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: ROOT_DIR,
|
path: ROOT_DIR,
|
||||||
library: 'ohifExtensionCornerstone',
|
library: 'OHIFExtCornerstone',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
|
libraryExport: 'default',
|
||||||
filename: pkg.main,
|
filename: pkg.main,
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({
|
||||||
|
maxChunks: 1,
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,130 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.2.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.2.4...@ohif/extension-cornerstone@1.2.5) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* version bump issue ([#963](https://github.com/OHIF/Viewers/issues/963)) ([e607ed2](https://github.com/OHIF/Viewers/commit/e607ed2)), closes [#962](https://github.com/OHIF/Viewers/issues/962)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.0.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.2.2...@ohif/extension-cornerstone@2.0.0) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Add DicomLoaderService & FileLoaderService to fix SR, PDF, and SEG support in local file and WADO-RS-only use cases ([#862](https://github.com/OHIF/Viewers/issues/862)) ([e7e1a8a](https://github.com/OHIF/Viewers/commit/e7e1a8a)), closes [#838](https://github.com/OHIF/Viewers/issues/838)
|
||||||
|
* version bump issue ([#962](https://github.com/OHIF/Viewers/issues/962)) ([c80ea17](https://github.com/OHIF/Viewers/commit/c80ea17))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* DICOM Seg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.0.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.2.2...@ohif/extension-cornerstone@2.0.0) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Add DicomLoaderService & FileLoaderService to fix SR, PDF, and SEG support in local file and WADO-RS-only use cases ([#862](https://github.com/OHIF/Viewers/issues/862)) ([e7e1a8a](https://github.com/OHIF/Viewers/commit/e7e1a8a)), closes [#838](https://github.com/OHIF/Viewers/issues/838)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* DICOM Seg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.2.1...@ohif/extension-cornerstone@1.2.2) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Add some code splitting for PWA build ([#937](https://github.com/OHIF/Viewers/issues/937)) ([8938035](https://github.com/OHIF/Viewers/commit/8938035))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.2.0...@ohif/extension-cornerstone@1.2.1) (2019-09-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* bump cornerstone-tools version in peerDeps ([4afc88c](https://github.com/OHIF/Viewers/commit/4afc88c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.2.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.1.1...@ohif/extension-cornerstone@1.2.0) (2019-09-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Annotate:** Add annotate tool back to toolbar ([26be967](https://github.com/OHIF/Viewers/commit/26be967))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.1.0...@ohif/extension-cornerstone@1.1.1) (2019-09-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.1.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.0.1...@ohif/extension-cornerstone@1.1.0) (2019-09-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **BidirectionalTool:** Add BidrectionalTool to "more" menu ([#911](https://github.com/OHIF/Viewers/issues/911)) ([e40cbae](https://github.com/OHIF/Viewers/commit/e40cbae))
|
||||||
|
* **EraserTool:** add eraserTool to @ohif/extension-cornerstone ([#912](https://github.com/OHIF/Viewers/issues/912)) ([698d274](https://github.com/OHIF/Viewers/commit/698d274))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@1.0.0...@ohif/extension-cornerstone@1.0.1) (2019-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* simplify runtime-extension usage ([ac5dbda](https://github.com/OHIF/Viewers/commit/ac5dbda))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.0.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.50.5...@ohif/extension-cornerstone@1.0.0) (2019-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 Upgraded to cornerstoneTools 4.0 ([86adb51](https://github.com/OHIF/Viewers/commit/86adb51))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* n
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.50.4...@ohif/extension-cornerstone@0.50.5) (2019-09-06)
|
## [0.50.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@0.50.4...@ohif/extension-cornerstone@0.50.5) (2019-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-cornerstone",
|
"name": "@ohif/extension-cornerstone",
|
||||||
"version": "0.50.5",
|
"version": "1.2.5",
|
||||||
"description": "OHIF extension for Cornerstone",
|
"description": "OHIF extension for Cornerstone",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -32,14 +32,14 @@
|
|||||||
"@ohif/ui": "^0.50.0",
|
"@ohif/ui": "^0.50.0",
|
||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-math": "^0.1.8",
|
"cornerstone-math": "^0.1.8",
|
||||||
"cornerstone-tools": "^3.1.0",
|
"cornerstone-tools": "^4.0.9",
|
||||||
"cornerstone-wado-image-loader": "^3.0.0",
|
"cornerstone-wado-image-loader": "^3.0.0",
|
||||||
"dcmjs": "^0.3.8",
|
"dcmjs": "^0.6.1",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^15.0.0 || ^16.0.0",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^15.0.0 || ^16.0.0",
|
"react-dom": "^16.8.6",
|
||||||
"react-redux": "^6.0.0",
|
"react-redux": "^6.0.0",
|
||||||
"react-resize-detector": "^3.4.0",
|
"react-resize-detector": "^3.4.0",
|
||||||
"redux": "^4.0.1"
|
"redux": "^4.0.1"
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* We use this component to leverage "Code Splitting"
|
||||||
|
*
|
||||||
|
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export default function asyncComponent(importComponent) {
|
||||||
|
class AsyncComponent extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
component: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
// Add dynamically loaded component to state
|
||||||
|
const { default: component } = await importComponent();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
component: component,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const C = this.state.component;
|
||||||
|
|
||||||
|
// Render the loaded component, or null
|
||||||
|
return C ? <C {...this.props} /> : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AsyncComponent;
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as dcmjs from "dcmjs";
|
import * as dcmjs from 'dcmjs';
|
||||||
|
|
||||||
import OHIF from "@ohif/core";
|
import OHIF from '@ohif/core';
|
||||||
import cornerstone from "cornerstone-core";
|
import cornerstone from 'cornerstone-core';
|
||||||
import cornerstoneTools from "cornerstone-tools";
|
import cornerstoneTools from 'cornerstone-tools';
|
||||||
|
|
||||||
const { StackManager } = OHIF.utils;
|
const { StackManager, DicomLoaderService } = OHIF.utils;
|
||||||
|
|
||||||
function getDisplaySet(studies, studyInstanceUid, displaySetInstanceUid) {
|
function getDisplaySet(studies, studyInstanceUid, displaySetInstanceUid) {
|
||||||
const study = studies.find(
|
const study = studies.find(
|
||||||
@@ -52,14 +52,6 @@ function addSegMetadataToCornerstoneToolState(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function retrieveDicomData(wadoUri) {
|
|
||||||
// TODO: Authorization header depends on the server. If we ever have multiple servers
|
|
||||||
// we will need to figure out how / when to pass this information in.
|
|
||||||
return fetch(wadoUri, {
|
|
||||||
headers: OHIF.DICOMWeb.getAuthorizationHeader()
|
|
||||||
}).then(response => response.arrayBuffer());
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSegmentationStorage(
|
async function handleSegmentationStorage(
|
||||||
studies,
|
studies,
|
||||||
studyInstanceUid,
|
studyInstanceUid,
|
||||||
@@ -73,8 +65,11 @@ async function handleSegmentationStorage(
|
|||||||
studyInstanceUid,
|
studyInstanceUid,
|
||||||
displaySetInstanceUid
|
displaySetInstanceUid
|
||||||
);
|
);
|
||||||
const segWadoUri = displaySet.images[0].getData().wadouri;
|
|
||||||
const arrayBuffer = await retrieveDicomData(segWadoUri);
|
const arrayBuffer = await DicomLoaderService.findDicomDataPromise(
|
||||||
|
displaySet,
|
||||||
|
studies
|
||||||
|
);
|
||||||
const dicomData = dcmjs.data.DicomMessage.readFile(arrayBuffer);
|
const dicomData = dcmjs.data.DicomMessage.readFile(arrayBuffer);
|
||||||
const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(
|
const dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(
|
||||||
dicomData.dict
|
dicomData.dict
|
||||||
@@ -91,7 +86,7 @@ async function handleSegmentationStorage(
|
|||||||
|
|
||||||
if (displaySets.length > 1) {
|
if (displaySets.length > 1) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"More than one display set with the same seriesInstanceUid. This is not supported yet..."
|
'More than one display set with the same seriesInstanceUid. This is not supported yet...'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,17 +95,19 @@ async function handleSegmentationStorage(
|
|||||||
const results = parseSeg(arrayBuffer, imageIds);
|
const results = parseSeg(arrayBuffer, imageIds);
|
||||||
|
|
||||||
if (!results) {
|
if (!results) {
|
||||||
throw new Error("Fractional segmentations are not supported");
|
throw new Error('Fractional segmentations are not supported');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { segMetadata, toolState } = results;
|
const { labelmapBuffer, segMetadata, segmentsOnFrame } = results;
|
||||||
|
const { setters } = cornerstoneTools.getModule('segmentation');
|
||||||
|
|
||||||
segMetadata.seriesInstanceUid = seriesInstanceUid;
|
setters.labelmap3DByFirstImageId(
|
||||||
|
imageIds[0],
|
||||||
addSegMetadataToCornerstoneToolState(
|
labelmapBuffer,
|
||||||
|
0, // TODO -> Can define a color LUT based on colors in the SEG later.
|
||||||
segMetadata,
|
segMetadata,
|
||||||
toolState,
|
imageIds.length,
|
||||||
displaySetInstanceUid
|
segmentsOnFrame
|
||||||
);
|
);
|
||||||
|
|
||||||
const cachedStack = StackManager.findOrCreateStack(
|
const cachedStack = StackManager.findOrCreateStack(
|
||||||
@@ -118,12 +115,13 @@ async function handleSegmentationStorage(
|
|||||||
referenceDisplaySet
|
referenceDisplaySet
|
||||||
);
|
);
|
||||||
const stack = Object.assign({}, cachedStack);
|
const stack = Object.assign({}, cachedStack);
|
||||||
|
|
||||||
stack.currentImageIdIndex = 0;
|
stack.currentImageIdIndex = 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
studyInstanceUid,
|
studyInstanceUid,
|
||||||
displaySetInstanceUid,
|
displaySetInstanceUid,
|
||||||
stack
|
stack,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import OHIFCornerstoneViewport from './OHIFCornerstoneViewport.js';
|
import asyncComponent from './asyncComponent.js';
|
||||||
import commandsModule from './commandsModule.js';
|
import commandsModule from './commandsModule.js';
|
||||||
import toolbarModule from './toolbarModule.js';
|
import toolbarModule from './toolbarModule.js';
|
||||||
|
|
||||||
|
const OHIFCornerstoneViewport = asyncComponent(() => import( /* webpackChunkName: "OHIFCornerstoneViewport" */ './OHIFCornerstoneViewport.js'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -69,6 +69,15 @@ const definitions = [
|
|||||||
commandName: 'setToolActive',
|
commandName: 'setToolActive',
|
||||||
commandOptions: { toolName: 'Length' },
|
commandOptions: { toolName: 'Length' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'ArrowAnnotate',
|
||||||
|
label: 'Annotate',
|
||||||
|
icon: 'measure-non-target',
|
||||||
|
//
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||||
|
commandName: 'setToolActive',
|
||||||
|
commandOptions: { toolName: 'ArrowAnnotate' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'Angle',
|
id: 'Angle',
|
||||||
label: 'Angle',
|
label: 'Angle',
|
||||||
@@ -186,6 +195,24 @@ const definitions = [
|
|||||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||||
commandName: 'clearAnnotations',
|
commandName: 'clearAnnotations',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'Bidirectional',
|
||||||
|
label: 'Bidirectional',
|
||||||
|
icon: 'measure-target',
|
||||||
|
//
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||||
|
commandName: 'setToolActive',
|
||||||
|
commandOptions: { toolName: 'Bidirectional' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'Eraser',
|
||||||
|
label: 'Eraser',
|
||||||
|
icon: 'eraser',
|
||||||
|
//
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||||
|
commandName: 'setToolActive',
|
||||||
|
commandOptions: { toolName: 'Eraser' },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||||
@@ -29,9 +30,15 @@ module.exports = (env, argv) => {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: ROOT_DIR,
|
path: ROOT_DIR,
|
||||||
library: 'ohifExtensionDicomHtml',
|
library: 'OHIFExtDicomHtml',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
|
libraryExport: 'default',
|
||||||
filename: pkg.main,
|
filename: pkg.main,
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({
|
||||||
|
maxChunks: 1,
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,60 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.0.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.8...@ohif/extension-dicom-html@1.0.0) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Add DicomLoaderService & FileLoaderService to fix SR, PDF, and SEG support in local file and WADO-RS-only use cases ([#862](https://github.com/OHIF/Viewers/issues/862)) ([e7e1a8a](https://github.com/OHIF/Viewers/commit/e7e1a8a)), closes [#838](https://github.com/OHIF/Viewers/issues/838)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* DICOM Seg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.7...@ohif/extension-dicom-html@0.50.8) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Add some code splitting for PWA build ([#937](https://github.com/OHIF/Viewers/issues/937)) ([8938035](https://github.com/OHIF/Viewers/commit/8938035))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.6...@ohif/extension-dicom-html@0.50.7) (2019-09-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.5...@ohif/extension-dicom-html@0.50.6) (2019-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* simplify runtime-extension usage ([ac5dbda](https://github.com/OHIF/Viewers/commit/ac5dbda))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.4...@ohif/extension-dicom-html@0.50.5) (2019-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-dicom-html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.3...@ohif/extension-dicom-html@0.50.4) (2019-09-06)
|
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@0.50.3...@ohif/extension-dicom-html@0.50.4) (2019-09-06)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-html",
|
"name": "@ohif/extension-dicom-html",
|
||||||
"version": "0.50.4",
|
"version": "1.0.0",
|
||||||
"description": "OHIF extension for rendering structured reports to HTML",
|
"description": "OHIF extension for rendering structured reports to HTML",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -29,10 +29,10 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "^0.50.0",
|
"@ohif/core": "^0.50.0",
|
||||||
"dcmjs": "^0.3.3",
|
"dcmjs": "^0.6.1",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^15.0.0 || ^16.0.0",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^15.0.0 || ^16.0.0"
|
"react-dom": "^16.8.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5"
|
"@babel/runtime": "^7.5.5"
|
||||||
|
|||||||
@@ -1,46 +1,34 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import DicomHtmlViewport from './DicomHtmlViewport';
|
import DicomHtmlViewport from './DicomHtmlViewport';
|
||||||
|
import OHIF from '@ohif/core';
|
||||||
|
const { DicomLoaderService } = OHIF.utils;
|
||||||
|
|
||||||
class OHIFDicomHtmlViewport extends Component {
|
class OHIFDicomHtmlViewport extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
studies: PropTypes.object,
|
studies: PropTypes.object,
|
||||||
displaySet: PropTypes.object,
|
displaySet: PropTypes.object,
|
||||||
viewportIndex: PropTypes.number
|
viewportIndex: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
byteArray: null,
|
byteArray: null,
|
||||||
error: null
|
error: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { displaySet } = this.props.viewportData;
|
const { displaySet, studies } = this.props.viewportData;
|
||||||
const {
|
|
||||||
studyInstanceUid,
|
|
||||||
seriesInstanceUid,
|
|
||||||
sopInstanceUid,
|
|
||||||
wadoRoot,
|
|
||||||
wadoUri,
|
|
||||||
authorizationHeaders
|
|
||||||
} = displaySet;
|
|
||||||
|
|
||||||
this.retrieveDicomData(
|
DicomLoaderService.findDicomDataPromise(displaySet, studies).then(
|
||||||
studyInstanceUid,
|
data => {
|
||||||
seriesInstanceUid,
|
const byteArray = new Uint8Array(data);
|
||||||
sopInstanceUid,
|
|
||||||
wadoRoot,
|
|
||||||
wadoUri,
|
|
||||||
authorizationHeaders
|
|
||||||
).then(
|
|
||||||
byteArray => {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
byteArray
|
byteArray: byteArray,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.setState({
|
this.setState({
|
||||||
error
|
error,
|
||||||
});
|
});
|
||||||
|
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
@@ -48,27 +36,6 @@ class OHIFDicomHtmlViewport extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
retrieveDicomData(
|
|
||||||
studyInstanceUid,
|
|
||||||
seriesInstanceUid,
|
|
||||||
sopInstanceUid,
|
|
||||||
wadoRoot,
|
|
||||||
wadoUri,
|
|
||||||
authorizationHeaders
|
|
||||||
) {
|
|
||||||
// TODO: Passing in a lot of data we aren't using
|
|
||||||
|
|
||||||
// TODO: Authorization header depends on the server. If we ever have multiple servers
|
|
||||||
// we will need to figure out how / when to pass this information in.
|
|
||||||
return fetch(wadoUri, {
|
|
||||||
headers: authorizationHeaders
|
|
||||||
})
|
|
||||||
.then(response => response.arrayBuffer())
|
|
||||||
.then(arraybuffer => {
|
|
||||||
return new Uint8Array(arraybuffer);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* We use this component to leverage "Code Splitting"
|
||||||
|
*
|
||||||
|
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export default function asyncComponent(importComponent) {
|
||||||
|
class AsyncComponent extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
component: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
// Add dynamically loaded component to state
|
||||||
|
const { default: component } = await importComponent();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
component: component,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const C = this.state.component;
|
||||||
|
|
||||||
|
// Render the loaded component, or null
|
||||||
|
return C ? <C {...this.props} /> : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AsyncComponent;
|
||||||
|
}
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
|
import asyncComponent from './asyncComponent.js';
|
||||||
import OHIFDicomHtmlSopClassHandler from './OHIFDicomHtmlSopClassHandler.js';
|
import OHIFDicomHtmlSopClassHandler from './OHIFDicomHtmlSopClassHandler.js';
|
||||||
import OHIFDicomHtmlViewport from './OHIFDicomHtmlViewport.js';
|
|
||||||
|
const OHIFDicomHtmlViewport = asyncComponent(() =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "OHIFDicomHtmlViewport" */ './OHIFDicomHtmlViewport.js'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
@@ -12,5 +18,5 @@ export default {
|
|||||||
},
|
},
|
||||||
getSopClassHandlerModule() {
|
getSopClassHandlerModule() {
|
||||||
return OHIFDicomHtmlSopClassHandler;
|
return OHIFDicomHtmlSopClassHandler;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||||
@@ -29,9 +30,15 @@ module.exports = (env, argv) => {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: ROOT_DIR,
|
path: ROOT_DIR,
|
||||||
library: 'ohifExtensionDicomMicroscopy',
|
library: 'OHIFExtDicomMicroscopy',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
|
libraryExport: 'default',
|
||||||
filename: pkg.main,
|
filename: pkg.main,
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({
|
||||||
|
maxChunks: 1
|
||||||
|
})
|
||||||
|
]
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,28 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [0.50.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.50.5...@ohif/extension-dicom-microscopy@0.50.6) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Add some code splitting for PWA build ([#937](https://github.com/OHIF/Viewers/issues/937)) ([8938035](https://github.com/OHIF/Viewers/commit/8938035))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.50.4...@ohif/extension-dicom-microscopy@0.50.5) (2019-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* simplify runtime-extension usage ([ac5dbda](https://github.com/OHIF/Viewers/commit/ac5dbda))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.50.3...@ohif/extension-dicom-microscopy@0.50.4) (2019-09-04)
|
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.50.3...@ohif/extension-dicom-microscopy@0.50.4) (2019-09-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
**Note:** Version bump only for package @ohif/extension-dicom-microscopy
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-microscopy",
|
"name": "@ohif/extension-dicom-microscopy",
|
||||||
"version": "0.50.4",
|
"version": "0.50.6",
|
||||||
"description": "OHIF extension for Dicom Microscopy",
|
"description": "OHIF extension for Dicom Microscopy",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "^0.50.0",
|
"@ohif/core": "^0.50.0",
|
||||||
"react": "^15.0.0 || ^16.0.0",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^15.0.0 || ^16.0.0"
|
"react-dom": "^16.8.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import ReactResizeDetector from 'react-resize-detector';
|
import ReactResizeDetector from 'react-resize-detector';
|
||||||
import { api } from 'dicom-microscopy-viewer';
|
|
||||||
import debounce from 'lodash.debounce';
|
import debounce from 'lodash.debounce';
|
||||||
|
|
||||||
const microscopyViewer = api.VLWholeSlideMicroscopyImageViewer;
|
|
||||||
|
|
||||||
class DicomMicroscopyViewport extends Component {
|
class DicomMicroscopyViewport extends Component {
|
||||||
state = {
|
state = {
|
||||||
error: null,
|
error: null,
|
||||||
@@ -56,9 +53,12 @@ class DicomMicroscopyViewport extends Component {
|
|||||||
}
|
}
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
})
|
})
|
||||||
.then(metadata => {
|
.then(async metadata => {
|
||||||
metadata = metadata.filter(m => m);
|
metadata = metadata.filter(m => m);
|
||||||
|
|
||||||
|
const { api } = await import(/* webpackChunkName: "dicom-microscopy-viewer" */ 'dicom-microscopy-viewer');
|
||||||
|
const microscopyViewer = api.VLWholeSlideMicroscopyImageViewer;
|
||||||
|
|
||||||
this.viewer = new microscopyViewer({
|
this.viewer = new microscopyViewer({
|
||||||
client: dicomWebClient,
|
client: dicomWebClient,
|
||||||
metadata,
|
metadata,
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* We use this component to leverage "Code Splitting"
|
||||||
|
*
|
||||||
|
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export default function asyncComponent(importComponent) {
|
||||||
|
class AsyncComponent extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
component: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
// Add dynamically loaded component to state
|
||||||
|
const { default: component } = await importComponent();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
component: component,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const C = this.state.component;
|
||||||
|
|
||||||
|
// Render the loaded component, or null
|
||||||
|
return C ? <C {...this.props} /> : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AsyncComponent;
|
||||||
|
}
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
|
import asyncComponent from './asyncComponent.js';
|
||||||
import DicomMicroscopySopClassHandler from './DicomMicroscopySopClassHandler.js';
|
import DicomMicroscopySopClassHandler from './DicomMicroscopySopClassHandler.js';
|
||||||
import DicomMicroscopyViewport from './DicomMicroscopyViewport.js';
|
|
||||||
|
const DicomMicroscopyViewport = asyncComponent(() =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "DicomMicroscopyViewport" */ './DicomMicroscopyViewport.js'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ module.exports = (env, argv) => {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: ROOT_DIR,
|
path: ROOT_DIR,
|
||||||
library: 'ohifExtensionDicomPdf',
|
library: 'OHIFExtDicomPdf',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
|
libraryExport: 'default',
|
||||||
filename: pkg.main,
|
filename: pkg.main,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,33 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.0.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.50.4...@ohif/extension-dicom-pdf@1.0.0) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Add DicomLoaderService & FileLoaderService to fix SR, PDF, and SEG support in local file and WADO-RS-only use cases ([#862](https://github.com/OHIF/Viewers/issues/862)) ([e7e1a8a](https://github.com/OHIF/Viewers/commit/e7e1a8a)), closes [#838](https://github.com/OHIF/Viewers/issues/838)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* DICOM Seg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.50.3...@ohif/extension-dicom-pdf@0.50.4) (2019-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* simplify runtime-extension usage ([ac5dbda](https://github.com/OHIF/Viewers/commit/ac5dbda))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.50.2...@ohif/extension-dicom-pdf@0.50.3) (2019-09-04)
|
## [0.50.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-pdf@0.50.2...@ohif/extension-dicom-pdf@0.50.3) (2019-09-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
**Note:** Version bump only for package @ohif/extension-dicom-pdf
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-dicom-pdf",
|
"name": "@ohif/extension-dicom-pdf",
|
||||||
"version": "0.50.3",
|
"version": "1.0.0",
|
||||||
"description": "OHIF extension for Dicom PDF",
|
"description": "OHIF extension for Dicom PDF",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
"@ohif/core": "^0.50.0",
|
"@ohif/core": "^0.50.0",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^15.0.0 || ^16.0.0",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^15.0.0 || ^16.0.0"
|
"react-dom": "^16.8.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
|
|||||||
@@ -4,41 +4,46 @@ import TypedArrayProp from './TypedArrayProp';
|
|||||||
|
|
||||||
// TODO: Should probably use dcmjs for this
|
// TODO: Should probably use dcmjs for this
|
||||||
const SOP_CLASS_UIDS = {
|
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',
|
||||||
};
|
};
|
||||||
|
|
||||||
class DicomPDFViewport extends Component {
|
class DicomPDFViewport extends Component {
|
||||||
state = {
|
state = {
|
||||||
fileURL: null,
|
fileURL: null,
|
||||||
error: null
|
error: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
byteArray: TypedArrayProp.uint8
|
byteArray: TypedArrayProp.uint8,
|
||||||
};
|
};
|
||||||
|
|
||||||
renderPDF = dataSet => {
|
renderPDF = (dataSet, byteArray) => {
|
||||||
const sopClassUid = dataSet.string('x00080016');
|
let pdfByteArray = byteArray;
|
||||||
|
|
||||||
if (sopClassUid !== SOP_CLASS_UIDS.ENCAPSULATED_PDF) {
|
if (dataSet) {
|
||||||
throw new Error('This is not a DICOM-encapsulated PDF');
|
const sopClassUid = dataSet.string('x00080016');
|
||||||
|
|
||||||
|
if (sopClassUid !== SOP_CLASS_UIDS.ENCAPSULATED_PDF) {
|
||||||
|
throw new Error('This is not a DICOM-encapsulated PDF');
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileTag = dataSet.elements.x00420011;
|
||||||
|
const offset = fileTag.dataOffset;
|
||||||
|
const remainder = offset + fileTag.length;
|
||||||
|
pdfByteArray = dataSet.byteArray.slice(offset, remainder);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileTag = dataSet.elements.x00420011;
|
|
||||||
const offset = fileTag.dataOffset;
|
|
||||||
const remainder = offset + fileTag.length;
|
|
||||||
const pdfByteArray = dataSet.byteArray.slice(offset, remainder);
|
|
||||||
const PDF = new Blob([pdfByteArray], { type: 'application/pdf' });
|
const PDF = new Blob([pdfByteArray], { type: 'application/pdf' });
|
||||||
const fileURL = URL.createObjectURL(PDF);
|
const fileURL = URL.createObjectURL(PDF);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
fileURL
|
fileURL,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
parseByteArray = byteArray => {
|
parseByteArray = byteArray => {
|
||||||
const options = {
|
const options = {
|
||||||
untilTag: ''
|
untilTag: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
let dataSet;
|
let dataSet;
|
||||||
@@ -47,7 +52,7 @@ class DicomPDFViewport extends Component {
|
|||||||
dataSet = dicomParser.parseDicom(byteArray, options);
|
dataSet = dicomParser.parseDicom(byteArray, options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.setState({
|
this.setState({
|
||||||
error
|
error,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +62,7 @@ class DicomPDFViewport extends Component {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const dataSet = this.parseByteArray(this.props.byteArray);
|
const dataSet = this.parseByteArray(this.props.byteArray);
|
||||||
|
|
||||||
this.renderPDF(dataSet);
|
this.renderPDF(dataSet, this.props.byteArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -1,60 +1,54 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from 'react';
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from 'prop-types';
|
||||||
import OHIF from "@ohif/core";
|
import OHIF from '@ohif/core';
|
||||||
import OHIFComponentPlugin from "./OHIFComponentPlugin.js";
|
import OHIFComponentPlugin from './OHIFComponentPlugin.js';
|
||||||
import DicomPDFViewport from "./DicomPDFViewport";
|
import DicomPDFViewport from './DicomPDFViewport';
|
||||||
|
|
||||||
const { DICOMWeb } = OHIF;
|
const { DicomLoaderService } = OHIF.utils;
|
||||||
|
|
||||||
class OHIFDicomPDFViewport extends Component {
|
class OHIFDicomPDFViewport extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
studies: PropTypes.object,
|
studies: PropTypes.object,
|
||||||
displaySet: PropTypes.object,
|
displaySet: PropTypes.object,
|
||||||
viewportIndex: PropTypes.number
|
viewportIndex: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
byteArray: null,
|
byteArray: null,
|
||||||
error: null
|
error: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
static id = "DicomPDFViewportPDF";
|
static id = 'DicomPDFViewportPDF';
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
console.log("DicomPDFViewport init()");
|
console.log('DicomPDFViewport init()');
|
||||||
}
|
}
|
||||||
|
|
||||||
static destroy() {
|
static destroy() {
|
||||||
console.log("DicomPDFViewport destroy()");
|
console.log('DicomPDFViewport destroy()');
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { displaySet } = this.props.viewportData;
|
const { displaySet, studies } = this.props.viewportData;
|
||||||
const {
|
const {
|
||||||
studyInstanceUid,
|
studyInstanceUid,
|
||||||
seriesInstanceUid,
|
seriesInstanceUid,
|
||||||
sopInstanceUid,
|
sopInstanceUid,
|
||||||
wadoRoot,
|
wadoRoot,
|
||||||
wadoUri,
|
wadoUri,
|
||||||
authorizationHeaders
|
authorizationHeaders,
|
||||||
} = displaySet;
|
} = displaySet;
|
||||||
|
|
||||||
this.retrieveDicomData(
|
DicomLoaderService.findDicomDataPromise(displaySet, studies).then(
|
||||||
studyInstanceUid,
|
data => {
|
||||||
seriesInstanceUid,
|
const byteArray = new Uint8Array(data);
|
||||||
sopInstanceUid,
|
|
||||||
wadoRoot,
|
|
||||||
wadoUri,
|
|
||||||
authorizationHeaders
|
|
||||||
).then(
|
|
||||||
byteArray => {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
byteArray
|
byteArray: byteArray,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.setState({
|
this.setState({
|
||||||
error
|
error,
|
||||||
});
|
});
|
||||||
|
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
@@ -62,27 +56,6 @@ class OHIFDicomPDFViewport extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
retrieveDicomData(
|
|
||||||
studyInstanceUid,
|
|
||||||
seriesInstanceUid,
|
|
||||||
sopInstanceUid,
|
|
||||||
wadoRoot,
|
|
||||||
wadoUri,
|
|
||||||
authorizationHeaders
|
|
||||||
) {
|
|
||||||
// TODO: Passing in a lot of data we aren't using
|
|
||||||
|
|
||||||
// TODO: Authorization header depends on the server. If we ever have multiple servers
|
|
||||||
// we will need to figure out how / when to pass this information in.
|
|
||||||
return fetch(wadoUri, {
|
|
||||||
headers: authorizationHeaders
|
|
||||||
})
|
|
||||||
.then(response => response.arrayBuffer())
|
|
||||||
.then(arraybuffer => {
|
|
||||||
return new Uint8Array(arraybuffer);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { id, init, destroy } = OHIFDicomPDFViewport;
|
const { id, init, destroy } = OHIFDicomPDFViewport;
|
||||||
const pluginProps = { id, init, destroy };
|
const pluginProps = { id, init, destroy };
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||||
@@ -29,9 +30,15 @@ module.exports = (env, argv) => {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: ROOT_DIR,
|
path: ROOT_DIR,
|
||||||
library: 'ohifExtensionVtk',
|
library: 'OHIFExtVtk',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
|
libraryExport: 'default',
|
||||||
filename: pkg.main,
|
filename: pkg.main,
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({
|
||||||
|
maxChunks: 1,
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,161 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [0.51.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.23...@ohif/extension-vtk@0.51.0) (2019-10-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 MPR UI improvements. Added MinIP, AvgIP, slab thickness slider and mode toggle ([#947](https://github.com/OHIF/Viewers/issues/947)) ([c79c0c3](https://github.com/OHIF/Viewers/commit/c79c0c3))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.23](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.22...@ohif/extension-vtk@0.50.23) (2019-10-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.22](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.21...@ohif/extension-vtk@0.50.22) (2019-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.21](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.20...@ohif/extension-vtk@0.50.21) (2019-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.20](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.19...@ohif/extension-vtk@0.50.20) (2019-09-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.19](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.18...@ohif/extension-vtk@0.50.19) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Add some code splitting for PWA build ([#937](https://github.com/OHIF/Viewers/issues/937)) ([8938035](https://github.com/OHIF/Viewers/commit/8938035))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.18](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.17...@ohif/extension-vtk@0.50.18) (2019-09-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.17](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.16...@ohif/extension-vtk@0.50.17) (2019-09-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.16](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.15...@ohif/extension-vtk@0.50.16) (2019-09-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Set transfer function range to data range when loading volumes in VTK ([#930](https://github.com/OHIF/Viewers/issues/930)) ([2341b32](https://github.com/OHIF/Viewers/commit/2341b32))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.15](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.14...@ohif/extension-vtk@0.50.15) (2019-09-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Bump VTK viewport dependency ([#929](https://github.com/OHIF/Viewers/issues/929)) ([66a0aad](https://github.com/OHIF/Viewers/commit/66a0aad))
|
||||||
|
* Stop adding empty labelmap to VTK Viewports for now. Wait until paint tools are implemented ([#926](https://github.com/OHIF/Viewers/issues/926)) ([7f642a0](https://github.com/OHIF/Viewers/commit/7f642a0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.14](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.13...@ohif/extension-vtk@0.50.14) (2019-09-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* bump cornerstone-tools version in peerDeps ([4afc88c](https://github.com/OHIF/Viewers/commit/4afc88c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.13](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.12...@ohif/extension-vtk@0.50.13) (2019-09-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.12](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.11...@ohif/extension-vtk@0.50.12) (2019-09-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.11](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.10...@ohif/extension-vtk@0.50.11) (2019-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* simplify runtime-extension usage ([ac5dbda](https://github.com/OHIF/Viewers/commit/ac5dbda))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.9...@ohif/extension-vtk@0.50.10) (2019-09-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.8...@ohif/extension-vtk@0.50.9) (2019-09-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.7...@ohif/extension-vtk@0.50.8) (2019-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.6...@ohif/extension-vtk@0.50.7) (2019-09-06)
|
## [0.50.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@0.50.6...@ohif/extension-vtk@0.50.7) (2019-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/extension-vtk
|
**Note:** Version bump only for package @ohif/extension-vtk
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/extension-vtk",
|
"name": "@ohif/extension-vtk",
|
||||||
"version": "0.50.7",
|
"version": "0.51.0",
|
||||||
"description": "OHIF extension for VTK.js",
|
"description": "OHIF extension for VTK.js",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"@ohif/ui": "^0.50.0",
|
"@ohif/ui": "^0.50.0",
|
||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-wado-image-loader": "^3.0.0",
|
"cornerstone-wado-image-loader": "^3.0.0",
|
||||||
"dcmjs": "^0.4.7",
|
"dcmjs": "^0.6.1",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
"i18next-browser-languagedetector": "^3.0.1",
|
"i18next-browser-languagedetector": "^3.0.1",
|
||||||
@@ -48,14 +48,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"react-vtkjs-viewport": "0.0.11"
|
"react-vtkjs-viewport": "0.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ohif/core": "^0.50.5",
|
"@ohif/core": "^1.0.1",
|
||||||
"@ohif/ui": "^0.50.4",
|
"@ohif/ui": "^0.52.0",
|
||||||
"cornerstone-tools": "^3.13.0",
|
"cornerstone-tools": "^4.0.9",
|
||||||
"cornerstone-wado-image-loader": "^3.0.0",
|
"cornerstone-wado-image-loader": "^3.0.0",
|
||||||
"dcmjs": "^0.5.1",
|
"dcmjs": "^0.6.1",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"gh-pages": "^2.0.1",
|
"gh-pages": "^2.0.1",
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
|
|||||||
@@ -189,6 +189,11 @@ class OHIFVTKViewport extends Component {
|
|||||||
volumeActor.setMapper(volumeMapper);
|
volumeActor.setMapper(volumeMapper);
|
||||||
volumeMapper.setInputData(data);
|
volumeMapper.setInputData(data);
|
||||||
|
|
||||||
|
const range = data.getPointData().getScalars().getRange();
|
||||||
|
|
||||||
|
// TODO: For PET we might want to just set this to 0-5 SUV
|
||||||
|
volumeActor.getProperty().getRGBTransferFunction(0).setRange(range[0], range[1]);
|
||||||
|
|
||||||
// TODO: Should look into implementing autoAdjustSampleDistance in vtk
|
// TODO: Should look into implementing autoAdjustSampleDistance in vtk
|
||||||
const sampleDistance =
|
const sampleDistance =
|
||||||
1.2 *
|
1.2 *
|
||||||
@@ -233,9 +238,11 @@ class OHIFVTKViewport extends Component {
|
|||||||
frameIndex
|
frameIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!labelmap) {
|
// TODO: Temporarily disabling this since it is not yet
|
||||||
|
// being used and hurts performance significantly.
|
||||||
|
/*if (!labelmap) {
|
||||||
labelmap = createLabelMapImageData(data);
|
labelmap = createLabelMapImageData(data);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
const volumeActor = this.getOrCreateVolume(data, displaySetInstanceUid);
|
const volumeActor = this.getOrCreateVolume(data, displaySetInstanceUid);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* We use this component to leverage "Code Splitting"
|
||||||
|
*
|
||||||
|
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export default function asyncComponent(importComponent) {
|
||||||
|
class AsyncComponent extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
component: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
// Add dynamically loaded component to state
|
||||||
|
const { default: component } = await importComponent();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
component: component,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const C = this.state.component;
|
||||||
|
|
||||||
|
// Render the loaded component, or null
|
||||||
|
return C ? <C {...this.props} /> : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AsyncComponent;
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ const { BlendMode } = Constants;
|
|||||||
// TODO: Put this somewhere else
|
// TODO: Put this somewhere else
|
||||||
let apis = {};
|
let apis = {};
|
||||||
let currentSlabThickness = 0.1;
|
let currentSlabThickness = 0.1;
|
||||||
|
let defaultSlabThickness = 0.1;
|
||||||
|
|
||||||
function getCrosshairCallbackForIndex(index) {
|
function getCrosshairCallbackForIndex(index) {
|
||||||
return ({ worldPos }) => {
|
return ({ worldPos }) => {
|
||||||
@@ -117,6 +118,7 @@ function switchMPRInteractors(api, istyle) {
|
|||||||
let currentSlabThickness;
|
let currentSlabThickness;
|
||||||
if (currentIStyle.getSlabThickness && istyle.getSlabThickness) {
|
if (currentIStyle.getSlabThickness && istyle.getSlabThickness) {
|
||||||
currentSlabThickness = currentIStyle.getSlabThickness();
|
currentSlabThickness = currentIStyle.getSlabThickness();
|
||||||
|
defaultSlabThickness = currentSlabThickness;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderWindow.getInteractor().setInteractorStyle(istyle);
|
renderWindow.getInteractor().setInteractorStyle(istyle);
|
||||||
@@ -182,7 +184,7 @@ const actions = {
|
|||||||
switchMPRInteractors(api, istyle);
|
switchMPRInteractors(api, istyle);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
setSlabThickness: slabThickness => {
|
setSlabThickness: ({ slabThickness }) => {
|
||||||
currentSlabThickness = slabThickness;
|
currentSlabThickness = slabThickness;
|
||||||
|
|
||||||
apis.forEach(api => {
|
apis.forEach(api => {
|
||||||
@@ -191,15 +193,6 @@ const actions = {
|
|||||||
|
|
||||||
if (istyle.setSlabThickness) {
|
if (istyle.setSlabThickness) {
|
||||||
istyle.setSlabThickness(currentSlabThickness);
|
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();
|
renderWindow.render();
|
||||||
@@ -220,6 +213,32 @@ const actions = {
|
|||||||
renderWindow.render();
|
renderWindow.render();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
setBlendModeToComposite: () => {
|
||||||
|
apis.forEach(api => {
|
||||||
|
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||||
|
const istyle = renderWindow.getInteractor().getInteractorStyle();
|
||||||
|
|
||||||
|
const mapper = api.volumes[0].getMapper();
|
||||||
|
if (mapper.setBlendModeToComposite) {
|
||||||
|
mapper.setBlendModeToComposite();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (istyle.setSlabThickness) {
|
||||||
|
istyle.setSlabThickness(defaultSlabThickness);
|
||||||
|
}
|
||||||
|
renderWindow.render();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setBlendModeToMaximumIntensity: () => {
|
||||||
|
apis.forEach(api => {
|
||||||
|
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||||
|
const mapper = api.volumes[0].getMapper();
|
||||||
|
if (mapper.setBlendModeToMaximumIntensity) {
|
||||||
|
mapper.setBlendModeToMaximumIntensity();
|
||||||
|
}
|
||||||
|
renderWindow.render();
|
||||||
|
});
|
||||||
|
},
|
||||||
setBlendMode: ({ blendMode }) => {
|
setBlendMode: ({ blendMode }) => {
|
||||||
apis.forEach(api => {
|
apis.forEach(api => {
|
||||||
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
const renderWindow = api.genericRenderWindow.getRenderWindow();
|
||||||
@@ -338,12 +357,12 @@ const definitions = {
|
|||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
setBlendModeToComposite: {
|
setBlendModeToComposite: {
|
||||||
commandFn: actions.setBlendMode,
|
commandFn: actions.setBlendModeToComposite,
|
||||||
storeContexts: [],
|
storeContexts: [],
|
||||||
options: { blendMode: BlendMode.COMPOSITE_BLEND },
|
options: { blendMode: BlendMode.COMPOSITE_BLEND },
|
||||||
},
|
},
|
||||||
setBlendModeToMaximumIntensity: {
|
setBlendModeToMaximumIntensity: {
|
||||||
commandFn: actions.setBlendMode,
|
commandFn: actions.setBlendModeToMaximumIntensity,
|
||||||
storeContexts: [],
|
storeContexts: [],
|
||||||
options: { blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND },
|
options: { blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import OHIFVTKViewport from './OHIFVTKViewport.js';
|
import asyncComponent from './asyncComponent.js';
|
||||||
import commandsModule from './commandsModule.js';
|
import commandsModule from './commandsModule.js';
|
||||||
import toolbarModule from './toolbarModule.js';
|
import toolbarModule from './toolbarModule.js';
|
||||||
// This feels weird
|
// This feels weird
|
||||||
// import loadLocales from './loadLocales';
|
// import loadLocales from './loadLocales';
|
||||||
|
|
||||||
|
const OHIFVTKViewport = asyncComponent(() =>
|
||||||
|
import(/* webpackChunkName: "OHIFVTKViewport" */ './OHIFVTKViewport.js')
|
||||||
|
);
|
||||||
|
|
||||||
const vtkExtension = {
|
const vtkExtension = {
|
||||||
/**
|
/**
|
||||||
* Only required property. Should be a unique value across all extensions.
|
* Only required property. Should be a unique value across all extensions.
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import { Range, Checkbox, Select } from '@ohif/ui';
|
||||||
|
|
||||||
|
import './slab-thickness-toolbar-button.styl';
|
||||||
|
|
||||||
|
const SLIDER = {
|
||||||
|
MIN: 0.1,
|
||||||
|
MAX: 1000,
|
||||||
|
STEP: 0.1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ToolbarLabel = props => {
|
||||||
|
const { label } = props;
|
||||||
|
return <div className="toolbar-button-label">{label}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ToolbarSlider = props => {
|
||||||
|
const { value, min, max, onChange } = props;
|
||||||
|
return (
|
||||||
|
<div className="toolbar-slider-container">
|
||||||
|
<label htmlFor="toolbar-slider">{value}mm</label>
|
||||||
|
<Range
|
||||||
|
value={value}
|
||||||
|
min={min}
|
||||||
|
max={max}
|
||||||
|
step={SLIDER.STEP}
|
||||||
|
onChange={onChange}
|
||||||
|
id="toolbar-slider"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _getSelectOptions = button => {
|
||||||
|
return button.operationButtons.map(button => {
|
||||||
|
return {
|
||||||
|
key: button.label,
|
||||||
|
value: button.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const _getClassNames = (isActive, className) => {
|
||||||
|
return classnames('toolbar-button', 'slab-thickness', className, {
|
||||||
|
active: isActive,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const _applySlabThickness = (
|
||||||
|
value,
|
||||||
|
modeChecked,
|
||||||
|
toolbarClickCallback,
|
||||||
|
button
|
||||||
|
) => {
|
||||||
|
if (!modeChecked || !toolbarClickCallback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { actionButton } = button;
|
||||||
|
|
||||||
|
const generateOperation = (operation, value) => {
|
||||||
|
// Combine slider value into slider operation
|
||||||
|
const generatedOperation = { ...operation };
|
||||||
|
generatedOperation.commandOptions = {
|
||||||
|
...operation.commandOptions,
|
||||||
|
slabThickness: value,
|
||||||
|
};
|
||||||
|
|
||||||
|
return generatedOperation;
|
||||||
|
};
|
||||||
|
|
||||||
|
const operation = generateOperation(actionButton, value);
|
||||||
|
toolbarClickCallback(operation, event);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _applyModeOperation = (
|
||||||
|
operation,
|
||||||
|
modeChecked,
|
||||||
|
toolbarClickCallback,
|
||||||
|
button
|
||||||
|
) => {
|
||||||
|
// in case modeChecked has not being triggered by user yet
|
||||||
|
if (typeof modeChecked !== 'boolean') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { deactivateButton } = button;
|
||||||
|
|
||||||
|
const _operation = modeChecked ? operation : deactivateButton;
|
||||||
|
if (toolbarClickCallback && _operation) {
|
||||||
|
toolbarClickCallback(_operation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _getInitialState = currentSelectedOption => {
|
||||||
|
return {
|
||||||
|
value: SLIDER.MIN,
|
||||||
|
sliderMin: SLIDER.MIN,
|
||||||
|
sliderMax: SLIDER.MAX,
|
||||||
|
modeChecked: undefined,
|
||||||
|
operation: currentSelectedOption,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const INITIAL_OPTION_INDEX = 0;
|
||||||
|
const _getInitialtSelectedOption = (button = {}) => {
|
||||||
|
return (
|
||||||
|
button.operationButtons && button.operationButtons[INITIAL_OPTION_INDEX]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function SlabThicknessToolbarComponent({
|
||||||
|
parentContext,
|
||||||
|
toolbarClickCallback,
|
||||||
|
button,
|
||||||
|
activeButtons,
|
||||||
|
isActive,
|
||||||
|
className,
|
||||||
|
}) {
|
||||||
|
const currentSelectedOption = _getInitialtSelectedOption(button);
|
||||||
|
const [state, setState] = useState(_getInitialState(currentSelectedOption));
|
||||||
|
const { label, operationButtons } = button;
|
||||||
|
const _className = _getClassNames(isActive, className);
|
||||||
|
const selectOptions = _getSelectOptions(button);
|
||||||
|
function onChangeSelect(selectedValue) {
|
||||||
|
// find select value
|
||||||
|
const operation = operationButtons.find(
|
||||||
|
button => button.id === selectedValue
|
||||||
|
);
|
||||||
|
|
||||||
|
if (operation === state.operation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState({ ...state, operation });
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChangeCheckbox(checked) {
|
||||||
|
setState({ ...state, modeChecked: checked });
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChangeSlider(event) {
|
||||||
|
const value = Number(event.target.value);
|
||||||
|
|
||||||
|
if (value !== state.value) {
|
||||||
|
setState({ ...state, value, modeChecked: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
_applyModeOperation(
|
||||||
|
state.operation,
|
||||||
|
state.modeChecked,
|
||||||
|
toolbarClickCallback,
|
||||||
|
button
|
||||||
|
);
|
||||||
|
}, [state.modeChecked, state.operation]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
_applySlabThickness(
|
||||||
|
state.value,
|
||||||
|
state.modeChecked,
|
||||||
|
toolbarClickCallback,
|
||||||
|
button
|
||||||
|
);
|
||||||
|
}, [state.operation, state.modeChecked, state.value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={_className}>
|
||||||
|
<div className="container">
|
||||||
|
<ToolbarSlider
|
||||||
|
value={state.value}
|
||||||
|
min={state.sliderMin}
|
||||||
|
max={state.sliderMax}
|
||||||
|
onChange={onChangeSlider}
|
||||||
|
/>
|
||||||
|
<ToolbarLabel key="toolbar-label" label={label} />
|
||||||
|
</div>
|
||||||
|
<div className="controller">
|
||||||
|
<Checkbox
|
||||||
|
label="mode"
|
||||||
|
checked={state.modeChecked}
|
||||||
|
onChange={onChangeCheckbox}
|
||||||
|
></Checkbox>
|
||||||
|
<Select
|
||||||
|
key="toolbar-select"
|
||||||
|
options={selectOptions}
|
||||||
|
value={selectOptions[INITIAL_OPTION_INDEX].value}
|
||||||
|
onChange={onChangeSelect}
|
||||||
|
></Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SlabThicknessToolbarComponent.propTypes = {
|
||||||
|
parentContext: PropTypes.object.isRequired,
|
||||||
|
toolbarClickCallback: PropTypes.func.isRequired,
|
||||||
|
button: PropTypes.object.isRequired,
|
||||||
|
activeButtons: PropTypes.array.isRequired,
|
||||||
|
isActive: PropTypes.bool,
|
||||||
|
className: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SlabThicknessToolbarComponent;
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
.slab-thickness
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-end;
|
||||||
|
height: 60px;
|
||||||
|
margin-top: -12px;
|
||||||
|
&:hover
|
||||||
|
color: var(--default-color);
|
||||||
|
.container
|
||||||
|
padding-right: 10px;
|
||||||
|
height: inherit;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
.toolbar-slider-container
|
||||||
|
width: 80px;
|
||||||
|
margin: 0px 2px 2px 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
&:hover
|
||||||
|
color: var(--hover-color);
|
||||||
|
input
|
||||||
|
height: 20px;
|
||||||
|
padding-top: 6px;
|
||||||
|
&::-moz-range-thumb
|
||||||
|
height: 16px;
|
||||||
|
margin-top: -7px;
|
||||||
|
&::-webkit-slider-thumb
|
||||||
|
height: 16px;
|
||||||
|
margin-top: -7px;
|
||||||
|
.controller
|
||||||
|
width: 62px;
|
||||||
|
.ohif-check-container
|
||||||
|
margin-bottom: 5px;
|
||||||
|
padding-left: 18px;
|
||||||
|
.ohif-check-label
|
||||||
|
text-transform: capitalize;
|
||||||
|
&:hover
|
||||||
|
color: var(--hover-color);
|
||||||
|
.ohif-checkbox
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: white;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
top: 22%;
|
||||||
|
&.ohif-checked:after
|
||||||
|
background-color: var(--active-color);
|
||||||
|
top: 17%;
|
||||||
|
left: 17%;
|
||||||
|
.select-ohif
|
||||||
|
color: var(--default-color);
|
||||||
|
border-color: var(--default-color);
|
||||||
|
background-color: black;
|
||||||
|
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
|
||||||
|
&:hover
|
||||||
|
color: var(--hover-color);
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import SlabThicknessToolbarComponent from './toolbarComponents/SlabThicknessToolbarComponent';
|
||||||
|
|
||||||
const TOOLBAR_BUTTON_TYPES = {
|
const TOOLBAR_BUTTON_TYPES = {
|
||||||
COMMAND: 'command',
|
COMMAND: 'command',
|
||||||
SET_TOOL_ACTIVE: 'setToolActive',
|
SET_TOOL_ACTIVE: 'setToolActive',
|
||||||
@@ -31,6 +33,7 @@ const definitions = [
|
|||||||
commandName: 'enableRotateTool',
|
commandName: 'enableRotateTool',
|
||||||
commandOptions: {},
|
commandOptions: {},
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
id: 'setBlendModeToComposite',
|
id: 'setBlendModeToComposite',
|
||||||
label: 'Disable MIP',
|
label: 'Disable MIP',
|
||||||
@@ -68,6 +71,50 @@ const definitions = [
|
|||||||
commandName: 'decreaseSlabThickness',
|
commandName: 'decreaseSlabThickness',
|
||||||
commandOptions: {},
|
commandOptions: {},
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
id: 'changeSlabThickness',
|
||||||
|
label: 'Slab Thickness',
|
||||||
|
icon: 'soft-tissue',
|
||||||
|
CustomComponent: SlabThicknessToolbarComponent,
|
||||||
|
commandName: 'setSlabThickness',
|
||||||
|
actionButton: {
|
||||||
|
id: 'setSlabThickness',
|
||||||
|
label: 'slider',
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||||
|
commandName: 'setSlabThickness',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
deactivateButton: {
|
||||||
|
id: 'setBlendModeToComposite',
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||||
|
commandName: 'setBlendModeToComposite',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
operationButtons: [
|
||||||
|
{
|
||||||
|
id: 'setBlendModeToMaximumIntensity',
|
||||||
|
label: 'MIP',
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||||
|
commandName: 'setBlendModeToMaximumIntensity',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'setBlendModeToMinimumIntensity',
|
||||||
|
label: 'MinIP',
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||||
|
commandName: 'setBlendModeToMinimumIntensity',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'setBlendModeToAverageIntensity',
|
||||||
|
label: 'AvgIP',
|
||||||
|
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||||
|
commandName: 'setBlendModeToAverageIntensity',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
+1
-20
@@ -3,7 +3,7 @@
|
|||||||
# TOML Reference:
|
# TOML Reference:
|
||||||
# https://www.netlify.com/docs/netlify-toml-reference/
|
# https://www.netlify.com/docs/netlify-toml-reference/
|
||||||
#
|
#
|
||||||
# We use Netlify for deploy previews and deploy previews only.
|
# We use Netlify for deploy previews and for publishing docs (gh-pages branch).
|
||||||
# https://viewer.ohif.org is created using a different process that is
|
# https://viewer.ohif.org is created using a different process that is
|
||||||
# managed by CircleCI and deployed to our Google Hosting
|
# managed by CircleCI and deployed to our Google Hosting
|
||||||
#
|
#
|
||||||
@@ -40,25 +40,6 @@
|
|||||||
publish = ".netlify/www/"
|
publish = ".netlify/www/"
|
||||||
command = "yarn config set workspaces-experimental true && chmod +x .netlify/build-deploy-preview.sh && .netlify/build-deploy-preview.sh"
|
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
|
|
||||||
# contexts no matter where you define them in the file.
|
|
||||||
# For context-specific rules, use _headers or _redirects files, which are
|
|
||||||
# PER-DEPLOY.
|
|
||||||
# The following redirect is intended for use with most SPAs that handle
|
|
||||||
# routing internally.
|
|
||||||
# By default, redirects won't be applied if there's a file with the same
|
|
||||||
# path as the one defined in the `from` property. Setting `force` to `true`
|
|
||||||
# will make the redirect rule take precedence over any existing files.
|
|
||||||
[[redirects]]
|
|
||||||
from = "/*"
|
|
||||||
to = "/index.html"
|
|
||||||
status = 200
|
|
||||||
|
|
||||||
[[redirects]]
|
|
||||||
from = "/pwa/*"
|
|
||||||
to = "/pwa/index.html"
|
|
||||||
status = 200
|
|
||||||
|
|
||||||
[[headers]]
|
[[headers]]
|
||||||
# Define which paths this specific [[headers]] block will cover.
|
# Define which paths this specific [[headers]] block will cover.
|
||||||
for = "/*"
|
for = "/*"
|
||||||
|
|||||||
+20
-2
@@ -13,6 +13,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"cm": "npx git-cz",
|
"cm": "npx git-cz",
|
||||||
"build": "lerna run build:viewer --stream",
|
"build": "lerna run build:viewer --stream",
|
||||||
|
"build:e2e": "lerna run build:viewer:e2e --stream",
|
||||||
"build:ci": "lerna run build:viewer:ci --stream",
|
"build:ci": "lerna run build:viewer:ci --stream",
|
||||||
"build:demo": "lerna run build:viewer:demo --stream",
|
"build:demo": "lerna run build:viewer:demo --stream",
|
||||||
"build:package": "lerna run build:viewer:package --stream",
|
"build:package": "lerna run build:viewer:package --stream",
|
||||||
@@ -21,14 +22,18 @@
|
|||||||
"dev:project": ".scripts/dev.sh",
|
"dev:project": ".scripts/dev.sh",
|
||||||
"dev:orthanc": "lerna run dev:orthanc --stream",
|
"dev:orthanc": "lerna run dev:orthanc --stream",
|
||||||
"orthanc:up": "docker-compose -f .docker/Nginx-Orthanc/docker-compose.yml up",
|
"orthanc:up": "docker-compose -f .docker/Nginx-Orthanc/docker-compose.yml up",
|
||||||
|
"start": "yarn run dev",
|
||||||
"test": "yarn run test:unit",
|
"test": "yarn run test:unit",
|
||||||
"test:unit": "jest --collectCoverage",
|
"test:unit": "jest --collectCoverage",
|
||||||
"test:unit:ci": "lerna run test:unit:ci --parallel --stream",
|
"test:unit:ci": "lerna run test:unit:ci --parallel --stream",
|
||||||
|
"test:e2e": "lerna run test:e2e --stream",
|
||||||
|
"test:e2e:dist": "lerna run test:e2e:dist --stream",
|
||||||
"see-changed": "lerna changed",
|
"see-changed": "lerna changed",
|
||||||
"docs:publish": "chmod +x ./build-and-publish-docs.sh && ./build-and-publish-docs.sh",
|
"docs:publish": "chmod +x ./build-and-publish-docs.sh && ./build-and-publish-docs.sh",
|
||||||
"release": "yarn run lerna:version && yarn run lerna:publish",
|
"release": "yarn run lerna:version && yarn run lerna:publish",
|
||||||
"lerna:version": "npx lerna version prerelease --force-publish",
|
"lerna:version": "npx lerna version prerelease --force-publish",
|
||||||
"lerna:publish": "lerna publish from-package --canary --dist-tag canary"
|
"lerna:publish": "lerna publish from-package --canary --dist-tag canary",
|
||||||
|
"link-list": "npm ls --depth=0 --link=true"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
@@ -78,13 +83,15 @@
|
|||||||
"react-dom": "^16.8.6",
|
"react-dom": "^16.8.6",
|
||||||
"react-hot-loader": "^4.12.11",
|
"react-hot-loader": "^4.12.11",
|
||||||
"redux-testkit": "^1.0.6",
|
"redux-testkit": "^1.0.6",
|
||||||
|
"serve": "^11.1.0",
|
||||||
"shader-loader": "^1.3.1",
|
"shader-loader": "^1.3.1",
|
||||||
|
"start-server-and-test": "^1.10.0",
|
||||||
"style-loader": "^1.0.0",
|
"style-loader": "^1.0.0",
|
||||||
"stylelint": "^10.1.0",
|
"stylelint": "^10.1.0",
|
||||||
"stylelint-config-recommended": "^2.2.0",
|
"stylelint-config-recommended": "^2.2.0",
|
||||||
"stylus": "^0.54.5",
|
"stylus": "^0.54.5",
|
||||||
"stylus-loader": "^3.0.2",
|
"stylus-loader": "^3.0.2",
|
||||||
"terser-webpack-plugin": "^1.4.1",
|
"terser-webpack-plugin": "^2.1.0",
|
||||||
"webpack": "^4.35.2",
|
"webpack": "^4.35.2",
|
||||||
"webpack-cli": "^3.3.5",
|
"webpack-cli": "^3.3.5",
|
||||||
"webpack-dev-server": "^3.7.2",
|
"webpack-dev-server": "^3.7.2",
|
||||||
@@ -93,6 +100,17 @@
|
|||||||
"workbox-webpack-plugin": "^4.3.1",
|
"workbox-webpack-plugin": "^4.3.1",
|
||||||
"worker-loader": "^2.0.0"
|
"worker-loader": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"src/**/*.{js,json,css}": [
|
||||||
|
"prettier --write",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"**/@babel/runtime": "7.5.5"
|
"**/@babel/runtime": "7.5.5"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,82 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.0.1](https://github.com/OHIF/Viewers/compare/@ohif/core@1.0.0...@ohif/core@1.0.1) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Check for Value in 00081155 sequence (Few patient protocol images doesn't have this value) and removed a duplicate declaration ([#921](https://github.com/OHIF/Viewers/issues/921)) ([d0ec9cf](https://github.com/OHIF/Viewers/commit/d0ec9cf))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.0.0](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.10...@ohif/core@1.0.0) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Add DicomLoaderService & FileLoaderService to fix SR, PDF, and SEG support in local file and WADO-RS-only use cases ([#862](https://github.com/OHIF/Viewers/issues/862)) ([e7e1a8a](https://github.com/OHIF/Viewers/commit/e7e1a8a)), closes [#838](https://github.com/OHIF/Viewers/issues/838)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* DICOM Seg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.10](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.9...@ohif/core@0.50.10) (2019-09-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Avoid using variable name "module" ([#942](https://github.com/OHIF/Viewers/issues/942)) ([72427fe](https://github.com/OHIF/Viewers/commit/72427fe)), closes [#940](https://github.com/OHIF/Viewers/issues/940)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.9](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.8...@ohif/core@0.50.9) (2019-09-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* bump cornerstone-tools version in peerDeps ([4afc88c](https://github.com/OHIF/Viewers/commit/4afc88c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.8](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.7...@ohif/core@0.50.8) (2019-09-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.7](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.6...@ohif/core@0.50.7) (2019-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove requestOptions when key is not needed ([32bc47d](https://github.com/OHIF/Viewers/commit/32bc47d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.6](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.5...@ohif/core@0.50.6) (2019-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.5](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.4...@ohif/core@0.50.5) (2019-09-04)
|
## [0.50.5](https://github.com/OHIF/Viewers/compare/@ohif/core@0.50.4...@ohif/core@0.50.5) (2019-09-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/core
|
**Note:** Version bump only for package @ohif/core
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/core",
|
"name": "@ohif/core",
|
||||||
"version": "0.50.5",
|
"version": "1.0.1",
|
||||||
"description": "Generic business logic for web-based medical imaging applications",
|
"description": "Generic business logic for web-based medical imaging applications",
|
||||||
"author": "OHIF Core Team",
|
"author": "OHIF Core Team",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-tools": "^3.9.0",
|
"cornerstone-tools": "^4.0.9",
|
||||||
"cornerstone-wado-image-loader": "^3.0.0",
|
"cornerstone-wado-image-loader": "^3.0.0",
|
||||||
"dicom-parser": "^1.8.3"
|
"dicom-parser": "^1.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,17 +6,21 @@ import user from '../user';
|
|||||||
/**
|
/**
|
||||||
* Returns the Authorization header as part of an Object.
|
* Returns the Authorization header as part of an Object.
|
||||||
*
|
*
|
||||||
* @returns {Object}
|
* @export
|
||||||
|
* @param {Object} [server={}]
|
||||||
|
* @param {Object} [server.requestOptions]
|
||||||
|
* @param {string} [server.requestOptions.auth]
|
||||||
|
* @returns {Object} { Authorization }
|
||||||
*/
|
*/
|
||||||
export default function getAuthorizationHeader(server) {
|
export default function getAuthorizationHeader({ requestOptions } = {}) {
|
||||||
const headers = {};
|
const headers = {};
|
||||||
|
|
||||||
// Check for OHIF.user since this can also be run on the server
|
// Check for OHIF.user since this can also be run on the server
|
||||||
const accessToken = user && user.getAccessToken && user.getAccessToken();
|
const accessToken = user && user.getAccessToken && user.getAccessToken();
|
||||||
|
|
||||||
if (server && server.requestOptions && server.requestOptions.auth) {
|
if (requestOptions && requestOptions.auth) {
|
||||||
// HTTP Basic Auth (user:password)
|
// HTTP Basic Auth (user:password)
|
||||||
headers.Authorization = `Basic ${btoa(server.requestOptions.auth)}`;
|
headers.Authorization = `Basic ${btoa(requestOptions.auth)}`;
|
||||||
} else if (accessToken) {
|
} else if (accessToken) {
|
||||||
headers.Authorization = `Bearer ${accessToken}`;
|
headers.Authorization = `Bearer ${accessToken}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ export class StudyMetadata extends Metadata {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (displaySet) {
|
if (displaySet) {
|
||||||
|
displaySet.sopClassModule = true;
|
||||||
displaySets.push(displaySet);
|
displaySets.push(displaySet);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -214,7 +215,7 @@ export class StudyMetadata extends Metadata {
|
|||||||
* @returns {boolean} True on success, false on failure.
|
* @returns {boolean} True on success, false on failure.
|
||||||
*/
|
*/
|
||||||
addDisplaySet(displaySet) {
|
addDisplaySet(displaySet) {
|
||||||
if (displaySet instanceof ImageSet) {
|
if (displaySet instanceof ImageSet || displaySet.sopClassModule) {
|
||||||
this._displaySets.push(displaySet);
|
this._displaySets.push(displaySet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import RetrieveMetadata from './services/wado/retrieveMetadata.js';
|
import RetrieveMetadata from './services/wado/retrieveMetadata.js';
|
||||||
|
|
||||||
const module = 'RetrieveStudyMetadata';
|
const moduleName = 'RetrieveStudyMetadata';
|
||||||
// Cache for promises. Prevents unnecessary subsequent calls to the server
|
// Cache for promises. Prevents unnecessary subsequent calls to the server
|
||||||
const StudyMetaDataPromises = new Map();
|
const StudyMetaDataPromises = new Map();
|
||||||
|
|
||||||
@@ -17,11 +17,11 @@ export function retrieveStudyMetadata(server, studyInstanceUid) {
|
|||||||
// corresponding promise from the "StudyMetaDataPromises" map...
|
// corresponding promise from the "StudyMetaDataPromises" map...
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
throw new Error(`${module}: Required 'server' parameter not provided.`);
|
throw new Error(`${moduleName}: Required 'server' parameter not provided.`);
|
||||||
}
|
}
|
||||||
if (!studyInstanceUid) {
|
if (!studyInstanceUid) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`${module}: Required 'studyInstanceUid' parameter not provided.`
|
`${moduleName}: Required 'studyInstanceUid' parameter not provided.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,8 @@ function getSourceImageInstanceUid(instance) {
|
|||||||
if (
|
if (
|
||||||
SourceImageSequence &&
|
SourceImageSequence &&
|
||||||
SourceImageSequence.Value &&
|
SourceImageSequence.Value &&
|
||||||
SourceImageSequence.Value.length
|
SourceImageSequence.Value.length &&
|
||||||
|
SourceImageSequence.Value[0]['00081155'].Value
|
||||||
) {
|
) {
|
||||||
return SourceImageSequence.Value[0]['00081155'].Value[0];
|
return SourceImageSequence.Value[0]['00081155'].Value[0];
|
||||||
}
|
}
|
||||||
@@ -293,7 +294,6 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
|||||||
// TODO: Pass a reference ID to the server instead of including the URLs here
|
// TODO: Pass a reference ID to the server instead of including the URLs here
|
||||||
const studyData = {
|
const studyData = {
|
||||||
seriesList: [],
|
seriesList: [],
|
||||||
studyInstanceUid,
|
|
||||||
wadoUriRoot: server.wadoUriRoot,
|
wadoUriRoot: server.wadoUriRoot,
|
||||||
wadoRoot: server.wadoRoot,
|
wadoRoot: server.wadoRoot,
|
||||||
qidoRoot: server.qidoRoot,
|
qidoRoot: server.qidoRoot,
|
||||||
@@ -402,6 +402,7 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
|||||||
baseWadoRsUri: baseWadoRsUri,
|
baseWadoRsUri: baseWadoRsUri,
|
||||||
wadouri: WADOProxy.convertURL(wadouri, server),
|
wadouri: WADOProxy.convertURL(wadouri, server),
|
||||||
wadorsuri: WADOProxy.convertURL(wadorsuri, server),
|
wadorsuri: WADOProxy.convertURL(wadorsuri, server),
|
||||||
|
wadoRoot: server.wadoRoot,
|
||||||
imageRendering: server.imageRendering,
|
imageRendering: server.imageRendering,
|
||||||
thumbnailRendering: server.thumbnailRendering,
|
thumbnailRendering: server.thumbnailRendering,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ describe('addServers', () => {
|
|||||||
qidoSupportsIncludeField: true,
|
qidoSupportsIncludeField: true,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
oidc: [
|
oidc: [
|
||||||
@@ -52,7 +49,6 @@ describe('addServers', () => {
|
|||||||
name: 'DCM4CHEE',
|
name: 'DCM4CHEE',
|
||||||
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||||
qidoSupportsIncludeField: true,
|
qidoSupportsIncludeField: true,
|
||||||
requestOptions: { requestFromBrowser: true },
|
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
type: 'dicomWeb',
|
type: 'dicomWeb',
|
||||||
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||||
|
|||||||
@@ -0,0 +1,199 @@
|
|||||||
|
import cornerstone from 'cornerstone-core';
|
||||||
|
import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
|
||||||
|
import { api } from 'dicomweb-client';
|
||||||
|
import DICOMWeb from '../DICOMWeb';
|
||||||
|
|
||||||
|
const getImageId = imageObj => {
|
||||||
|
if (!imageObj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeof imageObj.getImageId === 'function'
|
||||||
|
? imageObj.getImageId()
|
||||||
|
: imageObj.url;
|
||||||
|
};
|
||||||
|
|
||||||
|
const findImageIdOnStudies = (studies, displaySetInstanceUid) => {
|
||||||
|
const study = studies.find(study => {
|
||||||
|
const displaySet = study.displaySets.some(
|
||||||
|
displaySet => displaySet.displaySetInstanceUid === displaySetInstanceUid
|
||||||
|
);
|
||||||
|
return displaySet;
|
||||||
|
});
|
||||||
|
const { seriesList = [] } = study;
|
||||||
|
const { instances = [] } = seriesList[0] || {};
|
||||||
|
const instance = instances[0];
|
||||||
|
|
||||||
|
return getImageId(instance);
|
||||||
|
};
|
||||||
|
|
||||||
|
const someInvalidStrings = strings => {
|
||||||
|
const stringsArray = Array.isArray(strings) ? strings : [strings];
|
||||||
|
const emptyString = string => !string;
|
||||||
|
let invalid = stringsArray.some(emptyString);
|
||||||
|
return invalid;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getImageInstance = dataset => {
|
||||||
|
return dataset && dataset.images && dataset.images[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getImageInstanceId = imageInstance => {
|
||||||
|
return getImageId(imageInstance);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchIt = (url, headers = DICOMWeb.getAuthorizationHeader()) => {
|
||||||
|
return fetch(url, headers).then(response => response.arrayBuffer());
|
||||||
|
};
|
||||||
|
|
||||||
|
const cornerstoneRetriever = imageId => {
|
||||||
|
return cornerstone.loadAndCacheImage(imageId).then(image => {
|
||||||
|
return image && image.data && image.data.byteArray.buffer;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const wadorsRetriever = (
|
||||||
|
url,
|
||||||
|
studyInstanceUID,
|
||||||
|
seriesInstanceUID,
|
||||||
|
sopInstanceUID,
|
||||||
|
headers = DICOMWeb.getAuthorizationHeader()
|
||||||
|
) => {
|
||||||
|
const config = {
|
||||||
|
url,
|
||||||
|
headers,
|
||||||
|
};
|
||||||
|
const dicomWeb = new api.DICOMwebClient(config);
|
||||||
|
|
||||||
|
return dicomWeb.retrieveInstance({
|
||||||
|
studyInstanceUID,
|
||||||
|
seriesInstanceUID,
|
||||||
|
sopInstanceUID,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getImageLoaderType = imageId => {
|
||||||
|
const loaderRegExp = /^\w+\:/;
|
||||||
|
const loaderType = loaderRegExp.exec(imageId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
(loaderRegExp.lastIndex === 0 &&
|
||||||
|
loaderType &&
|
||||||
|
loaderType[0] &&
|
||||||
|
loaderType[0].replace(':', '')) ||
|
||||||
|
''
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DicomLoaderService = new (class {
|
||||||
|
getLocalData(dataset, studies) {
|
||||||
|
if (dataset && dataset.localFile) {
|
||||||
|
// Use referenced imageInstance
|
||||||
|
const imageInstance = getImageInstance(dataset);
|
||||||
|
let imageId = getImageInstanceId(imageInstance);
|
||||||
|
|
||||||
|
// or Try to get it from studies
|
||||||
|
if (someInvalidStrings(imageId)) {
|
||||||
|
imageId = findImageIdOnStudies(studies, dataset.displaySetInstanceUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!someInvalidStrings(imageId)) {
|
||||||
|
return cornerstoneWADOImageLoader.wadouri.loadFileRequest(imageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDataByImageType(dataset) {
|
||||||
|
const imageInstance = getImageInstance(dataset);
|
||||||
|
|
||||||
|
if (imageInstance) {
|
||||||
|
const imageId = getImageInstanceId(imageInstance);
|
||||||
|
let getDicomDataMethod = fetchIt;
|
||||||
|
const loaderType = getImageLoaderType(imageId);
|
||||||
|
|
||||||
|
switch (loaderType) {
|
||||||
|
case 'dicomfile':
|
||||||
|
getDicomDataMethod = cornerstoneRetriever.bind(this, imageId);
|
||||||
|
break;
|
||||||
|
case 'wadors':
|
||||||
|
const url = imageInstance.getData().wadoRoot;
|
||||||
|
const studyInstanceUID = imageInstance.getStudyInstanceUID();
|
||||||
|
const seriesInstanceUID = imageInstance.getSeriesInstanceUID();
|
||||||
|
const sopInstanceUID = imageInstance.getSOPInstanceUID();
|
||||||
|
const invalidParams = someInvalidStrings([
|
||||||
|
url,
|
||||||
|
studyInstanceUID,
|
||||||
|
seriesInstanceUID,
|
||||||
|
sopInstanceUID,
|
||||||
|
]);
|
||||||
|
if (invalidParams) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDicomDataMethod = wadorsRetriever.bind(
|
||||||
|
this,
|
||||||
|
url,
|
||||||
|
studyInstanceUID,
|
||||||
|
seriesInstanceUID,
|
||||||
|
sopInstanceUID
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'wadouri':
|
||||||
|
// Strip out the image loader specifier
|
||||||
|
imageId = imageId.substring(imageId.indexOf(':') + 1);
|
||||||
|
|
||||||
|
if (someInvalidStrings(imageId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getDicomDataMethod = fetchIt.bind(this, imageId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDicomDataMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDataByDatasetType(dataset) {
|
||||||
|
const {
|
||||||
|
studyInstanceUid,
|
||||||
|
seriesInstanceUid,
|
||||||
|
sopInstanceUid,
|
||||||
|
authorizationHeaders,
|
||||||
|
wadoRoot,
|
||||||
|
wadoUri,
|
||||||
|
} = dataset;
|
||||||
|
// Retrieve wadors or just try to fetch wadouri
|
||||||
|
if (!someInvalidStrings(wadoRoot)) {
|
||||||
|
return wadorsRetriever(
|
||||||
|
wadoRoot,
|
||||||
|
studyInstanceUid,
|
||||||
|
seriesInstanceUid,
|
||||||
|
sopInstanceUid,
|
||||||
|
authorizationHeaders
|
||||||
|
);
|
||||||
|
} else if (!someInvalidStrings(wadoUri)) {
|
||||||
|
return fetchIt(wadoUri, { headers: authorizationHeaders });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*getLoaderIterator(dataset, studies) {
|
||||||
|
yield this.getLocalData(dataset, studies);
|
||||||
|
yield this.getDataByImageType(dataset);
|
||||||
|
yield this.getDataByDatasetType(dataset);
|
||||||
|
}
|
||||||
|
|
||||||
|
findDicomDataPromise(dataset, studies) {
|
||||||
|
const loaderIterator = this.getLoaderIterator(dataset, studies);
|
||||||
|
// it returns first valid retriever method.
|
||||||
|
for (const loader of loaderIterator) {
|
||||||
|
if (loader) {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case of no valid loader
|
||||||
|
throw new Error('Invalid dicom data loader');
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default DicomLoaderService;
|
||||||
@@ -5,11 +5,16 @@ function getWADORSImageUrl(instance, frame) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to sum 1 because WADO-RS frame number is 1-based
|
// Use null to obtain an imageId which represents the instance
|
||||||
frame = frame ? parseInt(frame) + 1 : 1;
|
if (frame === null) {
|
||||||
|
wadorsuri = wadorsuri.replace(/frames\/(\d+)/, '');
|
||||||
|
} else {
|
||||||
|
// We need to sum 1 because WADO-RS frame number is 1-based
|
||||||
|
frame = frame ? parseInt(frame) + 1 : 1;
|
||||||
|
|
||||||
// Replaces /frame/1 by /frame/{frame}
|
// Replaces /frame/1 by /frame/{frame}
|
||||||
wadorsuri = wadorsuri.replace(/frames\/(\d+)/, `frames/${frame}`);
|
wadorsuri = wadorsuri.replace(/frames\/(\d+)/, `frames/${frame}`);
|
||||||
|
}
|
||||||
|
|
||||||
return wadorsuri;
|
return wadorsuri;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import sortBy from './sortBy.js';
|
|||||||
import studyMetadataManager from './studyMetadataManager';
|
import studyMetadataManager from './studyMetadataManager';
|
||||||
import updateMetaDataManager from './updateMetaDataManager.js';
|
import updateMetaDataManager from './updateMetaDataManager.js';
|
||||||
import writeScript from './writeScript.js';
|
import writeScript from './writeScript.js';
|
||||||
|
import DicomLoaderService from './dicomLoaderService.js';
|
||||||
|
|
||||||
const utils = {
|
const utils = {
|
||||||
guid,
|
guid,
|
||||||
@@ -21,6 +22,7 @@ const utils = {
|
|||||||
// Updates WADO-RS metaDataManager
|
// Updates WADO-RS metaDataManager
|
||||||
updateMetaDataManager,
|
updateMetaDataManager,
|
||||||
DICOMTagDescriptions,
|
DICOMTagDescriptions,
|
||||||
|
DicomLoaderService,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -35,6 +37,7 @@ export {
|
|||||||
// Updates WADO-RS metaDataManager
|
// Updates WADO-RS metaDataManager
|
||||||
updateMetaDataManager,
|
updateMetaDataManager,
|
||||||
DICOMTagDescriptions,
|
DICOMTagDescriptions,
|
||||||
|
DicomLoaderService,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default utils;
|
export default utils;
|
||||||
@@ -14,6 +14,7 @@ describe('Top level exports', () => {
|
|||||||
// Updates WADO-RS metaDataManager
|
// Updates WADO-RS metaDataManager
|
||||||
'updateMetaDataManager',
|
'updateMetaDataManager',
|
||||||
'DICOMTagDescriptions',
|
'DICOMTagDescriptions',
|
||||||
|
'DicomLoaderService',
|
||||||
].sort();
|
].sort();
|
||||||
|
|
||||||
const exports = Object.keys(utils.default).sort();
|
const exports = Object.keys(utils.default).sort();
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.50.3...@ohif/i18n@0.50.4) (2019-09-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/i18n
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.3](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.50.2...@ohif/i18n@0.50.3) (2019-09-04)
|
## [0.50.3](https://github.com/OHIF/Viewers/compare/@ohif/i18n@0.50.2...@ohif/i18n@0.50.3) (2019-09-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/i18n
|
**Note:** Version bump only for package @ohif/i18n
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/i18n",
|
"name": "@ohif/i18n",
|
||||||
"version": "0.50.3",
|
"version": "0.50.4",
|
||||||
"description": "Internationalization library for The OHIF Viewer",
|
"description": "Internationalization library for The OHIF Viewer",
|
||||||
"author": "OHIF",
|
"author": "OHIF",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -32,8 +32,8 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"i18next": "^17.0.3",
|
"i18next": "^17.0.3",
|
||||||
"i18next-browser-languagedetector": "^3.0.1",
|
"i18next-browser-languagedetector": "^3.0.1",
|
||||||
"react": "^16.0.0",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^16.0.0",
|
"react-dom": "^16.8.6",
|
||||||
"react-i18next": "^10.11.0"
|
"react-i18next": "^10.11.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -3,6 +3,61 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [0.52.0](https://github.com/OHIF/Viewers/compare/@ohif/ui@0.51.3...@ohif/ui@0.52.0) (2019-10-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 MPR UI improvements. Added MinIP, AvgIP, slab thickness slider and mode toggle ([#947](https://github.com/OHIF/Viewers/issues/947)) ([c79c0c3](https://github.com/OHIF/Viewers/commit/c79c0c3))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.51.3](https://github.com/OHIF/Viewers/compare/@ohif/ui@0.51.2...@ohif/ui@0.51.3) (2019-10-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Address issues with touch devices and drag/drop causing crashes ([#982](https://github.com/OHIF/Viewers/issues/982)) ([cf40a83](https://github.com/OHIF/Viewers/commit/cf40a83))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.51.2](https://github.com/OHIF/Viewers/compare/@ohif/ui@0.51.1...@ohif/ui@0.51.2) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Set series into active viewport by clicking on thumbnail ([#945](https://github.com/OHIF/Viewers/issues/945)) ([5551f81](https://github.com/OHIF/Viewers/commit/5551f81)), closes [#895](https://github.com/OHIF/Viewers/issues/895) [#895](https://github.com/OHIF/Viewers/issues/895)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.51.1](https://github.com/OHIF/Viewers/compare/@ohif/ui@0.51.0...@ohif/ui@0.51.1) (2019-09-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Use HTML5Backend for drag-drop if the device does not support touch ([#927](https://github.com/OHIF/Viewers/issues/927)) ([6fdac4d](https://github.com/OHIF/Viewers/commit/6fdac4d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.51.0](https://github.com/OHIF/Viewers/compare/@ohif/ui@0.50.4...@ohif/ui@0.51.0) (2019-09-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **EraserTool:** add eraserTool to @ohif/extension-cornerstone ([#912](https://github.com/OHIF/Viewers/issues/912)) ([698d274](https://github.com/OHIF/Viewers/commit/698d274))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/ui@0.50.3...@ohif/ui@0.50.4) (2019-09-06)
|
## [0.50.4](https://github.com/OHIF/Viewers/compare/@ohif/ui@0.50.3...@ohif/ui@0.50.4) (2019-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/ui
|
**Note:** Version bump only for package @ohif/ui
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/ui",
|
"name": "@ohif/ui",
|
||||||
"version": "0.50.4",
|
"version": "0.52.0",
|
||||||
"description": "A set of React components for Medical Imaging Viewers",
|
"description": "A set of React components for Medical Imaging Viewers",
|
||||||
"author": "OHIF Contributors",
|
"author": "OHIF Contributors",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -48,8 +48,9 @@
|
|||||||
"prop-types": "15.6.2",
|
"prop-types": "15.6.2",
|
||||||
"react-bootstrap-modal": "4.2.0",
|
"react-bootstrap-modal": "4.2.0",
|
||||||
"react-dates": "18.4.1",
|
"react-dates": "18.4.1",
|
||||||
"react-dnd": "8.0.3",
|
"react-dnd": "9.3.4",
|
||||||
"react-dnd-touch-backend": "^0.8.3",
|
"react-dnd-html5-backend": "^9.3.4",
|
||||||
|
"react-dnd-touch-backend": "^9.3.4",
|
||||||
"react-i18next": "^10.11.0",
|
"react-i18next": "^10.11.0",
|
||||||
"react-with-direction": "1.3.0"
|
"react-with-direction": "1.3.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,15 +6,29 @@ export class Checkbox extends Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
label: PropTypes.string.isRequired,
|
label: PropTypes.string.isRequired,
|
||||||
checked: PropTypes.bool,
|
checked: PropTypes.bool,
|
||||||
|
onChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { checked: props.checked, label: props.label };
|
this.state = { checked: !!props.checked, label: props.label };
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange(e) {
|
handleChange(e) {
|
||||||
this.setState({ checked: e.target.checked });
|
const checked = e.target.checked;
|
||||||
|
this.setState({ checked });
|
||||||
|
if (this.props.onChange) this.props.onChange(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(props) {
|
||||||
|
const { checked = false, label } = props;
|
||||||
|
|
||||||
|
if (this.state.checked !== checked || this.state.label !== label) {
|
||||||
|
this.setState({
|
||||||
|
checked,
|
||||||
|
label,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -32,9 +46,7 @@ export class Checkbox extends Component {
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={this.state.checked}
|
checked={this.state.checked}
|
||||||
onChange={e => {
|
onChange={this.handleChange.bind(this)}
|
||||||
this.handleChange(e);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
{checkbox}
|
{checkbox}
|
||||||
{this.state.label}
|
{this.state.label}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
UserPreferencesModal,
|
UserPreferencesModal,
|
||||||
} from './userPreferencesModal';
|
} from './userPreferencesModal';
|
||||||
|
|
||||||
|
import { Checkbox } from './checkbox';
|
||||||
import { CineDialog } from './cineDialog';
|
import { CineDialog } from './cineDialog';
|
||||||
import { QuickSwitch } from './quickSwitch';
|
import { QuickSwitch } from './quickSwitch';
|
||||||
import { RoundedButtonGroup } from './roundedButtonGroup';
|
import { RoundedButtonGroup } from './roundedButtonGroup';
|
||||||
@@ -23,6 +24,7 @@ import { ToolbarSection } from './toolbarSection';
|
|||||||
import { Tooltip } from './tooltip';
|
import { Tooltip } from './tooltip';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
Checkbox,
|
||||||
CineDialog,
|
CineDialog,
|
||||||
ExampleDropTarget,
|
ExampleDropTarget,
|
||||||
LayoutButton,
|
LayoutButton,
|
||||||
|
|||||||
@@ -99,13 +99,13 @@ class ThumbnailEntry extends Component {
|
|||||||
|
|
||||||
onClick = () => {
|
onClick = () => {
|
||||||
if (this.props.onClick) {
|
if (this.props.onClick) {
|
||||||
this.props.onClick();
|
this.props.onClick(this.props.displaySetInstanceUid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onDoubleClick = () => {
|
onDoubleClick = () => {
|
||||||
if (this.props.onDoubleClick) {
|
if (this.props.onDoubleClick) {
|
||||||
this.props.onDoubleClick();
|
this.props.onDoubleClick(this.props.displaySetInstanceUid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import edit from './icons/edit.svg';
|
|||||||
import ellipseCircle from './icons/ellipse-circle.svg';
|
import ellipseCircle from './icons/ellipse-circle.svg';
|
||||||
import ellipseH from './icons/ellipse-h.svg';
|
import ellipseH from './icons/ellipse-h.svg';
|
||||||
import ellipseV from './icons/ellipse-v.svg';
|
import ellipseV from './icons/ellipse-v.svg';
|
||||||
|
import eraser from './icons/eraser.svg';
|
||||||
import exclamationCircle from './icons/exclamation-circle.svg';
|
import exclamationCircle from './icons/exclamation-circle.svg';
|
||||||
import exclamationTriangle from './icons/exclamation-triangle.svg';
|
import exclamationTriangle from './icons/exclamation-triangle.svg';
|
||||||
import fastBackward from './icons/fast-backward.svg';
|
import fastBackward from './icons/fast-backward.svg';
|
||||||
@@ -110,6 +111,7 @@ const ICONS = {
|
|||||||
'create-comment': createComment,
|
'create-comment': createComment,
|
||||||
'create-screen-capture': createScreenCapture,
|
'create-screen-capture': createScreenCapture,
|
||||||
edit,
|
edit,
|
||||||
|
eraser,
|
||||||
'fast-backward': fastBackward,
|
'fast-backward': fastBackward,
|
||||||
'fast-forward': fastForward,
|
'fast-forward': fastForward,
|
||||||
'object-group': objectGroup,
|
'object-group': objectGroup,
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 2048 1792"
|
||||||
|
aria-labelledby="eraser"
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<title id="title">Eraser</title>
|
||||||
|
<path transform="translate(0,1792) scale(1,-1)" fill="ACTIVE_COLOR" d="M960 1408l336-384h-768l-336 384h768zm1013-1077q15
|
||||||
|
34 9.5 71.5t-30.5 65.5l-896 1024q-38 44-96 44h-768q-38
|
||||||
|
0-69.5-20.5t-47.5-54.5q-15-34-9.5-71.5t30.5-65.5l896-1024q38-44 96-44h768q38
|
||||||
|
0 69.5 20.5t47.5 54.5z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 492 B |
@@ -2,6 +2,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.range:focus {
|
.range:focus {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class Range extends React.Component {
|
|||||||
|
|
||||||
handleChange = event => {
|
handleChange = event => {
|
||||||
this.setState({ value: event.target.value });
|
this.setState({ value: event.target.value });
|
||||||
if (this.props.onChange) this.props.onChange();
|
if (this.props.onChange) this.props.onChange(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -21,6 +21,7 @@ class Range extends React.Component {
|
|||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
min={this.props.min}
|
min={this.props.min}
|
||||||
max={this.props.max}
|
max={this.props.max}
|
||||||
|
step={this.props.step || 1}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
id={this.props.id}
|
id={this.props.id}
|
||||||
className="range"
|
className="range"
|
||||||
|
|||||||
@@ -34,10 +34,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.select-ohif:focus {
|
.select-ohif:focus {
|
||||||
border-color: #aaa;
|
|
||||||
box-shadow: 0 0 1px 3px rgba(59, 153, 252, 0.7);
|
|
||||||
box-shadow: 0 0 0 3px -moz-mac-focusring;
|
|
||||||
color: #222;
|
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ class Select extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleChange = event => {
|
handleChange = event => {
|
||||||
this.setState({ value: event.target.value });
|
const value = event.target.value;
|
||||||
if (this.props.onChange) this.props.onChange();
|
this.setState({ value });
|
||||||
|
if (this.props.onChange) this.props.onChange(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
Checkbox,
|
||||||
CineDialog,
|
CineDialog,
|
||||||
ExampleDropTarget,
|
ExampleDropTarget,
|
||||||
LayoutButton,
|
LayoutButton,
|
||||||
@@ -25,7 +26,7 @@ import {
|
|||||||
import { ICONS, Icon } from './elements';
|
import { ICONS, Icon } from './elements';
|
||||||
|
|
||||||
// Alias this for now as not all dependents are using strict versioning
|
// Alias this for now as not all dependents are using strict versioning
|
||||||
import { DropdownMenu as Dropdown } from './elements/form';
|
import { DropdownMenu as Dropdown, Range, Select } from './elements/form';
|
||||||
import ExpandableToolMenu from './viewer/ExpandableToolMenu.js';
|
import ExpandableToolMenu from './viewer/ExpandableToolMenu.js';
|
||||||
import LayoutManager from './LayoutChooser/LayoutManager.js';
|
import LayoutManager from './LayoutChooser/LayoutManager.js';
|
||||||
import LayoutPanelDropTarget from './LayoutChooser/LayoutPanelDropTarget.js';
|
import LayoutPanelDropTarget from './LayoutChooser/LayoutPanelDropTarget.js';
|
||||||
@@ -38,6 +39,7 @@ import ViewerbaseDragDropContext from './utils/viewerbaseDragDropContext.js';
|
|||||||
export {
|
export {
|
||||||
ICONS,
|
ICONS,
|
||||||
//
|
//
|
||||||
|
Checkbox,
|
||||||
CineDialog,
|
CineDialog,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
ExpandableToolMenu,
|
ExpandableToolMenu,
|
||||||
@@ -53,8 +55,10 @@ export {
|
|||||||
OverlayTrigger,
|
OverlayTrigger,
|
||||||
PlayClipButton,
|
PlayClipButton,
|
||||||
QuickSwitch,
|
QuickSwitch,
|
||||||
|
Range,
|
||||||
RoundedButtonGroup,
|
RoundedButtonGroup,
|
||||||
ScrollableArea,
|
ScrollableArea,
|
||||||
|
Select,
|
||||||
SelectTree,
|
SelectTree,
|
||||||
SimpleDialog,
|
SimpleDialog,
|
||||||
StudyBrowser,
|
StudyBrowser,
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
import { DragDropContext } from 'react-dnd';
|
import React from 'react';
|
||||||
|
import { DndProvider } from "react-dnd";
|
||||||
|
import HTML5Backend from 'react-dnd-html5-backend';
|
||||||
import TouchBackend from 'react-dnd-touch-backend';
|
import TouchBackend from 'react-dnd-touch-backend';
|
||||||
|
|
||||||
|
const isTouchDevice = !!('ontouchstart' in window || navigator.maxTouchPoints);
|
||||||
|
|
||||||
// See https://github.com/react-dnd/react-dnd/issues/186#issuecomment-335429067
|
// See https://github.com/react-dnd/react-dnd/issues/186#issuecomment-335429067
|
||||||
// https://github.com/react-dnd/react-dnd/issues/186#issuecomment-282789420
|
// https://github.com/react-dnd/react-dnd/issues/186#issuecomment-282789420
|
||||||
// TODO: Find a way for this context to be used in the parent application as well.
|
//
|
||||||
|
|
||||||
// http://react-dnd.github.io/react-dnd/docs/api/drag-drop-context
|
// http://react-dnd.github.io/react-dnd/docs/api/drag-drop-context
|
||||||
export default function viewerbaseDragDropContext(DecoratedClass) {
|
export default function viewerbaseDragDropContext(DecoratedClass) {
|
||||||
return DragDropContext(TouchBackend({ enableMouseEvents: true }), null, true)(
|
const backend = isTouchDevice ? TouchBackend : HTML5Backend;
|
||||||
DecoratedClass
|
const opts = isTouchDevice ? { enableMouseEvents: true } : {};
|
||||||
|
|
||||||
|
return (props) => (
|
||||||
|
<DndProvider backend={backend} opts={opts}>
|
||||||
|
<DecoratedClass {...props}/>
|
||||||
|
</DndProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -108,16 +108,8 @@ class ExpandableToolMenu extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
const getToolBarButtonComponent = () => {
|
||||||
<OverlayTrigger
|
return (
|
||||||
key="menu-button"
|
|
||||||
trigger="click"
|
|
||||||
placement="bottom"
|
|
||||||
rootClose={true}
|
|
||||||
handleHide={this.onOverlayHide}
|
|
||||||
onClick={this.onExpandableToolClick}
|
|
||||||
overlay={this.toolbarMenuOverlay()}
|
|
||||||
>
|
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
key="menu-button"
|
key="menu-button"
|
||||||
type="tool"
|
type="tool"
|
||||||
@@ -128,6 +120,22 @@ class ExpandableToolMenu extends React.Component {
|
|||||||
isExpandable={true}
|
isExpandable={true}
|
||||||
isExpanded={this.state.isExpanded}
|
isExpanded={this.state.isExpanded}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toolbarComponent = getToolBarButtonComponent();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OverlayTrigger
|
||||||
|
key="menu-button"
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom"
|
||||||
|
rootClose={true}
|
||||||
|
handleHide={this.onOverlayHide}
|
||||||
|
onClick={this.onExpandableToolClick}
|
||||||
|
overlay={this.toolbarMenuOverlay()}
|
||||||
|
>
|
||||||
|
{toolbarComponent}
|
||||||
</OverlayTrigger>
|
</OverlayTrigger>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge');
|
||||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||||
//
|
//
|
||||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||||
const fontsToJavaScriptRule = require('./rules/fontsToJavaScript.js');
|
const fontsToJavaScriptRule = require('./rules/fontsToJavaScript.js');
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
// const
|
// const
|
||||||
const SRC_DIR = path.join(__dirname, '../src');
|
const SRC_DIR = path.join(__dirname, '../src');
|
||||||
const DIST_DIR = path.join(__dirname, '../dist');
|
const DIST_DIR = path.join(__dirname, '../dist');
|
||||||
|
const PUBLIC_DIR = path.join(__dirname, '../public');
|
||||||
|
// ~~ Env Vars
|
||||||
|
const HTML_TEMPLATE = process.env.HTML_TEMPLATE || 'script-tag.html';
|
||||||
|
const PUBLIC_URL = process.env.PUBLIC_URL || '/';
|
||||||
|
|
||||||
module.exports = (env, argv) => {
|
module.exports = (env, argv) => {
|
||||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||||
@@ -33,7 +39,7 @@ module.exports = (env, argv) => {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: DIST_DIR,
|
path: DIST_DIR,
|
||||||
library: 'ohifViewer',
|
library: 'OHIFViewer',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
filename: 'index.umd.js',
|
filename: 'index.umd.js',
|
||||||
},
|
},
|
||||||
@@ -43,6 +49,15 @@ module.exports = (env, argv) => {
|
|||||||
plugins: [
|
plugins: [
|
||||||
// Clean output.path
|
// Clean output.path
|
||||||
new CleanWebpackPlugin(),
|
new CleanWebpackPlugin(),
|
||||||
|
// Generate "index.html" w/ correct includes/imports
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
inject: false,
|
||||||
|
template: `${PUBLIC_DIR}/html-templates/${HTML_TEMPLATE}`,
|
||||||
|
filename: 'index.html',
|
||||||
|
}),
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({
|
||||||
|
maxChunks: 1
|
||||||
|
})
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -71,6 +71,12 @@ module.exports = (env, argv) => {
|
|||||||
// Ignore our configuration files
|
// Ignore our configuration files
|
||||||
ignore: ['config/*', 'html-templates/*', '.DS_Store'],
|
ignore: ['config/*', 'html-templates/*', '.DS_Store'],
|
||||||
},
|
},
|
||||||
|
// Short term solution to make sure GCloud config is available in output
|
||||||
|
// for our docker implementation
|
||||||
|
{
|
||||||
|
from: `${PUBLIC_DIR}/config/google.js`,
|
||||||
|
to: `${DIST_DIR}/google.js`,
|
||||||
|
},
|
||||||
// Copy over and rename our target app config file
|
// Copy over and rename our target app config file
|
||||||
{
|
{
|
||||||
from: `${PUBLIC_DIR}/${APP_CONFIG}`,
|
from: `${PUBLIC_DIR}/${APP_CONFIG}`,
|
||||||
@@ -108,6 +114,8 @@ module.exports = (env, argv) => {
|
|||||||
hot: true,
|
hot: true,
|
||||||
open: true,
|
open: true,
|
||||||
port: 3000,
|
port: 3000,
|
||||||
|
host: '0.0.0.0',
|
||||||
|
public: 'http://localhost:' + 3000,
|
||||||
historyApiFallback: {
|
historyApiFallback: {
|
||||||
disableDotRule: true,
|
disableDotRule: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,332 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.3.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.8...@ohif/viewer@1.3.0) (2019-10-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 MPR UI improvements. Added MinIP, AvgIP, slab thickness slider and mode toggle ([#947](https://github.com/OHIF/Viewers/issues/947)) ([c79c0c3](https://github.com/OHIF/Viewers/commit/c79c0c3))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.8](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.7...@ohif/viewer@1.2.8) (2019-10-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.7](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.6...@ohif/viewer@1.2.7) (2019-10-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.6](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.5...@ohif/viewer@1.2.6) (2019-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.4...@ohif/viewer@1.2.5) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* version bump issue ([#963](https://github.com/OHIF/Viewers/issues/963)) ([e607ed2](https://github.com/OHIF/Viewers/commit/e607ed2)), closes [#962](https://github.com/OHIF/Viewers/issues/962)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.0.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.3...@ohif/viewer@2.0.0) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Add DicomLoaderService & FileLoaderService to fix SR, PDF, and SEG support in local file and WADO-RS-only use cases ([#862](https://github.com/OHIF/Viewers/issues/862)) ([e7e1a8a](https://github.com/OHIF/Viewers/commit/e7e1a8a)), closes [#838](https://github.com/OHIF/Viewers/issues/838)
|
||||||
|
* version bump issue ([#962](https://github.com/OHIF/Viewers/issues/962)) ([c80ea17](https://github.com/OHIF/Viewers/commit/c80ea17))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* DICOM Seg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [2.0.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.3...@ohif/viewer@2.0.0) (2019-09-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Add DicomLoaderService & FileLoaderService to fix SR, PDF, and SEG support in local file and WADO-RS-only use cases ([#862](https://github.com/OHIF/Viewers/issues/862)) ([e7e1a8a](https://github.com/OHIF/Viewers/commit/e7e1a8a)), closes [#838](https://github.com/OHIF/Viewers/issues/838)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* DICOM Seg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.2...@ohif/viewer@1.2.3) (2019-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.1...@ohif/viewer@1.2.2) (2019-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.2.0...@ohif/viewer@1.2.1) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* google cloud support w/ docker (via env var) ([#958](https://github.com/OHIF/Viewers/issues/958)) ([e375a4a](https://github.com/OHIF/Viewers/commit/e375a4a))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.2.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.14...@ohif/viewer@1.2.0) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 React custom component on toolbar button ([#935](https://github.com/OHIF/Viewers/issues/935)) ([a90605c](https://github.com/OHIF/Viewers/commit/a90605c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.14](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.13...@ohif/viewer@1.1.14) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Set series into active viewport by clicking on thumbnail ([#945](https://github.com/OHIF/Viewers/issues/945)) ([5551f81](https://github.com/OHIF/Viewers/commit/5551f81)), closes [#895](https://github.com/OHIF/Viewers/issues/895) [#895](https://github.com/OHIF/Viewers/issues/895)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.13](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.12...@ohif/viewer@1.1.13) (2019-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Add some code splitting for PWA build ([#937](https://github.com/OHIF/Viewers/issues/937)) ([8938035](https://github.com/OHIF/Viewers/commit/8938035))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.12](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.11...@ohif/viewer@1.1.12) (2019-09-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.11](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.10...@ohif/viewer@1.1.11) (2019-09-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.10](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.9...@ohif/viewer@1.1.10) (2019-09-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.9](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.8...@ohif/viewer@1.1.9) (2019-09-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.8](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.7...@ohif/viewer@1.1.8) (2019-09-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.7](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.6...@ohif/viewer@1.1.7) (2019-09-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.6](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.5...@ohif/viewer@1.1.6) (2019-09-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.4...@ohif/viewer@1.1.5) (2019-09-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* bump cornerstone-tools to latest version ([f519f86](https://github.com/OHIF/Viewers/commit/f519f86))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.4](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.3...@ohif/viewer@1.1.4) (2019-09-17)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.2...@ohif/viewer@1.1.3) (2019-09-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 🐛 Fix issue on not loading gcloud ([#919](https://github.com/OHIF/Viewers/issues/919)) ([f723546](https://github.com/OHIF/Viewers/commit/f723546))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.1...@ohif/viewer@1.1.2) (2019-09-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.1.0...@ohif/viewer@1.1.1) (2019-09-12)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.1.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.0.5...@ohif/viewer@1.1.0) (2019-09-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 🎸 Load local file or folder using native dialog ([#870](https://github.com/OHIF/Viewers/issues/870)) ([c221dd8](https://github.com/OHIF/Viewers/commit/c221dd8))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.0.4...@ohif/viewer@1.0.5) (2019-09-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.4](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.0.3...@ohif/viewer@1.0.4) (2019-09-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.0.2...@ohif/viewer@1.0.3) (2019-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* on-brand library global name ([ababe63](https://github.com/OHIF/Viewers/commit/ababe63))
|
||||||
|
* remove requestOptions when key is not needed ([32bc47d](https://github.com/OHIF/Viewers/commit/32bc47d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.0.1...@ohif/viewer@1.0.2) (2019-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* import regenerator-runtime for umd build ([bad987a](https://github.com/OHIF/Viewers/commit/bad987a))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@1.0.0...@ohif/viewer@1.0.1) (2019-09-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.0.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@0.50.21...@ohif/viewer@1.0.0) (2019-09-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* 💡 React components to consume appConfig using Context ([#852](https://github.com/OHIF/Viewers/issues/852)) ([7c4ee73](https://github.com/OHIF/Viewers/commit/7c4ee73)), closes [#725](https://github.com/OHIF/Viewers/issues/725) [#725](https://github.com/OHIF/Viewers/issues/725)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* #725
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.50.21](https://github.com/OHIF/Viewers/compare/@ohif/viewer@0.50.20...@ohif/viewer@0.50.21) (2019-09-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* viewer project should build output before publish ([94b625d](https://github.com/OHIF/Viewers/commit/94b625d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.50.20](https://github.com/OHIF/Viewers/compare/@ohif/viewer@0.50.19...@ohif/viewer@0.50.20) (2019-09-06)
|
## [0.50.20](https://github.com/OHIF/Viewers/compare/@ohif/viewer@0.50.19...@ohif/viewer@0.50.20) (2019-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @ohif/viewer
|
**Note:** Version bump only for package @ohif/viewer
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"baseUrl": "http://localhost:3000",
|
"baseUrl": "http://localhost:3000",
|
||||||
"video": true,
|
"video": false,
|
||||||
|
"chromeWebSecurity": false,
|
||||||
"projectId": "4oe38f"
|
"projectId": "4oe38f"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
const dataTransfer = new DataTransfer();
|
||||||
|
|
||||||
|
export const DragSimulator = {
|
||||||
|
MAX_TRIES: 1,
|
||||||
|
DELAY_INTERVAL_MS: 10,
|
||||||
|
counter: 0,
|
||||||
|
rectsEqual(r1, r2) {
|
||||||
|
return (
|
||||||
|
r1.top === r2.top &&
|
||||||
|
r1.right === r2.right &&
|
||||||
|
r1.bottom === r2.bottom &&
|
||||||
|
r1.left === r2.left
|
||||||
|
);
|
||||||
|
},
|
||||||
|
get dropped() {
|
||||||
|
const currentSourcePosition = this.source.getBoundingClientRect();
|
||||||
|
return !this.rectsEqual(
|
||||||
|
this.initialSourcePosition,
|
||||||
|
currentSourcePosition
|
||||||
|
);
|
||||||
|
},
|
||||||
|
get hasTriesLeft() {
|
||||||
|
return this.counter < this.MAX_TRIES;
|
||||||
|
},
|
||||||
|
dragstart() {
|
||||||
|
cy.log('**DRAG START**');
|
||||||
|
cy.wrap(this.source)
|
||||||
|
.trigger('mousedown', { which: 1, button: 0 })
|
||||||
|
.trigger('dragstart', { dataTransfer })
|
||||||
|
.trigger('drag', {});
|
||||||
|
},
|
||||||
|
drop() {
|
||||||
|
cy.log('**DROP**');
|
||||||
|
return cy
|
||||||
|
.wrap(this.target)
|
||||||
|
.trigger('mousemove', 'center')
|
||||||
|
.trigger('dragover', { dataTransfer, force: true })
|
||||||
|
.trigger('drop', { dataTransfer, force: true })
|
||||||
|
.trigger('dragend', { dataTransfer })
|
||||||
|
.trigger('mouseup', { which: 1, button: 0 });
|
||||||
|
},
|
||||||
|
dragover() {
|
||||||
|
cy.log('**DRAGOVER**');
|
||||||
|
if (!this.dropped && this.hasTriesLeft) {
|
||||||
|
this.counter += 1;
|
||||||
|
return cy
|
||||||
|
.wrap(this.target)
|
||||||
|
.trigger('mousemove', 'center')
|
||||||
|
.trigger('dragover', {
|
||||||
|
dataTransfer,
|
||||||
|
position: this.position,
|
||||||
|
})
|
||||||
|
.wait(this.DELAY_INTERVAL_MS)
|
||||||
|
.then(() => this.dragover());
|
||||||
|
}
|
||||||
|
return this.drop().then(() => true);
|
||||||
|
},
|
||||||
|
init(source, target, position) {
|
||||||
|
this.source = source;
|
||||||
|
this.target = target;
|
||||||
|
this.position = position;
|
||||||
|
this.counter = 0;
|
||||||
|
|
||||||
|
this.dragstart();
|
||||||
|
|
||||||
|
return cy.wait(this.DELAY_INTERVAL_MS).then(() => {
|
||||||
|
this.initialSourcePosition = this.source.getBoundingClientRect();
|
||||||
|
return this.dragover();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
simulate(sourceWrapper, targetSelector, position = 'center') {
|
||||||
|
return cy
|
||||||
|
.get(targetSelector)
|
||||||
|
.then(targetWrapper =>
|
||||||
|
this.init(sourceWrapper.get(0), targetWrapper.get(0), position)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
File renamed without changes.
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
TODO: Temporarily commented out because it is failing on CI due to timing issues
|
||||||
|
describe('OHIF Study Viewer Page', () => {
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
cy.openStudy("MISTER^MR");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('checks if series thumbnails are being displayed', ()=> {
|
||||||
|
cy.get('.ThumbnailEntryContainer')
|
||||||
|
.its('length')
|
||||||
|
.should('be.gt', 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('drags and drop a series thumbnail into viewport', () => {
|
||||||
|
cy.get('.ThumbnailEntryContainer:nth-child(2)') //element to be dragged
|
||||||
|
.drag('.cornerstone-canvas'); //dropzone element
|
||||||
|
|
||||||
|
const overlaySeriesInformation = 'div.ViewportOverlay > div.bottom-left.overlay-element > div';
|
||||||
|
const expectedText = 'Ser: 2Img: 1 1/13512 x 512Loc: -17.60 mm Thick: 3.00 mm';
|
||||||
|
|
||||||
|
cy.get(overlaySeriesInformation)
|
||||||
|
.should('have.text', expectedText);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('checks if Series left panel can be hidden/displayed', ()=> {
|
||||||
|
const seriesButton = '.pull-left > .RoundedButtonGroup > .roundedButtonWrapper > .roundedButton';
|
||||||
|
const leftPanel = 'section.sidepanel.from-left';
|
||||||
|
|
||||||
|
cy.get(seriesButton).click();
|
||||||
|
cy.get(leftPanel).should('not.be.enabled')
|
||||||
|
|
||||||
|
cy.get(seriesButton).click();
|
||||||
|
cy.get(leftPanel).should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('checks if Measurements right panel can be hidden/displayed', ()=> {
|
||||||
|
const measurementsButton = '.pull-right > .RoundedButtonGroup > .roundedButtonWrapper > .roundedButton';
|
||||||
|
const rightPanel = 'section.sidepanel.from-right';
|
||||||
|
|
||||||
|
cy.get(measurementsButton).click();
|
||||||
|
cy.get(rightPanel).should('be.visible');
|
||||||
|
|
||||||
|
|
||||||
|
cy.get(measurementsButton).click();
|
||||||
|
cy.get(rightPanel).should('not.be.enabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
*/
|
||||||
File renamed without changes.
@@ -1,3 +1,5 @@
|
|||||||
|
import { DragSimulator } from "../helpers/DragSimulator.js";
|
||||||
|
|
||||||
// ***********************************************
|
// ***********************************************
|
||||||
// This example commands.js shows you how to
|
// This example commands.js shows you how to
|
||||||
// create various custom commands and overwrite
|
// create various custom commands and overwrite
|
||||||
@@ -23,3 +25,17 @@
|
|||||||
//
|
//
|
||||||
// -- This is will overwrite an existing command --
|
// -- This is will overwrite an existing command --
|
||||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||||
|
|
||||||
|
Cypress.Commands.add('openStudy', (patientName) => {
|
||||||
|
cy.visit('/');
|
||||||
|
cy.get('#patientName')
|
||||||
|
.type(patientName);
|
||||||
|
cy.get('.studylistStudy > .patientName')
|
||||||
|
.contains(patientName)
|
||||||
|
.click();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Cypress.Commands.add('drag', {prevSubject: 'element',},
|
||||||
|
(...args) => DragSimulator.simulate(...args)
|
||||||
|
);
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
|
|
||||||
<meta name="description" content="Open Health Imaging Foundation DICOM Viewer" />
|
|
||||||
<meta name="viewport"
|
|
||||||
content="width=device-width,initial-scale=1.0,minimum-scale=1,maximum-scale=1,user-scalable=no" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<meta http-equiv="cleartype" content="on" />
|
|
||||||
<meta name="MobileOptimized" content="320" />
|
|
||||||
<meta name="HandheldFriendly" content="True" />
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
|
|
||||||
<!-- Latest compiled and minified CSS -->
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
|
|
||||||
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous" />
|
|
||||||
|
|
||||||
<title>OHIF Standalone Viewer</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
|
||||||
|
|
||||||
<div id="root"></div>
|
|
||||||
|
|
||||||
<!-- Load React. -->
|
|
||||||
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
|
|
||||||
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
|
|
||||||
|
|
||||||
<script src="/index.umd.js" crossorigin></script>
|
|
||||||
<script>
|
|
||||||
window.config = {
|
|
||||||
// default: '/'
|
|
||||||
routerBasename: '/',
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
window.OHIFStandaloneViewer.installViewer(window.config);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ohif/viewer",
|
"name": "@ohif/viewer",
|
||||||
"version": "0.50.20",
|
"version": "1.3.0",
|
||||||
"description": "OHIF Viewer",
|
"description": "OHIF Viewer",
|
||||||
"author": "OHIF Contributors",
|
"author": "OHIF Contributors",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -18,7 +18,8 @@
|
|||||||
"proxy": "http://localhost:8042",
|
"proxy": "http://localhost:8042",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:package": "cross-env NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.commonjs.js",
|
"build:package": "cross-env NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.commonjs.js",
|
||||||
"build:viewer": "cross-env NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js",
|
"build:viewer": "cross-env NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js --progress",
|
||||||
|
"build:viewer:e2e": "cross-env NODE_ENV=development node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js --progress",
|
||||||
"build:viewer:ci": "cross-env NODE_ENV=production PUBLIC_URL=/pwa/ APP_CONFIG=config/netlify.js node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js",
|
"build:viewer:ci": "cross-env NODE_ENV=production PUBLIC_URL=/pwa/ APP_CONFIG=config/netlify.js node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js",
|
||||||
"build:viewer:demo": "cross-env NODE_ENV=production APP_CONFIG=config/demo.js HTML_TEMPLATE=rollbar.html node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --progress --config .webpack/webpack.pwa.js",
|
"build:viewer:demo": "cross-env NODE_ENV=production APP_CONFIG=config/demo.js HTML_TEMPLATE=rollbar.html node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --progress --config .webpack/webpack.pwa.js",
|
||||||
"build:viewer:package": "yarn run build:package",
|
"build:viewer:package": "yarn run build:package",
|
||||||
@@ -27,8 +28,13 @@
|
|||||||
"dev:viewer": "yarn run dev",
|
"dev:viewer": "yarn run dev",
|
||||||
"start": "yarn run dev",
|
"start": "yarn run dev",
|
||||||
"test:e2e": "cypress open",
|
"test:e2e": "cypress open",
|
||||||
|
"test:e2e:ci": "cypress run",
|
||||||
|
"test:e2e:dist": "start-server-and-test test:e2e:serve http://localhost:3000 test:e2e:ci",
|
||||||
|
"test:e2e:serve": "serve -l 3000 -s dist",
|
||||||
"test:unit": "jest --watchAll",
|
"test:unit": "jest --watchAll",
|
||||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage"
|
"test:unit:ci": "jest --ci --runInBand --collectCoverage",
|
||||||
|
"prepublishOnly": "yarn run build:package",
|
||||||
|
"postpublish": "node -p -e \"require('./package.json').version\" > success_version.txt"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
@@ -40,22 +46,22 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"@ohif/core": "^0.50.5",
|
"@ohif/core": "^1.0.1",
|
||||||
"@ohif/extension-cornerstone": "^0.50.5",
|
"@ohif/extension-cornerstone": "^2.0.0",
|
||||||
"@ohif/extension-dicom-html": "^0.50.4",
|
"@ohif/extension-dicom-html": "^1.0.0",
|
||||||
"@ohif/extension-dicom-microscopy": "^0.50.4",
|
"@ohif/extension-dicom-microscopy": "^0.50.6",
|
||||||
"@ohif/extension-dicom-pdf": "^0.50.3",
|
"@ohif/extension-dicom-pdf": "^1.0.0",
|
||||||
"@ohif/extension-vtk": "^0.50.7",
|
"@ohif/extension-vtk": "^0.51.0",
|
||||||
"@ohif/i18n": "^0.50.3",
|
"@ohif/i18n": "^0.50.4",
|
||||||
"@ohif/ui": "^0.50.4",
|
"@ohif/ui": "^0.52.0",
|
||||||
"@tanem/react-nprogress": "^1.1.25",
|
"@tanem/react-nprogress": "^1.1.25",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"core-js": "^3.2.1",
|
"core-js": "^3.2.1",
|
||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-math": "^0.1.8",
|
"cornerstone-math": "^0.1.8",
|
||||||
"cornerstone-tools": "^3.19.2",
|
"cornerstone-tools": "^4.0.9",
|
||||||
"cornerstone-wado-image-loader": "^3.0.0",
|
"cornerstone-wado-image-loader": "^3.0.0",
|
||||||
"dcmjs": "^0.4.7",
|
"dcmjs": "^0.6.1",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
"dicomweb-client": "^0.4.4",
|
"dicomweb-client": "^0.4.4",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ window.config = {
|
|||||||
qidoSupportsIncludeField: true,
|
qidoSupportsIncludeField: true,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ window.config = {
|
|||||||
qidoSupportsIncludeField: true,
|
qidoSupportsIncludeField: true,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ window.config = {
|
|||||||
qidoSupportsIncludeField: false,
|
qidoSupportsIncludeField: false,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,11 +14,10 @@ window.config = {
|
|||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
// REQUIRED TAG:
|
// REQUIRED TAG:
|
||||||
// TODO: Remove tag after https://github.com/OHIF/ohif-core/pull/19 is merged and we bump version
|
// TODO: Remove tag after https://github.com/OHIF/ohif-core/pull/19 is merged and we bump version
|
||||||
requestOptions: {
|
// requestOptions: {
|
||||||
// undefined to use JWT + Bearer auth
|
// undefined to use JWT + Bearer auth
|
||||||
// auth: 'orthanc:orthanc',
|
// auth: 'orthanc:orthanc',
|
||||||
requestFromBrowser: true,
|
// },
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,15 +12,11 @@ window.config = {
|
|||||||
qidoSupportsIncludeField: false,
|
qidoSupportsIncludeField: false,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
// REQUIRED TAG:
|
// requestOptions: {
|
||||||
// https://github.com/OHIF/ohif-core/blob/59e1e04b92be24aee5d4402445cb3dcedb746995/src/studies/retrieveStudyMetadata.js#L54
|
// undefined to use JWT + Bearer auth
|
||||||
// TODO: Remove tag after https://github.com/OHIF/ohif-core/pull/19 is merged and we bump version
|
// auth: 'orthanc:orthanc',
|
||||||
requestOptions: {
|
// },
|
||||||
// undefined to use JWT + Bearer auth
|
|
||||||
// auth: 'orthanc:orthanc',
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
@@ -14,11 +14,10 @@ window.config = {
|
|||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
requestOptions: {
|
||||||
requestFromBrowser: true,
|
|
||||||
auth: 'admin:admin',
|
auth: 'admin:admin',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
studyListFunctionsEnabled: true,
|
studyListFunctionsEnabled: true,
|
||||||
}
|
};
|
||||||
@@ -11,9 +11,6 @@ window.config = {
|
|||||||
qidoSupportsIncludeField: true,
|
qidoSupportsIncludeField: true,
|
||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
requestOptions: {
|
|
||||||
requestFromBrowser: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
Loaded 100 of 126 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user