Compare commits

..
Author SHA1 Message Date
dannyrb a6c0be0797 chore(release): publish %s [skip ci]
- @ohif/extension-cornerstone@0.0.39-alpha.2
 - @ohif/extension-dicom-html@0.0.4-alpha.2
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.2
 - @ohif/extension-dicom-pdf@0.0.8-alpha.2
 - @ohif/extension-vtk@0.1.4-alpha.2
 - @ohif/core@0.11.1-alpha.2
 - @ohif/i18n@0.2.3-alpha.2
 - @ohif/ui@0.2.18-alpha.2
 - @ohif/viewer@0.0.22-alpha.3
2019-08-07 16:25:22 -04:00
dannyrb f421d16e85 catch changes 2019-08-07 16:09:59 -04:00
dannyrb a5baa9228c Fix build scripts 2019-08-07 16:06:44 -04:00
dannyrb 23372fbfbd Update package.jsons 2019-08-07 16:05:24 -04:00
dannyrb d9d9aa1728 test lerna publish 2019-08-07 15:50:20 -04:00
dannyrb b1657ac1ef chore(release): publish %s [skip ci]
- @ohif/viewer@0.0.22-alpha.2
2019-08-07 15:47:58 -04:00
dannyrb ea45681d00 Add global prettier config 2019-08-07 15:22:39 -04:00
dannyrb a97bd302f7 test version bump 2019-08-07 15:22:26 -04:00
dannyrb e1542f50f8 chore(release): publish %s [skip ci]
- @ohif/extension-cornerstone@0.0.39-alpha.1
 - @ohif/extension-dicom-html@0.0.4-alpha.1
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.1
 - @ohif/extension-dicom-pdf@0.0.8-alpha.1
 - @ohif/extension-vtk@0.1.4-alpha.1
 - @ohif/core@0.11.1-alpha.1
 - @ohif/i18n@0.2.3-alpha.1
 - @ohif/ui@0.2.18-alpha.1
 - @ohif/viewer@0.0.22-alpha.1
2019-08-07 00:32:04 -04:00
dannyrb abdbe9a608 Safer publish command 2019-08-07 00:24:27 -04:00
dannyrb 755da173ea ohif-core --> @ohif/core 2019-08-06 23:56:44 -04:00
dannyrb 8c5bd55f88 Remove unused/duplicate config files for projects/packages 2019-08-06 23:48:43 -04:00
dannyrb e98611fc24 Redux testkit dep 2019-08-06 23:21:19 -04:00
dannyrb fa0aa7f68e bump @ohif/core versions 2019-08-06 15:48:33 -04:00
dannyrb 30902bc048 Fix @ohif/ui versions 2019-08-06 15:37:44 -04:00
dannyrb 4b532183af Reduce duplicate code in @ohif/core 2019-08-06 15:03:43 -04:00
dannyrb 58b3727a2e Clean up ui and i18n config 2019-08-06 14:41:13 -04:00
dannyrb d48e29d1bb Update UI project's docs 2019-08-06 14:31:01 -04:00
dannyrb e47dcf27fc Clean duplicate code in UI project 2019-08-06 14:22:44 -04:00
dannyrb 60f48fbdc0 Tidy up project links 2019-08-06 13:58:43 -04:00
dannyrb 9a5372766c Clean up UI to set webpack scripts 2019-08-05 23:34:02 -04:00
dannyrb e0cf337222 Remove old scripts 2019-08-05 23:28:12 -04:00
dannyrb 7db3bde95a Shift build command; satisfy default PWA build 2019-08-05 23:26:28 -04:00
dannyrb b081e73297 Support for dev and dev:* commands 2019-08-05 23:15:07 -04:00
dannyrb ce72d8bb15 Clean up primary readme 2019-08-05 22:32:36 -04:00
dannyrb 7ba2916cf5 chore(release): publish %s [skip ci]
- @ohif/extension-cornerstone@0.0.39-alpha.0
 - @ohif/extension-dicom-html@0.0.4-alpha.0
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.0
 - @ohif/extension-dicom-pdf@0.0.8-alpha.0
 - @ohif/extension-vtk@0.1.4-alpha.0
 - @ohif/core@0.11.1-alpha.0
 - @ohif/i18n@0.2.3-alpha.0
 - @ohif/ui@0.2.18-alpha.0
 - @ohif/viewer@0.0.22-alpha.0
2019-08-05 14:45:09 -04:00
dannyrb 4736ad5620 Catch more updates 2019-08-05 14:44:45 -04:00
dannyrb 44f562e24c Adding note 2019-08-05 14:44:20 -04:00
dannyrb 8683e1e8ff Changing to scoped package names 2019-08-05 14:29:14 -04:00
dannyrb f86eb5e8f2 Fix typo 2019-08-05 14:00:20 -04:00
dannyrb 64fd724455 Set default threshold 2019-08-05 13:52:02 -04:00
dannyrb b2dfb6e0f7 Fix path; split PR and Merge unit tests into separate jobs 2019-08-05 13:04:27 -04:00
dannyrb 7c043b46b4 Try running with aliased folder 2019-08-05 12:54:23 -04:00
dannyrb 62932b3e80 Also upload core 2019-08-05 12:49:35 -04:00
dannyrb 7a7b2774e6 Try to see the contents of our cat'd file 2019-08-05 12:41:42 -04:00
dannyrb 1556b3bbf8 Fix filename 2019-08-05 12:37:01 -04:00
dannyrb 199db68674 Use home alias 2019-08-05 12:35:13 -04:00
dannyrb d74b6fb826 long paths 2019-08-05 12:30:27 -04:00
dannyrb aeac900496 Combine lines to reduce path 2019-08-05 12:26:29 -04:00
dannyrb 835fec7f32 Escape string literal 2019-08-05 12:23:10 -04:00
dannyrb 4c202ed064 tryfix syntax 2019-08-05 12:21:39 -04:00
dannyrb e751e8fab8 Escape anchors 2019-08-05 12:12:27 -04:00
dannyrb ae795ea97d Combine files before upload 2019-08-05 12:08:18 -04:00
dannyrb d90c70cab5 Fix dir 2019-08-05 11:52:35 -04:00
dannyrb 1a8fd13896 Remove individual codecov calls 2019-08-05 11:52:09 -04:00
dannyrb 0026801b62 Use full string paths 2019-08-05 11:43:03 -04:00
dannyrb 395315ea4c Upload core and viewer 2019-08-05 11:39:10 -04:00
dannyrb 4664f673d6 Bump circleci version 2019-08-05 11:32:38 -04:00
dannyrb a8c4534b33 Try using codecov orb 2019-08-05 11:07:14 -04:00
dannyrb e4a3510c86 Simplify 2019-08-02 13:33:21 -04:00
dannyrb d28f332312 Try fixing paths 2019-08-02 13:04:03 -04:00
dannyrb 37f60ba0af Generate example for codecov issue 2019-07-19 14:54:34 -04:00
dannyrb d64cdc429e Shift back to calling codecov from root 2019-07-18 15:05:52 -04:00
dannyrb e06e8304d3 Remove clear flag 2019-07-18 14:26:47 -04:00
dannyrb 0e862c69db Fix typo 2019-07-18 13:57:14 -04:00
dannyrb fbdb61bcb2 Use recommended flags from issue comments for codecov 2019-07-18 13:52:27 -04:00
dannyrb 3acea218fb Trigger codecov after everything has finished running; these may not support flags 2019-07-18 13:40:31 -04:00
dannyrb a521ce31ce Generate separate reports 2019-07-18 13:07:29 -04:00
dannyrb 67e2fd39a3 Add projects to split by flags 2019-07-18 12:53:24 -04:00
dannyrb 253620650b Try once relying on codecov yaml to split w/ flags 2019-07-18 12:43:03 -04:00
dannyrb 31357ea9b5 Run and report individually and in parallel 2019-07-18 10:26:33 -04:00
dannyrb b8baae7c25 Get all platform unit tests to run 2019-07-17 14:57:50 -04:00
dannyrb 5544c57c37 Use cpx so our copying finishes? 2019-07-16 14:58:40 -04:00
dannyrb 6b523cb50d Add codecov flags 2019-07-16 14:51:04 -04:00
dannyrb 579c2b41d1 Set path and enable workspaces 2019-07-16 14:27:22 -04:00
dannyrb 9449ae4314 Try alternative jest transform 2019-07-16 14:23:41 -04:00
dannyrb 4386b5c960 Run version command instead of calling node directly 2019-07-16 14:14:34 -04:00
dannyrb fe3ee3010f Try alternative jest-canvas-mock location and version file syntax 2019-07-16 14:06:02 -04:00
dannyrb ee5530183e Lower version to match circleci image 2019-07-16 13:43:55 -04:00
dannyrb 413214786d Change copy syntax; try running tests on viewers from root for circleci 2019-07-16 13:31:52 -04:00
dannyrb 0b62b720c5 Attempt to fix ticks/escapes 2019-07-16 13:24:46 -04:00
dannyrb c3fead1ca9 We need to pull cornerstone-wado-image-loader files from hoisted node_modules 2019-07-16 13:11:16 -04:00
dannyrb bc8d505a0a We may have figured it out johnny, boy 2019-07-16 12:57:37 -04:00
dannyrb ab4067144f and again 2019-07-16 12:50:33 -04:00
dannyrb 575d11ac5b Annd let's try again 2019-07-16 12:42:40 -04:00
dannyrb aa53d3258c Try bash -l instead of exec bash 2019-07-16 12:19:51 -04:00
dannyrb dc672bf38d Try swapping bash with a new shell 2019-07-16 12:11:21 -04:00
dannyrb 65a855d99b try again to set bin path 2019-07-16 11:12:19 -04:00
dannyrb 99c1d0220d Follow deploy log output advice 2019-07-16 10:43:01 -04:00
dannyrb dab0b5e0e3 More agressive with modifying PATH 2019-07-16 10:35:06 -04:00
dannyrb ea3f7d5657 Export node_modules path 2019-07-16 10:01:33 -04:00
dannyrb 3c812792bb Try to use global gitbook-cli 2019-07-16 09:55:34 -04:00
dannyrb ff21408440 push workspace enabled to initial command; remove second yarn install; use npx to call gitbook cli commands 2019-07-16 09:42:43 -04:00
dannyrb fd720bd4d7 Attempt to fix deploy preview build 2019-07-16 09:32:14 -04:00
dannyrb 2279e555a3 First attempt at a netlify deploy preview 2019-07-16 09:24:24 -04:00
dannyrb 91ee615aee Shift links to bottom of doc 2019-07-15 15:56:07 -04:00
dannyrb f8d9bbef8a Rename example extension folder 2019-07-15 15:51:36 -04:00
dannyrb 4fcf544abe Begin providing basic readme info 2019-07-15 15:51:24 -04:00
dannyrb 2ba0e95fe8 Specify additional lerna config props 2019-07-15 15:51:10 -04:00
dannyrb 91564bfa06 Shift docs to root 2019-07-15 15:50:47 -04:00
dannyrb 83e627e5c9 Fix ESM symlink build for Viewers 2019-07-15 13:03:29 -04:00
dannyrb 2fbbb4a8e2 Push changes up to switch PCs 2019-07-11 13:12:37 -04:00
dannyrb c05058a0f5 Better entrypoint for extensions 2019-07-09 12:56:08 -04:00
dannyrb 2429294dda Provide WebPack build options for microscopy, vtk, and ui 2019-07-09 12:39:15 -04:00
dannyrb 2234869b11 Add Webpack Stylus loader 2019-07-09 12:38:12 -04:00
dannyrb 96686850cb Target for UMD bundle 2019-07-09 12:37:58 -04:00
dannyrb 35dc82e120 Resolve viewer's modules 2019-07-09 12:37:02 -04:00
dannyrb f5d6674b62 Make it possible to pass in extensions as App props 2019-07-08 10:18:03 -04:00
dannyrb f3009c7a45 Consolidate how/where we specify file/module type entrypoints 2019-07-08 09:38:16 -04:00
dannyrb e8969fba11 Split packages into platform and extensions 2019-07-08 00:41:25 -04:00
dannyrb f175d4b96b Commit changes before a long weekend 2019-07-05 22:58:25 -04:00
dannyrb e250ac0c50 Begin updating dependent libraries to use sync'd webpack builds w/ watches 2019-07-05 13:28:49 -04:00
dannyrb 3e1e456cc2 Move @babel dependencies up to workspace root 2019-07-04 20:35:30 -04:00
dannyrb e58ba39a60 more shifting 2019-07-04 16:19:28 -04:00
dannyrb b73ea99971 init 2019-07-04 16:12:43 -04:00
297 changed files with 25108 additions and 8378 deletions

No files matched your search

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