Refactor extensions interface (#344)
* Added container class for plugins that care for registration of submodules * Added extensions manager that cares for adding modules to store * Make extensions require less knowledge of internal extension management * Reformatting * Update generateStaticSite to use ohif-viewer, remove old OHIFViewer-react folder * Add yarn.lock so Netlify knows to use Yarn * Fix for copying static site folder * Try to fix netlify build which is stuck uploading * Try to fix static site deployment * Try to fix static site deployment again * Try to fix static site deployment one more time * Extracted pdf plugin into external package * Removed some unused dependencies * Published pdf extension to npm registry * Added external microscopy extension (work in progress) * Extraction of microscopy plugin working now * Added microscopy extension npm package to package.json * Increase ohif-core version * update yarn.lock * Fix error in readme * Fix authentication error in pdf plugin * Remove readme, update packages, add redirect for netlify * netlify test * netlify test 2 * netlify test 2, forgot to add new redirects file * Use public dicom server for demo * Another netlify try * Another netlify try 2 * Another netlify try 3 * Another netlify try 4
This commit is contained in:
parent
af68db0c09
commit
b93a677ef3
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,5 +9,5 @@ npm-debug.log
|
||||
Packages/active-entry/helloworld/
|
||||
LesionTracker/tests/nightwatch/reports/
|
||||
docs/_book
|
||||
OHIFViewer-react/build/
|
||||
.DS_Store
|
||||
**/.history/*
|
||||
|
||||
3
OHIFViewer-react/.gitignore
vendored
3
OHIFViewer-react/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
src/sha.js
|
||||
src/version.js
|
||||
yarn-error.log
|
||||
File diff suppressed because it is too large
Load Diff
23768
OHIFViewer-react/package-lock.json
generated
23768
OHIFViewer-react/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,57 +0,0 @@
|
||||
{
|
||||
"name": "OHIFViewer",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"homepage": "http://localhost:5000/",
|
||||
"dependencies": {
|
||||
"cornerstone-core": "2.2.8",
|
||||
"cornerstone-math": "0.1.8",
|
||||
"cornerstone-tools": "3.0.0-b.1512",
|
||||
"cornerstone-wado-image-loader": "2.2.3",
|
||||
"dicom-parser": "1.8.3",
|
||||
"dicomweb-client": "^0.4.1",
|
||||
"hammerjs": "^2.0.8",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"moment": "^2.22.2",
|
||||
"ohif-core": "^0.1.8",
|
||||
"ohif-viewer": "0.0.5",
|
||||
"oidc-client": "^1.6.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"query-string": "^6.2.0",
|
||||
"react": "^16.7.0",
|
||||
"react-cornerstone-viewport": "^0.1.8",
|
||||
"react-dom": "^16.4.1",
|
||||
"react-redux": "^6.0.0",
|
||||
"react-router": "^4.3.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-scripts": "^2.1.3",
|
||||
"react-viewerbase": "^0.2.4",
|
||||
"react-vtkjs-viewport": "^0.0.1",
|
||||
"redux": "^4.0.1",
|
||||
"redux-oidc": "^3.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"copy:webworkers": "cp node_modules/cornerstone-wado-image-loader/dist/*.min.js* public",
|
||||
"version": "node -p -e \"'export default \\'' + require('./package.json').version + '\\';'\" > src/version.js",
|
||||
"sha": "echo \"export default '\"$(git rev-parse HEAD)\"';\" > src/sha.js",
|
||||
"details": "npm run version && npm run sha",
|
||||
"prep": "npm run details && npm run copy:webworkers",
|
||||
"start": "npm run prep && react-scripts start",
|
||||
"build": "npm run prep && react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.2.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.2.3",
|
||||
"husky": "^1.3.1"
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
12
OHIFViewer-react/public/es6-shim.min.js
vendored
12
OHIFViewer-react/public/es6-shim.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,237 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<symbol id="icon-hud" viewBox="0 0 20 22">
|
||||
<title>HUD</title>
|
||||
<g id="icon-hud-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path id="icon-hud-dashes" d="m14.5,2.75 2,0 a2.5 2.5 0 0 1 2.5 2.5 l0,13.25 a2.5 2.5 0 0 1 -2.5 2.5 l-11.5,0 a2.5 2.5 0 0 1 -2.5 -2.5 l0,-1" stroke-dasharray="1,3" />
|
||||
<path id="icon-hud-box" d="m0.5,2 0,14 a1.5 1.5 0 0 0 1.5 1.5 l12,0 a1.5 1.5 0 0 0 1.5 -1.5 l0,-14" />
|
||||
<path id="icon-hud-top" d="m2,2 12,0" stroke-width="4" />
|
||||
<path id="icon-hud-paralel" d="m4.4,7.5 7.2,0 m0,3 -7.2,0 m0,3 7.2,0" stroke-linecap="square" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-measurements-additional" viewBox="0 0 16 16">
|
||||
<title>Additional Measurements</title>
|
||||
<g id="icon-measurements-additional-group" stroke="none">
|
||||
<path id="icon-measurements-additional-boxes" d="M11,2 l1.85,-1.85 a1 1 0 0 1 1,0 l2,2 a1 1 0 0 1 0,1 l-1.85,1.85Z M10,3 l-10,10 0,3 3,0 10,-10Z M16,16 l0,-2 -9,0 -2,2Z" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-measurements-lesions" viewBox="0 0 18 10">
|
||||
<title>Lesions</title>
|
||||
<g id="icon-measurements-lesions-group" stroke="none">
|
||||
<path id="icon-measurements-lesions-boxes" d="M0,0 2,0 2,2 0,2Z M4,0 18,0 18,2 4,2Z M0,4 2,4 2,6 0,6Z M4,4 18,4 18,6 4,6Z M0,8 2,8 2,10 0,10Z M4,8 18,8 18,10 4,10Z" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-settings" viewBox="0 0 15 15">
|
||||
<title>Settings</title>
|
||||
<path d="M12.85 8.25C12.85 8.03 12.93 7.8 12.93 7.5 12.93 7.2 12.93 6.98 12.85 6.75L14.43 5.48C14.58 5.33 14.58 5.18 14.5 5.03L13 2.4C12.93 2.33 12.78 2.25 12.55 2.33L10.68 3.08C10.3 2.78 9.85 2.55 9.4 2.33L9.1 0.38C9.18 0.15 8.95 0 8.8 0L5.8 0C5.65 0 5.43 0.15 5.43 0.3L5.13 2.33C4.68 2.48 4.3 2.78 3.85 3.08L2.05 2.33C1.83 2.25 1.68 2.33 1.53 2.48L0.03 5.1C-0.05 5.18 0.03 5.4 0.18 5.55L1.75 6.75C1.75 6.98 1.68 7.2 1.68 7.5 1.68 7.8 1.68 8.03 1.75 8.25L0.18 9.53C0.03 9.68 0.03 9.82 0.1 9.98L1.6 12.6C1.68 12.68 1.83 12.75 2.05 12.68L3.93 11.93C4.3 12.23 4.75 12.45 5.2 12.68L5.5 14.63C5.5 14.78 5.65 14.93 5.88 14.93L8.88 14.93C9.03 14.93 9.25 14.78 9.25 14.63L9.55 12.68C10 12.45 10.45 12.23 10.83 11.93L12.7 12.68C12.85 12.75 13.08 12.68 13.15 12.53L14.65 9.9C14.73 9.75 14.73 9.53 14.58 9.45L12.85 8.25 12.85 8.25ZM7.3 10.13C5.88 10.13 4.68 8.93 4.68 7.5 4.68 6.08 5.88 4.88 7.3 4.88 8.73 4.88 9.93 6.08 9.93 7.5 9.93 8.93 8.73 10.13 7.3 10.13L7.3 10.13Z" id="Shape"/>
|
||||
</symbol>
|
||||
<symbol id="icon-status-complete" viewBox="0 0 27 27">
|
||||
<title>Complete</title>
|
||||
<g id="icon-status-complete-group" stroke="none">
|
||||
<path id="icon-status-complete-circle" d="M13.5,0 a13.5 13.5 0 0 1 0 27 a13.5 13.5 0 0 1 0 -27 M23,8 l-2,-2 -10,10, -5,-5 -2,2 7,7Z" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-status-lock" viewBox="0 0 16 21">
|
||||
<title>Locked</title>
|
||||
<path d="M14 7L13 7 13 5C13 2.2 10.8 0 8 0 5.2 0 3 2.2 3 5L3 7 2 7C0.9 7 0 7.9 0 9L0 19C0 20.1 0.9 21 2 21L14 21C15.1 21 16 20.1 16 19L16 9C16 7.9 15.1 7 14 7L14 7ZM11.1 7L4.9 7 4.9 5C4.9 3.3 6.3 1.9 8 1.9 9.7 1.9 11.1 3.3 11.1 5L11.1 7 11.1 7Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-studies" viewBox="0 0 15 13">
|
||||
<title>Studies</title>
|
||||
<g id="icon-studies-group" stroke="none">
|
||||
<path id="icon-studies-boxes" d="M0,0 7,0 7,6 0,6Z M8,0 15,0 15,6 8,6Z M0,7 7,7 7,13 0,13Z M8,7 15,7 15,13 8,13Z" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-levels" viewBox="0 0 18 18">
|
||||
<title>Window / Level</title>
|
||||
<g id="icon-tools-levels-group">
|
||||
<path id="icon-tools-levels-path" d="M14.5,3.5 a1 1 0 0 1 -11,11 Z" stroke="none" opacity="0.8" />
|
||||
<circle id="icon-tools-levels-circle" cx="9" cy="9" r="8" fill="none" stroke-width="2" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-link" viewBox="0 0 23 15">
|
||||
<title>Link</title>
|
||||
<g id="icon-tools-link-group" stroke="none">
|
||||
<circle id="icon-tools-link-circle-l" opacity="0.8" cx="7.5" cy="7.5" r="7.5" />
|
||||
<circle id="icon-tools-link-circle-r" opacity="0.6" cx="15.5" cy="7.5" r="7.5" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-non-target" viewBox="0 0 24 24">
|
||||
<title>Non-Target Measurement</title>
|
||||
<g id="icon-tools-measure-non-target-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle id="icon-tools-measure-non-target-circle" cx="6.5" cy="6.5" r="6" />
|
||||
<path id="icon-tools-measure-non-target-plus" d="M6.5,3 l0,7 M3,6.5 l7,0"></path>
|
||||
<path id="icon-tools-measure-non-target-arrow" d="M23,7 l-15,15 M7,17 l0,6 6,0" stroke-width="2" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-target" viewBox="0 0 26 26">
|
||||
<title>Target Measurement</title>
|
||||
<g id="icon-tools-measure-target-group" stroke-width="0">
|
||||
<path id="icon-tools-measure-target-ruler" d="m9.5,26 2,-2 -1.5,-1.5 0.5,-0.5 1.5,1.5 1.5,-1.5 -2.5,-2.5 0.5,-0.5 2.5,2.5 1.5,-1.5 -1.5,-1.5 0.5,-0.5 1.5,1.5 1.5,-1.5 -2.5,-2.5 0.5,-0.5 2.5,2.5 1.5,-1.5 -1.5,-1.5 0.5,-0.5 1.5,1.5 1.5,-1.5 -2.5,-2.5 0.5,-0.5 2.5,2.5 1.5,-1.5 -1.5,-1.5 0.5,-0.5 1.5,1.5 2,-2 -4,-4 a2 2 0 0 0 -2.5 0 l-14 14 a2 2 0 0 0 0 2.5 l4,4 Z" />
|
||||
<path id="icon-tools-measure-target-plus" d="m6,0 a6 6 0 0 1 0 12 a6 6 0 0 1 0 -12 m0.5,3 a0.5 0.5 0 0 0 -1 0 l0,2.5 -2.5,0 a0.5 0.5 0 0 0 0 1 l2.5,0 0,2.5 a0.5 0.5 0 0 0 1 0 l0,-2.5 2.5,0 a0.5 0.5 0 0 0 0 -1 l-2.5,0 z" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-target-cr" viewBox="0 0 24 24">
|
||||
<title>Target CR Measurement</title>
|
||||
<g id="icon-tools-measure-target-cr-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<text id="icon-tools-measure-target-cr-text" fill="#000000" x="0" y="8" style="font-size:10px; font-family:sans-serif">CR</text>
|
||||
<path id="icon-tools-measure-target-cr-arrow" d="M23,7 l-15,15 M7,17 l0,6 6,0" stroke-width="2" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-target-un" viewBox="0 0 24 24">
|
||||
<title>Target UN Measurement</title>
|
||||
<g id="icon-tools-measure-target-un-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<text id="icon-tools-measure-target-un-text" fill="#000000" x="0" y="8" style="font-size:10px; font-family:sans-serif">UN</text>
|
||||
<path id="icon-tools-measure-target-un-arrow" d="M23,7 l-15,15 M7,17 l0,6 6,0" stroke-width="2" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-temp" viewBox="0 0 24 24">
|
||||
<title>Temporary Measurement</title>
|
||||
<g id="icon-tools-measure-temp-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle id="icon-tools-measure-temp-circle" cx="6.5" cy="6.5" r="6" />
|
||||
<path id="icon-tools-measure-temp-plus" d="M6.5,3 l0,7 M3,6.5 l7,0"></path>
|
||||
<path id="icon-tools-measure-temp-dashes" d="m22.5,6 -16.5,16.5" stroke-width="3" stroke-dasharray="0.6666,5" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-more" viewBox="0 0 18 18">
|
||||
<title>More</title>
|
||||
<g id="icon-tools-more-group" stroke="none">
|
||||
<path id="icon-tools-more-circle" d="M9,0 a9 9 0 0 1 0 18 a9 9 0 0 1 0 -18 M4.5,8 a1.5 1.5 0 0 0 0 3 a1.5 1.5 0 0 0 0 -3 M9,8 a1.5 1.5 0 0 0 0 3 a1.5 1.5 0 0 0 0 -3 M13.5,8 a1.5 1.5 0 0 0 0 3 a1.5 1.5 0 0 0 0 -3" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-pan" viewBox="0 0 18 18">
|
||||
<title>Pan</title>
|
||||
<g id="icon-tools-pan-group" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path id="icon-tools-pan-line-v" d="M9,1 L9,17"></path>
|
||||
<path id="icon-tools-pan-line-h" d="M1,9 L17,9"></path>
|
||||
<polyline id="icon-tools-pan-caret-t" points="7 3 9 1 11 3"></polyline>
|
||||
<polyline id="icon-tools-pan-caret-r" points="15 11 17 9 15 7"></polyline>
|
||||
<polyline id="icon-tools-pan-caret-b" points="11 15 9 17 7 15"></polyline>
|
||||
<polyline id="icon-tools-pan-caret-l" points="3 7 1 9 3 11"></polyline>
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-zoom" viewBox="0 0 17 17">
|
||||
<title>Zoom</title>
|
||||
<g id="icon-tools-zoom-group" fill="none" stroke-width="2" stroke-linecap="round">
|
||||
<path id="icon-tools-zoom-path" d="m11.5,11.5 4.5,4.5" />
|
||||
<circle id="icon-tools-zoom-circle" cx="7" cy="7" r="6" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-invert" viewBox="0 0 24 28">
|
||||
<title>Invert</title>
|
||||
<path d="M12 22.5v-17c-4.688 0-8.5 3.813-8.5 8.5s3.813 8.5 8.5 8.5zM24 14c0 6.625-5.375 12-12 12s-12-5.375-12-12 5.375-12 12-12 12 5.375 12 12z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-stack-scroll" viewBox="0 0 24 28">
|
||||
<title>Stack Scroll</title>
|
||||
<path d="M24 21v2c0 0.547-0.453 1-1 1h-22c-0.547 0-1-0.453-1-1v-2c0-0.547 0.453-1 1-1h22c0.547 0 1 0.453 1 1zM24 13v2c0 0.547-0.453 1-1 1h-22c-0.547 0-1-0.453-1-1v-2c0-0.547 0.453-1 1-1h22c0.547 0 1 0.453 1 1zM24 5v2c0 0.547-0.453 1-1 1h-22c-0.547 0-1-0.453-1-1v-2c0-0.547 0.453-1 1-1h22c0.547 0 1 0.453 1 1z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-elliptical-roi" viewBox="0 0 24 28">
|
||||
<title>Elliptical ROI</title>
|
||||
<path d="M12 5.5c-4.688 0-8.5 3.813-8.5 8.5s3.813 8.5 8.5 8.5 8.5-3.813 8.5-8.5-3.813-8.5-8.5-8.5zM24 14c0 6.625-5.375 12-12 12s-12-5.375-12-12 5.375-12 12-12v0c6.625 0 12 5.375 12 12z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-magnify" viewBox="0 0 24 28">
|
||||
<title>Magnify</title>
|
||||
<path d="M24 14c0 6.625-5.375 12-12 12s-12-5.375-12-12 5.375-12 12-12 12 5.375 12 12z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-reset" viewBox="0 0 24 28">
|
||||
<title>Reset</title>
|
||||
<path d="M24 14c0 6.609-5.391 12-12 12-3.578 0-6.953-1.578-9.234-4.328-0.156-0.203-0.141-0.5 0.031-0.672l2.141-2.156c0.109-0.094 0.25-0.141 0.391-0.141 0.141 0.016 0.281 0.078 0.359 0.187 1.531 1.984 3.828 3.109 6.312 3.109 4.406 0 8-3.594 8-8s-3.594-8-8-8c-2.047 0-3.984 0.781-5.437 2.141l2.141 2.156c0.297 0.281 0.375 0.719 0.219 1.078-0.156 0.375-0.516 0.625-0.922 0.625h-7c-0.547 0-1-0.453-1-1v-7c0-0.406 0.25-0.766 0.625-0.922 0.359-0.156 0.797-0.078 1.078 0.219l2.031 2.016c2.203-2.078 5.187-3.313 8.266-3.313 6.609 0 12 5.391 12 12z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-rotate" viewBox="0 0 24 28">
|
||||
<title>Rotate</title>
|
||||
<path d="M24 4v7c0 0.547-0.453 1-1 1h-7c-0.406 0-0.766-0.25-0.922-0.625-0.156-0.359-0.078-0.797 0.219-1.078l2.156-2.156c-1.469-1.359-3.406-2.141-5.453-2.141-4.406 0-8 3.594-8 8s3.594 8 8 8c2.484 0 4.781-1.125 6.312-3.109 0.078-0.109 0.219-0.172 0.359-0.187 0.141 0 0.281 0.047 0.391 0.141l2.141 2.156c0.187 0.172 0.187 0.469 0.031 0.672-2.281 2.75-5.656 4.328-9.234 4.328-6.609 0-12-5.391-12-12s5.391-12 12-12c3.078 0 6.062 1.234 8.266 3.313l2.031-2.016c0.281-0.297 0.719-0.375 1.094-0.219 0.359 0.156 0.609 0.516 0.609 0.922z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-rotate-right" viewBox="0 0 24 24">
|
||||
<title>Rotate Right</title>
|
||||
<path d="M16.875 15.469c0.563-0.75 0.891-1.594 1.031-2.484h2.016c-0.188 1.406-0.703 2.719-1.594 3.891zM12.984 17.906c0.891-0.141 1.734-0.469 2.484-1.031l1.453 1.453c-1.172 0.891-2.531 1.406-3.938 1.594v-2.016zM19.922 11.016h-2.016c-0.141-0.891-0.469-1.734-1.031-2.484l1.453-1.406c0.891 1.172 1.406 2.484 1.594 3.891zM15.563 5.531l-4.547 4.453v-3.891c-2.859 0.469-5.016 2.953-5.016 5.906s2.156 5.438 5.016 5.906v2.016c-3.938-0.469-7.031-3.844-7.031-7.922s3.094-7.453 7.031-7.922v-3.094z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-cineplay-toggle" viewBox="0 0 28 28">
|
||||
<title>Cineplay Toggle</title>
|
||||
<path d="M11.109 17.625l7.562-3.906-7.562-3.953v7.859zM14 4.156c5.891 0 9.797 0.281 9.797 0.281 0.547 0.063 1.75 0.063 2.812 1.188 0 0 0.859 0.844 1.109 2.781 0.297 2.266 0.281 4.531 0.281 4.531v2.125s0.016 2.266-0.281 4.531c-0.25 1.922-1.109 2.781-1.109 2.781-1.062 1.109-2.266 1.109-2.812 1.172 0 0-3.906 0.297-9.797 0.297v0c-7.281-0.063-9.516-0.281-9.516-0.281-0.625-0.109-2.031-0.078-3.094-1.188 0 0-0.859-0.859-1.109-2.781-0.297-2.266-0.281-4.531-0.281-4.531v-2.125s-0.016-2.266 0.281-4.531c0.25-1.937 1.109-2.781 1.109-2.781 1.062-1.125 2.266-1.125 2.812-1.188 0 0 3.906-0.281 9.797-0.281v0z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-flip-vertical" viewBox="0 0 6 28">
|
||||
<title>Vertical</title>
|
||||
<path d="M6 19.5v3c0 0.828-0.672 1.5-1.5 1.5h-3c-0.828 0-1.5-0.672-1.5-1.5v-3c0-0.828 0.672-1.5 1.5-1.5h3c0.828 0 1.5 0.672 1.5 1.5zM6 11.5v3c0 0.828-0.672 1.5-1.5 1.5h-3c-0.828 0-1.5-0.672-1.5-1.5v-3c0-0.828 0.672-1.5 1.5-1.5h3c0.828 0 1.5 0.672 1.5 1.5zM6 3.5v3c0 0.828-0.672 1.5-1.5 1.5h-3c-0.828 0-1.5-0.672-1.5-1.5v-3c0-0.828 0.672-1.5 1.5-1.5h3c0.828 0 1.5 0.672 1.5 1.5z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-flip-horizontal" viewBox="0 0 22 28">
|
||||
<title>Horizontal</title>
|
||||
<path d="M6 11.5v3c0 0.828-0.672 1.5-1.5 1.5h-3c-0.828 0-1.5-0.672-1.5-1.5v-3c0-0.828 0.672-1.5 1.5-1.5h3c0.828 0 1.5 0.672 1.5 1.5zM14 11.5v3c0 0.828-0.672 1.5-1.5 1.5h-3c-0.828 0-1.5-0.672-1.5-1.5v-3c0-0.828 0.672-1.5 1.5-1.5h3c0.828 0 1.5 0.672 1.5 1.5zM22 11.5v3c0 0.828-0.672 1.5-1.5 1.5h-3c-0.828 0-1.5-0.672-1.5-1.5v-3c0-0.828 0.672-1.5 1.5-1.5h3c0.828 0 1.5 0.672 1.5 1.5z"></path>
|
||||
</symbol>
|
||||
<symbol id="icon-trial-info" viewBox="0 0 20 20">
|
||||
<title>Trial Information</title>
|
||||
<g id="icon-trial-info-group" fill="none" stroke-width="2">
|
||||
<path id="icon-trial-info-circle" d="M10,1 a9 9 0 0 1 0 18 a9 9 0 0 1 0 -18 M10,5 l0,2 m0,2 0,6" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-ui-accordion-expand" viewBox="0 0 12 8">
|
||||
<title>Expand</title>
|
||||
<polygon transform="translate(6.000000, 3.700000) rotate(-270.000000) translate(-6.000000, -3.700000) " points="3.7 -2.3 2.3 -0.9 6.9 3.7 2.3 8.3 3.7 9.7 9.7 3.7"/>
|
||||
</symbol>
|
||||
<symbol id="icon-ui-add" viewBox="0 0 12 13">
|
||||
<title>Add</title>
|
||||
<path d="M6.5 7L6.5 12C6.5 12.28 6.28 12.5 6 12.5 5.72 12.5 5.5 12.28 5.5 12L5.5 7 0.5 7C0.22 7 0 6.78 0 6.5 0 6.22 0.22 6 0.5 6L5.5 6 5.5 1C5.5 0.72 5.72 0.5 6 0.5 6.28 0.5 6.5 0.72 6.5 1L6.5 6 11.5 6C11.78 6 12 6.22 12 6.5 12 6.78 11.78 7 11.5 7L6.5 7Z" id="Combined-Shape"/>
|
||||
</symbol>
|
||||
<symbol id="icon-ui-close" viewBox="0 0 14 14">
|
||||
<title>Close</title>
|
||||
<g id="icon-ui-close-group" stroke-width="1.75">
|
||||
<path id="icon-ui-close-path" d="M1,1 13,13 M1,13 13,1" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-create-comment" viewBox="0 0 37 34">
|
||||
<title>Comment</title>
|
||||
<path fill="#94a8b3" d="M22.32 14L35 14C36.1 14 37 14.9 37 16L37 28C37 29.1 36.1 30 35 30L21 30 17 34 17 20.39C19.45 18.97 21.36 16.71 22.32 14Z" id="Combined-Shape"/>
|
||||
<path d="M10 0C4.5 0 0 4.5 0 10 0 15.5 4.5 20 10 20 15.5 20 20 15.5 20 10 20 4.5 15.5 0 10 0L10 0ZM15 11L11 11 11 15 9 15 9 11 5 11 5 9 9 9 9 5 11 5 11 9 15 9 15 11 15 11Z" id="Shape"/>
|
||||
</symbol>
|
||||
<symbol id="icon-create-screen-capture" viewBox="0 0 37 35">
|
||||
<title>Capture Screen</title>
|
||||
<g id="camera-alt" transform="translate(17.000000, 17.000000)" fill="#94a8b3">
|
||||
<path d="M10 13C11.66 13 13 11.66 13 10 13 8.34 11.66 7 10 7 8.34 7 7 8.34 7 10 7 11.66 8.34 13 10 13Z" id="Oval"/>
|
||||
<path d="M7 0L5.2 2 2 2C0.9 2 0 2.9 0 4L0 16C0 17.1 0.9 18 2 18L18 18C19.1 18 20 17.1 20 16L20 4C20 2.9 19.1 2 18 2L14.8 2 13 0 7 0 7 0ZM10 15C7.2 15 5 12.8 5 10 5 7.2 7.2 5 10 5 12.8 5 15 7.2 15 10 15 12.8 12.8 15 10 15L10 15Z" id="Shape"/>
|
||||
</g>
|
||||
<path d="M10 0C4.5 0 0 4.5 0 10 0 15.5 4.5 20 10 20 15.5 20 20 15.5 20 10 20 4.5 15.5 0 10 0L10 0ZM15 11L11 11 11 15 9 15 9 11 5 11 5 9 9 9 9 5 11 5 11 9 15 9 15 11 15 11Z" id="Shape"/>
|
||||
</symbol>
|
||||
<symbol id="icon-ui-warning" viewBox="0 0 22 20">
|
||||
<title>Warning</title>
|
||||
<g id="icon-ui-warning-group" stroke="none">
|
||||
<path d="m11,0 11,20 -22,0Z m1,7 -2,0 0,6 2,0Z m0,8 -2,0 0,2 2,0Z" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-ohif-logo" viewBox="0 0 47 47">
|
||||
<title>Open Health Imaging Foundation</title>
|
||||
<g id="icon-ohif-logo" stroke="#fff" stroke-width="2.5" stroke-miterlimit="10">
|
||||
<rect x="1.25" y="1.25" width="18.8" height="18.8" rx="1" ry="1"/>
|
||||
<rect x="26" y="1.25" width="18.8" height="18.8" rx="1" ry="1"/>
|
||||
<rect x="1.25" y="26" width="18.8" height="18.8" rx="1" ry="1"/>
|
||||
<rect x="26" y="26" width="18.8" height="18.8" rx="1" ry="1"/>
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-viewport-link" viewBox="0 0 32 32">
|
||||
<title>Viewport Link</title>
|
||||
<g id="icon-viewport-link-group" stroke="none">
|
||||
<path d="m5.364 28.917c1.047 1.046 2.422 1.57 3.797 1.57 1.376 0 2.751-0.523 3.798-1.572l7.552-7.554c1.016-1.014 1.574-2.361 1.574-3.797 -0.001-1.432-0.558-2.781-1.574-3.796l-2.297-2.298 -2.009 2.009 2.297 2.298c0.478 0.478 0.741 1.113 0.741 1.788 0 0.674-0.264 1.309-0.741 1.786l-7.553 7.555c-0.987 0.985-2.59 0.985-3.576 0l-2.297-2.298c-0.987-0.985-0.987-2.589 0-3.576l3.775-3.776 -2.009-2.009 -3.776 3.776c-2.094 2.096-2.092 5.502 0 7.595l2.299 2.3zM26.695 2.992"/>
|
||||
<path d="m26.695 2.992c-1.014-1.016-2.362-1.575-3.797-1.575 -0.001 0-0.001 0-0.002 0 -1.435 0-2.784 0.56-3.798 1.573l-7.551 7.553c-1.017 1.016-1.576 2.363-1.576 3.799 0 1.434 0.558 2.784 1.574 3.797l2.297 2.297 2.01-2.009 -2.298-2.297c-0.477-0.477-0.741-1.113-0.741-1.788 0-0.676 0.265-1.311 0.742-1.788l7.553-7.555c0.477-0.477 1.111-0.74 1.789-0.74 0 0 0 0 0.001 0 0.674 0 1.309 0.264 1.786 0.74l2.297 2.299c0.477 0.477 0.74 1.111 0.74 1.788 0 0.674-0.264 1.311-0.74 1.788l-3.776 3.777 2.009 2.009 3.776-3.777c1.014-1.013 1.573-2.363 1.574-3.797 0-1.435-0.56-2.784-1.574-3.797l-2.295-2.296z"/>
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="theme" viewBox="0 0 24 24">
|
||||
<title>Theme</title>
|
||||
<path d="M17.484 12c0.844 0 1.5-0.656 1.5-1.5s-0.656-1.5-1.5-1.5-1.5 0.656-1.5 1.5 0.656 1.5 1.5 1.5zM14.484 8.016c0.844 0 1.5-0.656 1.5-1.5s-0.656-1.5-1.5-1.5-1.5 0.656-1.5 1.5 0.656 1.5 1.5 1.5zM9.516 8.016c0.844 0 1.5-0.656 1.5-1.5s-0.656-1.5-1.5-1.5-1.5 0.656-1.5 1.5 0.656 1.5 1.5 1.5zM6.516 12c0.844 0 1.5-0.656 1.5-1.5s-0.656-1.5-1.5-1.5-1.5 0.656-1.5 1.5 0.656 1.5 1.5 1.5zM12 3c4.969 0 9 3.609 9 8.016 0 2.766-2.25 4.969-5.016 4.969h-1.734c-0.844 0-1.5 0.656-1.5 1.5 0 0.375 0.141 0.703 0.375 0.984s0.375 0.656 0.375 1.031c0 0.844-0.656 1.5-1.5 1.5-4.969 0-9-4.031-9-9s4.031-9 9-9z"></path>
|
||||
</symbol>
|
||||
<symbol id="log" viewBox="0 0 24 24">
|
||||
<title>Log</title>
|
||||
<path d="M9.516 14.016c2.484 0 4.5-2.016 4.5-4.5s-2.016-4.5-4.5-4.5-4.5 2.016-4.5 4.5 2.016 4.5 4.5 4.5zM15.516 14.016l4.969 4.969-1.5 1.5-4.969-4.969v-0.797l-0.281-0.281c-1.125 0.984-2.625 1.547-4.219 1.547-3.609 0-6.516-2.859-6.516-6.469s2.906-6.516 6.516-6.516 6.469 2.906 6.469 6.516c0 1.594-0.563 3.094-1.547 4.219l0.281 0.281h0.797z"></path>
|
||||
</symbol>
|
||||
<symbol id="server" viewBox="0 0 24 28">
|
||||
<title>Server</title>
|
||||
<path d="M12 12c4.703 0 9.422-0.844 12-2.656v2.656c0 2.203-5.375 4-12 4s-12-1.797-12-4v-2.656c2.578 1.813 7.297 2.656 12 2.656zM12 24c4.703 0 9.422-0.844 12-2.656v2.656c0 2.203-5.375 4-12 4s-12-1.797-12-4v-2.656c2.578 1.813 7.297 2.656 12 2.656zM12 18c4.703 0 9.422-0.844 12-2.656v2.656c0 2.203-5.375 4-12 4s-12-1.797-12-4v-2.656c2.578 1.813 7.297 2.656 12 2.656zM12 0c6.625 0 12 1.797 12 4v2c0 2.203-5.375 4-12 4s-12-1.797-12-4v-2c0-2.203 5.375-4 12-4z"></path>
|
||||
</symbol>
|
||||
<symbol id="study-list" viewBox="0 0 24 24">
|
||||
<title>Study List</title>
|
||||
<path d="M9 5.016h12v3.984h-12v-3.984zM9 18.984v-3.984h12v3.984h-12zM9 14.016v-4.031h12v4.031h-12zM3.984 9v-3.984h4.031v3.984h-4.031zM3.984 18.984v-3.984h4.031v3.984h-4.031zM3.984 14.016v-4.031h4.031v4.031h-4.031z"></path>
|
||||
</symbol>
|
||||
<symbol id="logout" viewBox="0 0 24 28">
|
||||
<title>Logout</title>
|
||||
<path d="M24 14c0 6.609-5.391 12-12 12s-12-5.391-12-12c0-3.797 1.75-7.297 4.797-9.578 0.891-0.672 2.141-0.5 2.797 0.391 0.672 0.875 0.484 2.141-0.391 2.797-2.031 1.531-3.203 3.859-3.203 6.391 0 4.406 3.594 8 8 8s8-3.594 8-8c0-2.531-1.172-4.859-3.203-6.391-0.875-0.656-1.062-1.922-0.391-2.797 0.656-0.891 1.922-1.062 2.797-0.391 3.047 2.281 4.797 5.781 4.797 9.578zM14 2v10c0 1.094-0.906 2-2 2s-2-0.906-2-2v-10c0-1.094 0.906-2 2-2s2 0.906 2 2z"></path>
|
||||
</symbol>
|
||||
<symbol id="password" viewBox="0 0 18 28">
|
||||
<title>Password</title>
|
||||
<path d="M5 12h8v-3c0-2.203-1.797-4-4-4s-4 1.797-4 4v3zM18 13.5v9c0 0.828-0.672 1.5-1.5 1.5h-15c-0.828 0-1.5-0.672-1.5-1.5v-9c0-0.828 0.672-1.5 1.5-1.5h0.5v-3c0-3.844 3.156-7 7-7s7 3.156 7 7v3h0.5c0.828 0 1.5 0.672 1.5 1.5z"></path>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 20 KiB |
@ -1,30 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
|
||||
<title>OHIF Viewer</title>
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
|
||||
<!-- WEB FONTS -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Sanchez" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
|
||||
crossorigin="anonymous">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -1,25 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>OpenID Connect Logout Redirect Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.7/es5-shim.min.js"></script>
|
||||
<script type="text/javascript" src='es6-shim.min.js'></script>
|
||||
<script type="text/javascript" src='oidc-client.min.js'></script>
|
||||
<script type="text/javascript" src='polyfill.min.js'></script>
|
||||
<script type="text/javascript">
|
||||
// TODO: I think this is actually not necessary anymore
|
||||
new UserManager().signoutRedirectCallback().then(function() {
|
||||
// TODO: Keycloak + Auth0 is not properly logging out both sessions?
|
||||
// This is a hacky hardcoded workaround. This could also be added as a component to the React application rather than a static page.
|
||||
var path = 'https://www.crowds-cure.org';
|
||||
var client_id = 'z5cXMPTxeFOdB3i4xRA8JyhTonQmqMKM';
|
||||
var url = 'https://auth.crowds-cure.org/v2/logout?client_id=' + client_id + '&returnTo=' + path;
|
||||
window.location.href = url;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"short_name": "react-cornerstone-viewport",
|
||||
"name": "react-cornerstone-viewport",
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
46
OHIFViewer-react/public/oidc-client.min.js
vendored
46
OHIFViewer-react/public/oidc-client.min.js
vendored
File diff suppressed because one or more lines are too long
1
OHIFViewer-react/public/polyfill.min.js
vendored
1
OHIFViewer-react/public/polyfill.min.js
vendored
@ -1 +0,0 @@
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(0,function(){"use strict";function e(e){var n=this.constructor;return this.then(function(t){return n.resolve(e()).then(function(){return t})},function(t){return n.resolve(e()).then(function(){return n.reject(t)})})}function n(){}function t(e){if(!(this instanceof t))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],u(e,this)}function o(e,n){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,t._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null!==t){var o;try{o=t(e._value)}catch(f){return void i(n.promise,f)}r(n.promise,o)}else(1===e._state?r:i)(n.promise,e._value)})):e._deferreds.push(n)}function r(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var o=n.then;if(n instanceof t)return e._state=3,e._value=n,void f(e);if("function"==typeof o)return void u(function(e,n){return function(){e.apply(n,arguments)}}(o,n),e)}e._state=1,e._value=n,f(e)}catch(r){i(e,r)}}function i(e,n){e._state=2,e._value=n,f(e)}function f(e){2===e._state&&0===e._deferreds.length&&t._immediateFn(function(){e._handled||t._unhandledRejectionFn(e._value)});for(var n=0,r=e._deferreds.length;r>n;n++)o(e,e._deferreds[n]);e._deferreds=null}function u(e,n){var t=!1;try{e(function(e){t||(t=!0,r(n,e))},function(e){t||(t=!0,i(n,e))})}catch(o){if(t)return;t=!0,i(n,o)}}var c=setTimeout;t.prototype["catch"]=function(e){return this.then(null,e)},t.prototype.then=function(e,t){var r=new this.constructor(n);return o(this,new function(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}(e,t,r)),r},t.prototype["finally"]=e,t.all=function(e){return new t(function(n,t){function o(e,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(n){o(e,n)},t)}r[e]=f,0==--i&&n(r)}catch(c){t(c)}}if(!e||"undefined"==typeof e.length)throw new TypeError("Promise.all accepts an array");var r=Array.prototype.slice.call(e);if(0===r.length)return n([]);for(var i=r.length,f=0;r.length>f;f++)o(f,r[f])})},t.resolve=function(e){return e&&"object"==typeof e&&e.constructor===t?e:new t(function(n){n(e)})},t.reject=function(e){return new t(function(n,t){t(e)})},t.race=function(e){return new t(function(n,t){for(var o=0,r=e.length;r>o;o++)e[o].then(n,t)})},t._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){c(e,0)},t._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var l=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"Promise"in l?l.Promise.prototype["finally"]||(l.Promise.prototype["finally"]=e):l.Promise=t});
|
||||
@ -1,16 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Silent OpenID Connect Token Refresh Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.7/es5-shim.min.js"></script>
|
||||
<script type="text/javascript" src='es6-shim.min.js'></script>
|
||||
<script type="text/javascript" src="oidc-client.min.js"></script>
|
||||
<script type="text/javascript" src='polyfill.min.js'></script>
|
||||
<script type="text/javascript">
|
||||
new UserManager().signinSilentCallback().catch(console.error);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,18 +0,0 @@
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
background-color: black;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-family: Roboto, OpenSans, HelveticaNeue-Light, Helvetica Neue Light,
|
||||
Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif;
|
||||
}
|
||||
@ -1,128 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from 'react-router';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { ViewerbaseDragDropContext } from 'react-viewerbase';
|
||||
import routes from './routes/';
|
||||
import StudyListRouting from './studylist/StudyListRouting.js';
|
||||
import CallbackPage from './CallbackPage.js';
|
||||
import './App.css';
|
||||
import './variables.css';
|
||||
import './theme-tide.css';
|
||||
|
||||
const { ViewerRouting, StandaloneRouting, IHEInvokeImageDisplay } = routes;
|
||||
|
||||
const reload = () => window.location.reload();
|
||||
|
||||
function setContext(context) {
|
||||
/*Rollbar.configure({
|
||||
payload: {
|
||||
context
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
class App extends Component {
|
||||
static propTypes = {
|
||||
history: PropTypes.object.isRequired,
|
||||
user: PropTypes.object,
|
||||
userManager: PropTypes.object,
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.unlisten = this.props.history.listen((location, action) => {
|
||||
setContext(window.location.pathname);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unlisten();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user, userManager } = this.props;
|
||||
|
||||
const userNotLoggedIn = userManager && (!user || user.expired);
|
||||
if (userNotLoggedIn) {
|
||||
const pathname = this.props.location.pathname;
|
||||
|
||||
if (pathname !== '/callback') {
|
||||
sessionStorage.setItem('ohif-redirect-to', pathname);
|
||||
}
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route exact path="/silent-refresh.html" onEnter={reload} />
|
||||
<Route exact path="/logout-redirect.html" onEnter={reload} />
|
||||
<Route path="/callback" render={
|
||||
() => <CallbackPage userManager={userManager} />
|
||||
} />
|
||||
<Route component={() => {
|
||||
userManager.signinRedirect();
|
||||
|
||||
return null;
|
||||
}} />
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route exact path="/silent-refresh.html" onEnter={reload} />
|
||||
<Route exact path="/logout-redirect.html" onEnter={reload} />
|
||||
<Route
|
||||
exact
|
||||
path="/studylist"
|
||||
component={StudyListRouting}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
component={StudyListRouting}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/viewer"
|
||||
component={StandaloneRouting}
|
||||
/>
|
||||
<Route
|
||||
path="/viewer/:studyInstanceUids"
|
||||
component={ViewerRouting}
|
||||
/>
|
||||
<Route
|
||||
path="/study/:studyInstanceUid/series/:seriesInstanceUids"
|
||||
component={ViewerRouting}
|
||||
/>
|
||||
<Route
|
||||
path="/IHEInvokeImageDisplay"
|
||||
component={IHEInvokeImageDisplay}
|
||||
/>
|
||||
<Route path="/silent-refresh.html" onEnter={reload} />
|
||||
<Route path="/logout-redirect.html" onEnter={reload} />
|
||||
<Route exact path='/login' component={() => {
|
||||
userManager.signinRedirect();
|
||||
}}
|
||||
/>
|
||||
<Route path="/callback" component={CallbackPage} />
|
||||
<Route render={() =>
|
||||
<div> Sorry, this page does not exist. </div>}
|
||||
/>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
user: state.oidc.user,
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedApp = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(App);
|
||||
|
||||
export default ViewerbaseDragDropContext(withRouter(ConnectedApp));
|
||||
@ -1,32 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import { CallbackComponent } from "redux-oidc";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class CallbackPage extends Component {
|
||||
static propTypes = {
|
||||
userManager: PropTypes.object.isRequired,
|
||||
history: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<CallbackComponent
|
||||
userManager={this.props.userManager}
|
||||
successCallback={() => {
|
||||
const pathname = sessionStorage.getItem('ohif-redirect-to');
|
||||
|
||||
this.props.history.push(pathname);
|
||||
}}
|
||||
errorCallback={error => {
|
||||
//this.props.history.push("/");
|
||||
throw new Error(error);
|
||||
}}
|
||||
>
|
||||
<div>Redirecting...</div>
|
||||
</CallbackComponent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(CallbackPage);
|
||||
@ -1,21 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ExampleViewportPlugin from './ExampleViewportPlugin';
|
||||
|
||||
// We don't really need Redux to do this, this is just an example
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { displaySet } = ownProps.viewportData;
|
||||
const { studyInstanceUid, seriesInstanceUid } = displaySet;
|
||||
|
||||
return {
|
||||
studyInstanceUid,
|
||||
seriesInstanceUid,
|
||||
displaySet
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedExampleViewportPlugin = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(ExampleViewportPlugin);
|
||||
|
||||
export default ConnectedExampleViewportPlugin;
|
||||
@ -1,27 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class ExampleViewportPlugin extends Component {
|
||||
static propTypes = {
|
||||
studyInstanceUid: PropTypes.string.isRequired,
|
||||
seriesInstanceUid: PropTypes.string.isRequired,
|
||||
displaySet: PropTypes.object
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
studyInstanceUid: '',
|
||||
seriesInstanceUid: ''
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ExampleViewportPlugin">
|
||||
<p>StudyInstanceUid: {this.props.studyInstanceUid}</p>
|
||||
<p>SeriesInstanceUid: {this.props.seriesInstanceUid}</p>
|
||||
{JSON.stringify(this.props.displaySet)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ExampleViewportPlugin;
|
||||
@ -1,24 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import Header from './Header.js';
|
||||
import { setUserPreferencesModalOpen } from '../../redux/actions.js';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
isOpen: state.ui.userPreferencesModalOpen,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
openUserPreferencesModal: () => {
|
||||
dispatch(setUserPreferencesModalOpen(true))
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedHeader = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(Header);
|
||||
|
||||
export default ConnectedHeader;
|
||||
@ -1,108 +0,0 @@
|
||||
.entry-header {
|
||||
padding: 10px 10px 0;
|
||||
height: var(--top-bar-height);
|
||||
}
|
||||
|
||||
.entry-header.header-big {
|
||||
background: rgba(21,25,30,0.7);
|
||||
padding: 10px var(--study-list-padding);
|
||||
height: auto;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-left-box {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-viewerLink {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.header-brand {
|
||||
height: 30px;
|
||||
text-decoration: none;
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.entry-header.header-big .header-brand {
|
||||
height: auto;
|
||||
padding: 25px 0;
|
||||
}
|
||||
|
||||
|
||||
.header-logo-image {
|
||||
fill: transparent;
|
||||
height: 100%;
|
||||
margin: 0 8px 0 0;
|
||||
width: 30px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.entry-header.header-big .header-logo-image {
|
||||
margin: 0 20px 0 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.header-logo-text {
|
||||
display: inline-block;
|
||||
font-family: var(--logo-font-family);
|
||||
font-size: 14px;
|
||||
font-weight: var(--logo-font-weight);
|
||||
color: var(--text-primary-color);
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.entry-header.header-big .header-logo-text {
|
||||
font-size: 30px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.header-btn {
|
||||
color: var(--text-secondary-color);
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.header-btn:hover {
|
||||
color: var(--hover-color);
|
||||
}
|
||||
|
||||
.header-btn:active {
|
||||
color: var(--active-color);
|
||||
}
|
||||
|
||||
.header-studyListLinkSection {
|
||||
border-left: var(--ui-border-thickness) solid var(--ui-border-color);
|
||||
margin: 3px 0 0 10px;
|
||||
padding: 0 0 0 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.header-menu {
|
||||
color: var(--text-primary-color);
|
||||
float: right;
|
||||
padding: 4px 0;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
text-decoration: none;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.entry-header.header-big .header-menu {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.header-menu .research-use {
|
||||
float: left;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #91b9cd;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
import { Dropdown } from "react-viewerbase";
|
||||
import './Header.css';
|
||||
import ConnectedUserPreferencesModal from "../../connectedComponents/ConnectedUserPreferencesModal";
|
||||
const Icons = '/icons.svg';
|
||||
|
||||
class Header extends Component {
|
||||
|
||||
static propTypes = {
|
||||
home: PropTypes.bool.isRequired,
|
||||
location: PropTypes.object,
|
||||
openUserPreferencesModal: PropTypes.func,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
home: true
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
userPreferencesOpen: false,
|
||||
};
|
||||
|
||||
this.options = [
|
||||
{
|
||||
title: 'Preferences ',
|
||||
icon: 'fa fa-user',
|
||||
onClick: this.props.openUserPreferencesModal,
|
||||
},
|
||||
{
|
||||
title: 'About',
|
||||
icon: 'fa fa-info',
|
||||
link: 'http://ohif.org',
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
return (<div className={`entry-header ${this.props.home ? 'header-big' : ''}`}>
|
||||
<div className='header-left-box'>
|
||||
{
|
||||
this.props.location && this.props.location.studyLink &&
|
||||
<Link to={this.props.location.studyLink} className="header-btn header-viewerLink">
|
||||
Back to Viewer
|
||||
</Link>
|
||||
}
|
||||
|
||||
<a target="_blank" rel="noopener noreferrer" className="header-brand" href="http://ohif.org">
|
||||
<svg className="header-logo-image">
|
||||
<use xlinkHref={`${Icons}#icon-ohif-logo`} />
|
||||
</svg>
|
||||
<div className="header-logo-text">Open Health Imaging Foundation</div>
|
||||
</a>
|
||||
|
||||
{!this.props.home &&
|
||||
<Link className='header-btn header-studyListLinkSection' to={{
|
||||
pathname: "/",
|
||||
state: { studyLink: this.props.location.pathname }
|
||||
}}>Study list</Link>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="header-menu">
|
||||
<span className="research-use">
|
||||
INVESTIGATIONAL USE ONLY
|
||||
</span>
|
||||
<Dropdown
|
||||
title='Options'
|
||||
list={this.options}
|
||||
align='right'
|
||||
/>
|
||||
<ConnectedUserPreferencesModal />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default withRouter(Header)
|
||||
@ -1,15 +0,0 @@
|
||||
import UserPreferences from "../UserPreferences/UserPreferences";
|
||||
|
||||
export default [
|
||||
{
|
||||
"title": "Preferences",
|
||||
"icon": "fa fa-user",
|
||||
"onClick": UserPreferences,
|
||||
"state": { "modal": true }
|
||||
},
|
||||
{
|
||||
"title": "About",
|
||||
"icon": "fa fa-info",
|
||||
"link": "http://ohif.org"
|
||||
}
|
||||
];
|
||||
@ -1,3 +0,0 @@
|
||||
import Header from './Header'
|
||||
|
||||
export default Header
|
||||
@ -1,43 +0,0 @@
|
||||
import { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
|
||||
class StudyLoadingMonitor extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.array.isRequired,
|
||||
setStudyLoadingProgress: PropTypes.func.isRequired,
|
||||
clearStudyLoadingProgress: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
// TODO: This is pretty ugly. The thing is that the StudyLoadingListener
|
||||
// needs to update the Redux store, but shouldn't know that it exists.
|
||||
// I am therefore passing in some functions to update the store instead,
|
||||
// but this should definitely be cleaned up somehow.
|
||||
const options = {
|
||||
_setProgressData: (progressId, progressData) => {
|
||||
this.props.setStudyLoadingProgress(progressId, progressData)
|
||||
},
|
||||
_clearProgressById: (progressId) => {
|
||||
this.props.clearStudyLoadingProgress(progressId)
|
||||
}
|
||||
}
|
||||
|
||||
const { StudyLoadingListener } = OHIF.classes;
|
||||
this.studyLoadingListener = StudyLoadingListener.getInstance(options);
|
||||
this.studyLoadingListener.clear();
|
||||
this.studyLoadingListener.addStudies(this.props.studies);
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// Destroy stack loading listeners when we close the viewer
|
||||
this.studyLoadingListener.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default StudyLoadingMonitor;
|
||||
@ -1,30 +0,0 @@
|
||||
import { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
|
||||
const { StudyPrefetcher } = OHIF.classes;
|
||||
|
||||
class StudyPrefetcherComponent extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.array,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { studies } = this.props;
|
||||
|
||||
this.studyPrefetcher = StudyPrefetcher.getInstance();
|
||||
this.studyPrefetcher.setStudies(studies);
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// Stop prefetching when we close the viewer
|
||||
this.studyPrefetcher.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default StudyPrefetcherComponent;
|
||||
@ -1,73 +0,0 @@
|
||||
import dicomParser from 'dicom-parser';
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
|
||||
import cornerstoneMath from 'cornerstone-math';
|
||||
import OHIF from 'ohif-core';
|
||||
import sha from './sha.js';
|
||||
import version from './version.js';
|
||||
import { homepage } from '../package.json';
|
||||
|
||||
window.info = {
|
||||
sha,
|
||||
version,
|
||||
homepage
|
||||
};
|
||||
|
||||
// For debugging
|
||||
window.cornerstone = cornerstone;
|
||||
window.cornerstoneWADOImageLoader = cornerstoneWADOImageLoader;
|
||||
|
||||
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
|
||||
cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
|
||||
|
||||
OHIF.external.cornerstone = cornerstone;
|
||||
OHIF.external.cornerstoneMath = cornerstoneMath;
|
||||
OHIF.external.cornerstoneWADOImageLoader = cornerstoneWADOImageLoader;
|
||||
|
||||
// TODO: Is there a better way to guess ROOT_URL?
|
||||
let ROOT_URL = homepage;
|
||||
|
||||
// If the page we are on is not a subset of the expected homepage
|
||||
// provided in the package.json file, we might be doing local development.
|
||||
// In this case, set the base URL to the current location's origin.
|
||||
if (homepage.includes(window.location.origin) === false) {
|
||||
ROOT_URL = window.location.origin;
|
||||
}
|
||||
|
||||
const config = {
|
||||
maxWebWorkers: Math.max(navigator.hardwareConcurrency - 1, 1),
|
||||
startWebWorkersOnDemand: true,
|
||||
webWorkerPath: ROOT_URL + '/cornerstoneWADOImageLoaderWebWorker.min.js',
|
||||
taskConfiguration: {
|
||||
decodeTask: {
|
||||
loadCodecsOnStartup: true,
|
||||
initializeCodecsOnStartup: false,
|
||||
codecsPath: ROOT_URL + '/cornerstoneWADOImageLoaderCodecs.min.js',
|
||||
usePDFJS: false,
|
||||
strict: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cornerstoneWADOImageLoader.webWorkerManager.initialize(config);
|
||||
|
||||
|
||||
OHIF.user.getAccessToken = () => {
|
||||
// TODO: Get the Redux store from somewhere else
|
||||
const state = window.store.getState();
|
||||
if (!state.oidc || !state.oidc.user) {
|
||||
return;
|
||||
}
|
||||
|
||||
return state.oidc.user.access_token;
|
||||
}
|
||||
|
||||
cornerstoneWADOImageLoader.configure({
|
||||
beforeSend: function(xhr) {
|
||||
const headers = OHIF.DICOMWeb.getAuthorizationHeader();
|
||||
|
||||
if (headers.Authorization) {
|
||||
xhr.setRequestHeader("Authorization", headers.Authorization);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1,111 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { CineDialog } from 'react-viewerbase';
|
||||
import OHIF from 'ohif-core';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
|
||||
const { setViewportSpecificData } = OHIF.redux.actions;
|
||||
|
||||
// TODO: I'm guessing this function will be used in other connect locations
|
||||
// so we might want to put it somewhere shared
|
||||
function getActiveViewportSpecificData(state) {
|
||||
const { viewportSpecificData, activeViewportIndex } = state.viewports;
|
||||
return viewportSpecificData[activeViewportIndex];
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
// TODO:
|
||||
// - Test if including CineDialog in the toolbarRow will prevent it
|
||||
// from hovering over the rest of the UI when visible.
|
||||
//
|
||||
// - Create custom ToolbarButton which just shows Play state
|
||||
// - Connect this ToolbarButton to Redux
|
||||
const activeViewportSpecificData = getActiveViewportSpecificData(state);
|
||||
|
||||
let stack = {
|
||||
imageIds: [],
|
||||
currentImageIdIndex: 0
|
||||
};
|
||||
if (activeViewportSpecificData && activeViewportSpecificData.stack) {
|
||||
stack = activeViewportSpecificData.stack
|
||||
}
|
||||
|
||||
let cine = {
|
||||
isPlaying: false,
|
||||
cineFrameRate: 24
|
||||
};
|
||||
if (activeViewportSpecificData && activeViewportSpecificData.cine) {
|
||||
cine = activeViewportSpecificData.cine
|
||||
}
|
||||
|
||||
|
||||
// TODO: activeViewportStackData won't currently change anything on
|
||||
// CornerstoneViewport. The updates are too frequent and it's killing
|
||||
// performance. Need to revisit how we can do this.
|
||||
return {
|
||||
activeViewportStackData: stack,
|
||||
activeViewportCineData: cine,
|
||||
activeViewportIndex: state.viewports.activeViewportIndex
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
dispatchSetViewportSpecificData: (viewportIndex, data) => {
|
||||
dispatch(setViewportSpecificData(viewportIndex, data));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
|
||||
const { activeViewportStackData, activeViewportCineData, activeViewportIndex } = propsFromState;
|
||||
|
||||
return {
|
||||
cineFrameRate: activeViewportCineData.cineFrameRate,
|
||||
isPlaying: activeViewportCineData.isPlaying,
|
||||
onPlayPauseChanged: isPlaying => {
|
||||
const cine = cloneDeep(activeViewportCineData);
|
||||
cine.isPlaying = !cine.isPlaying;
|
||||
|
||||
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { cine });
|
||||
},
|
||||
onFrameRateChanged: frameRate => {
|
||||
const cine = cloneDeep(activeViewportCineData);
|
||||
cine.cineFrameRate = frameRate;
|
||||
|
||||
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { cine });
|
||||
},
|
||||
onClickNextButton: () => {
|
||||
const stack = cloneDeep(activeViewportStackData);
|
||||
const largestPossibleIndex = stack.imageIds.length - 1;
|
||||
stack.currentImageIdIndex = Math.min(stack.currentImageIdIndex + 1, largestPossibleIndex)
|
||||
|
||||
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
|
||||
},
|
||||
onClickBackButton: () => {
|
||||
const stack = cloneDeep(activeViewportStackData);
|
||||
stack.currentImageIdIndex = Math.max(stack.currentImageIdIndex - 1, 0);
|
||||
|
||||
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
|
||||
},
|
||||
onClickSkipToStart: () => {
|
||||
const stack = cloneDeep(activeViewportStackData);
|
||||
stack.currentImageIdIndex = 0;
|
||||
|
||||
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
|
||||
},
|
||||
onClickSkipToEnd: () => {
|
||||
const stack = cloneDeep(activeViewportStackData);
|
||||
stack.currentImageIdIndex = stack.imageIds.length;
|
||||
|
||||
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedCineDialog = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
mergeProps
|
||||
)(CineDialog);
|
||||
|
||||
export default ConnectedCineDialog;
|
||||
@ -1,16 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import FlexboxLayout from './FlexboxLayout';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
leftSidebarOpen: state.ui.leftSidebarOpen,
|
||||
rightSidebarOpen: state.ui.rightSidebarOpen,
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedFlexboxLayout = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(FlexboxLayout);
|
||||
|
||||
export default ConnectedFlexboxLayout;
|
||||
@ -1,41 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { LayoutButton } from 'react-viewerbase';
|
||||
import OHIF from 'ohif-core'
|
||||
|
||||
const { setLayout } = OHIF.redux.actions;
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
currentLayout: state.viewports.layout,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
// TODO: Change if layout switched becomes more complex
|
||||
onChange: selectedCell => {
|
||||
let viewports = [];
|
||||
const rows = selectedCell.row + 1;
|
||||
const columns = selectedCell.col + 1;
|
||||
const numViewports = rows * columns;
|
||||
for (let i = 0; i < numViewports; i++) {
|
||||
viewports.push({
|
||||
height: `${100 / rows}%`,
|
||||
width: `${100 / columns}%`
|
||||
});
|
||||
}
|
||||
const layout = {
|
||||
viewports
|
||||
};
|
||||
|
||||
dispatch(setLayout(layout))
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedLayoutButton = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(LayoutButton);
|
||||
|
||||
export default ConnectedLayoutButton;
|
||||
@ -1,34 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { LayoutManager } from 'react-viewerbase';
|
||||
import OHIF from 'ohif-core';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const viewportPluginIds = state.plugins.availablePlugins.filter(plugin => plugin.type === OHIF.plugins.PLUGIN_TYPES.VIEWPORT).map(plugin => plugin.id);
|
||||
const availablePlugins = {}
|
||||
viewportPluginIds.forEach(id => {
|
||||
const plugin = OHIF.plugins.availablePlugins.find(plugin => plugin.id === id);
|
||||
if (plugin) {
|
||||
availablePlugins[id] = plugin.component;
|
||||
}
|
||||
});
|
||||
|
||||
// TODO Use something like state.plugins.defaultPlugin[OHIF.plugins.PLUGIN_TYPES.VIEWPORT]
|
||||
let defaultPlugin;
|
||||
if (viewportPluginIds && viewportPluginIds.length) {
|
||||
defaultPlugin = viewportPluginIds[0];
|
||||
}
|
||||
|
||||
return {
|
||||
layout: state.viewports.layout,
|
||||
activeViewportIndex: state.viewports.activeViewportIndex,
|
||||
availablePlugins,
|
||||
defaultPlugin
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedLayoutManager = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(LayoutManager);
|
||||
|
||||
export default ConnectedLayoutManager;
|
||||
@ -1,40 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { StudyBrowser } from 'react-viewerbase';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
|
||||
// TODO
|
||||
// - Determine in which display set is active from Redux (activeViewportIndex and layout viewportData)
|
||||
// - Pass in errors and stack loading progress from Redux
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
// If we know that the stack loading progress details have changed,
|
||||
// we can try to update the component state so that the thumbnail
|
||||
// progress bar is updated
|
||||
const stackLoadingProgressMap = state.loading.progress;
|
||||
const studiesWithLoadingData = cloneDeep(ownProps.studies);
|
||||
|
||||
studiesWithLoadingData.forEach(study => {
|
||||
study.thumbnails.forEach(data => {
|
||||
const { displaySetInstanceUid } = data
|
||||
const stackId = `StackProgress:${displaySetInstanceUid}`;
|
||||
const stackProgressData = stackLoadingProgressMap[stackId];
|
||||
|
||||
let stackPercentComplete = 0;
|
||||
if (stackProgressData) {
|
||||
stackPercentComplete = stackProgressData.percentComplete;
|
||||
}
|
||||
|
||||
data.stackPercentComplete = stackPercentComplete;
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
studies: studiesWithLoadingData
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedStudyBrowser = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(StudyBrowser);
|
||||
|
||||
export default ConnectedStudyBrowser;
|
||||
@ -1,23 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import StudyLoadingMonitor from '../components/StudyLoadingMonitor.js';
|
||||
import OHIF from 'ohif-core'
|
||||
|
||||
const { setStudyLoadingProgress, clearStudyLoadingProgress } = OHIF.redux.actions;
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
setStudyLoadingProgress: (progressId, progressData) => {
|
||||
dispatch(setStudyLoadingProgress(progressId, progressData))
|
||||
},
|
||||
clearStudyLoadingProgress: progressId => {
|
||||
dispatch(clearStudyLoadingProgress(progressId))
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedStudyLoadingMonitor = connect(
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)(StudyLoadingMonitor);
|
||||
|
||||
export default ConnectedStudyLoadingMonitor;
|
||||
@ -1,29 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ToolbarRow from './ToolbarRow';
|
||||
import { setLeftSidebarOpen, setRightSidebarOpen } from '../redux/actions.js';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
leftSidebarOpen: state.ui.leftSidebarOpen,
|
||||
rightSidebarOpen: state.ui.rightSidebarOpen
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
setLeftSidebarOpen: state => {
|
||||
dispatch(setLeftSidebarOpen(state))
|
||||
},
|
||||
setRightSidebarOpen: state => {
|
||||
dispatch(setRightSidebarOpen(state))
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedToolbarRow = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ToolbarRow);
|
||||
|
||||
export default ConnectedToolbarRow;
|
||||
@ -1,29 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { ToolbarSection } from 'react-viewerbase';
|
||||
import OHIF from 'ohif-core'
|
||||
|
||||
const { setToolActive } = OHIF.redux.actions;
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const activeButton = state.tools.buttons.find(tool => tool.active === true);
|
||||
|
||||
return {
|
||||
buttons: state.tools.buttons,
|
||||
activeCommand: activeButton && activeButton.command
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
setToolActive: tool => {
|
||||
dispatch(setToolActive(tool.command))
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedToolbarSection = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ToolbarSection);
|
||||
|
||||
export default ConnectedToolbarSection;
|
||||
@ -1,44 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { UserPreferencesModal } from 'react-viewerbase';
|
||||
import OHIF from 'ohif-core';
|
||||
import { setUserPreferencesModalOpen } from '../redux/actions.js';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
|
||||
const { setUserPreferences } = OHIF.redux.actions;
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const contextName = window.store.getState().commandContext.context;
|
||||
return {
|
||||
isOpen: state.ui.userPreferencesModalOpen,
|
||||
windowLevelData: state.preferences[contextName] ? state.preferences[contextName].windowLevelData : {},
|
||||
hotKeysData: state.preferences[contextName] ? state.preferences[contextName].hotKeysData : {},
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
onCancel: () => {
|
||||
dispatch(setUserPreferencesModalOpen(false));
|
||||
},
|
||||
onSave: data => {
|
||||
const contextName = window.store.getState().commandContext.context;
|
||||
const preferences = cloneDeep(window.store.getState().preferences)
|
||||
preferences[contextName] = data;
|
||||
dispatch(setUserPreferences(preferences));
|
||||
dispatch(setUserPreferencesModalOpen(false));
|
||||
OHIF.hotkeysUtil.setHotkeys(data.hotKeysData);
|
||||
},
|
||||
onResetToDefaults: () => {
|
||||
dispatch(setUserPreferences());
|
||||
dispatch(setUserPreferencesModalOpen(false));
|
||||
OHIF.hotkeysUtil.setHotkeys();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedUserPreferencesModal = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(UserPreferencesModal);
|
||||
|
||||
export default ConnectedUserPreferencesModal;
|
||||
@ -1,19 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js';
|
||||
|
||||
const isActive = (a) => a.active === true;
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const activeServer = state.servers.servers.find(isActive);
|
||||
|
||||
return {
|
||||
server: activeServer,
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedViewerRetrieveStudyData = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(ViewerRetrieveStudyData);
|
||||
|
||||
export default ConnectedViewerRetrieveStudyData;
|
||||
@ -1,47 +0,0 @@
|
||||
.FlexboxLayout {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-flow: row nowrap;
|
||||
align-items: stretch;
|
||||
height: calc(100% - var(--toolbar-height));
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
height: 100%;
|
||||
/* required transformation to make inner fixed elements relative to this one*/
|
||||
transform: scale(1);
|
||||
transition: var(--sidebar-transition);
|
||||
}
|
||||
|
||||
.sidebar-left {
|
||||
border-right: var(--ui-border-thickness) solid var(--ui-border-color);
|
||||
flex: 1;
|
||||
margin-left: calc(var(--left-sidebar-menu-width) * -1);
|
||||
max-width: var(--left-sidebar-menu-width);
|
||||
order: 1
|
||||
}
|
||||
|
||||
.sidebar-left.sidebar-open {
|
||||
margin-left: 0
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
order: 2;
|
||||
overflow: hidden;
|
||||
transition: var(--sidebar-transition);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar-right {
|
||||
flex: 1;
|
||||
margin-right: calc(var(--right-sidebar-menu-width) * -1);
|
||||
max-width: var(--right-sidebar-menu-width);
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.sidebar-right.sidebar-open {
|
||||
margin-right: 0;
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
|
||||
import ViewerMain from './ViewerMain.js';
|
||||
import './FlexboxLayout.css';
|
||||
|
||||
class FlexboxLayout extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.array.isRequired,
|
||||
leftSidebarOpen: PropTypes.bool.isRequired,
|
||||
rightSidebarOpen: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
studiesForBrowser: []
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const studiesForBrowser = this.getStudiesForBrowser();
|
||||
|
||||
this.setState({
|
||||
studiesForBrowser
|
||||
});
|
||||
}
|
||||
|
||||
getStudiesForBrowser = () => {
|
||||
const { studies } = this.props;
|
||||
|
||||
// TODO[react]:
|
||||
// - Add sorting of display sets
|
||||
// - Add useMiddleSeriesInstanceAsThumbnail
|
||||
// - Add showStackLoadingProgressBar option
|
||||
return studies.map((study) => {
|
||||
const { studyInstanceUid } = study;
|
||||
|
||||
const thumbnails = study.displaySets.map((displaySet) => {
|
||||
const { displaySetInstanceUid, seriesDescription, seriesNumber, instanceNumber, numImageFrames } = displaySet;
|
||||
|
||||
|
||||
let imageId;
|
||||
|
||||
if (displaySet.images && displaySet.images.length) {
|
||||
imageId = displaySet.images[0].getImageId();
|
||||
}
|
||||
|
||||
return {
|
||||
imageId,
|
||||
displaySetInstanceUid,
|
||||
seriesDescription,
|
||||
seriesNumber,
|
||||
instanceNumber,
|
||||
numImageFrames,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
studyInstanceUid,
|
||||
thumbnails
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let mainContentClassName = "main-content"
|
||||
if (this.props.leftSidebarOpen) {
|
||||
mainContentClassName += ' sidebar-left-open';
|
||||
}
|
||||
|
||||
if (this.props.rightSidebarOpen) {
|
||||
mainContentClassName += ' sidebar-right-open';
|
||||
}
|
||||
|
||||
// TODO[react]: Add measurementLightTable
|
||||
return (
|
||||
<div className="FlexboxLayout">
|
||||
<div className={this.props.leftSidebarOpen ? "sidebar-menu sidebar-left sidebar-open" : "sidebar-menu sidebar-left"}>
|
||||
<ConnectedStudyBrowser studies={this.state.studiesForBrowser}/>
|
||||
</div>
|
||||
<div className={mainContentClassName}>
|
||||
<ViewerMain studies={this.props.studies}/>
|
||||
</div>
|
||||
{/* <div className={this.props.rightSidebarOpen ? "sidebar-menu sidebar-right sidebar-open" : "sidebar-menu sidebar-right"}>
|
||||
{{> measurementLightTable (clone this)}}
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default FlexboxLayout;
|
||||
@ -1,52 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import CornerstoneViewport from 'react-cornerstone-viewport';
|
||||
import OHIF from 'ohif-core'
|
||||
import cornerstone from "cornerstone-core";
|
||||
import cornerstoneTools from "cornerstone-tools";
|
||||
|
||||
const { setViewportActive, setViewportSpecificData, clearViewportSpecificData } = OHIF.redux.actions;
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const activeButton = state.tools.buttons.find(tool => tool.active === true);
|
||||
|
||||
// If this is the active viewport, enable prefetching.
|
||||
const { viewportIndex } = ownProps;//.viewportData;
|
||||
const isActive = viewportIndex === state.viewports.activeViewportIndex;
|
||||
const viewportSpecificData = state.viewports.viewportSpecificData[viewportIndex] || {};
|
||||
|
||||
return {
|
||||
layout: state.viewports.layout,
|
||||
isActive,
|
||||
activeTool: activeButton && activeButton.command,
|
||||
enableStackPrefetch: isActive,
|
||||
//stack: viewportSpecificData.stack,
|
||||
cineToolData: viewportSpecificData.cine,
|
||||
cornerstone,
|
||||
cornerstoneTools
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch, ownProps) => {
|
||||
const { viewportIndex } = ownProps;
|
||||
|
||||
return {
|
||||
setViewportActive: () => {
|
||||
dispatch(setViewportActive(viewportIndex))
|
||||
},
|
||||
|
||||
setViewportSpecificData: (data) => {
|
||||
dispatch(setViewportSpecificData(viewportIndex, data))
|
||||
},
|
||||
|
||||
clearViewportSpecificData: () => {
|
||||
dispatch(clearViewportSpecificData(viewportIndex));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedCornerstoneViewport = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(CornerstoneViewport);
|
||||
|
||||
export default ConnectedCornerstoneViewport;
|
||||
@ -1,85 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
import ConnectedCornerstoneViewport from './ConnectedCornerstoneViewport';
|
||||
import OHIFComponentPlugin from '../OHIFComponentPlugin.js';
|
||||
import cornerstoneTools from "cornerstone-tools";
|
||||
import cornerstone from "cornerstone-core";
|
||||
import './config';
|
||||
|
||||
const { StackManager } = OHIF.utils;
|
||||
|
||||
// Create the synchronizer used to update reference lines
|
||||
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.updateImageSynchronizer);
|
||||
|
||||
// Metadata configuration
|
||||
const metadataProvider = new OHIF.cornerstone.MetadataProvider();
|
||||
|
||||
cornerstone.metaData.addProvider(metadataProvider.provider.bind(metadataProvider));
|
||||
|
||||
StackManager.setMetadataProvider(metadataProvider);
|
||||
|
||||
class OHIFCornerstoneViewportPlugin extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.object,
|
||||
displaySet: PropTypes.object,
|
||||
viewportIndex: PropTypes.number,
|
||||
};
|
||||
|
||||
static id = 'CornerstoneViewportPlugin';
|
||||
|
||||
static init() {
|
||||
console.log('CornerstoneViewportPlugin init()');
|
||||
}
|
||||
|
||||
static destroy() {
|
||||
console.log('CornerstoneViewportPlugin destroy()');
|
||||
StackManager.clearStacks();
|
||||
}
|
||||
|
||||
static getCornerstoneStack(studies, studyInstanceUid, displaySetInstanceUid) {
|
||||
// Create shortcut to displaySet
|
||||
const study = studies.find(study => study.studyInstanceUid === studyInstanceUid);
|
||||
|
||||
const displaySet = study.displaySets.find((set) => {
|
||||
return set.displaySetInstanceUid === displaySetInstanceUid;
|
||||
});
|
||||
|
||||
// Get stack from Stack Manager
|
||||
return StackManager.findOrCreateStack(study, displaySet);
|
||||
}
|
||||
|
||||
static getPluginViewportData = (studies, studyInstanceUid, displaySetInstanceUid) => {
|
||||
const currentStack = OHIFCornerstoneViewportPlugin.getCornerstoneStack(studies, studyInstanceUid, displaySetInstanceUid);
|
||||
|
||||
// Clone the stack here so we don't mutate it later
|
||||
const stack = Object.assign({}, currentStack);
|
||||
stack.currentImageIdIndex = 0;
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { viewportIndex } = this.props;
|
||||
const { studies, displaySet } = this.props.viewportData;
|
||||
const { studyInstanceUid, displaySetInstanceUid } = displaySet;
|
||||
const stack = OHIFCornerstoneViewportPlugin.getPluginViewportData(studies, studyInstanceUid, displaySetInstanceUid);
|
||||
const viewportData = {
|
||||
studyInstanceUid,
|
||||
displaySetInstanceUid,
|
||||
stack
|
||||
};
|
||||
|
||||
const { id, init, destroy } = OHIFCornerstoneViewportPlugin;
|
||||
const pluginProps = { id, init, destroy };
|
||||
|
||||
return (
|
||||
<OHIFComponentPlugin {...pluginProps}>
|
||||
<ConnectedCornerstoneViewport viewportData={viewportData} viewportIndex={viewportIndex}/>
|
||||
</OHIFComponentPlugin>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default OHIFCornerstoneViewportPlugin;
|
||||
@ -1,31 +0,0 @@
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import cornerstoneMath from 'cornerstone-math';
|
||||
import cornerstoneTools from 'cornerstone-tools';
|
||||
import Hammer from 'hammerjs';
|
||||
import OHIF from 'ohif-core';
|
||||
|
||||
// For debugging
|
||||
window.cornerstoneTools = cornerstoneTools;
|
||||
|
||||
cornerstoneTools.external.cornerstone = cornerstone;
|
||||
cornerstoneTools.external.Hammer = Hammer;
|
||||
cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
|
||||
cornerstoneTools.init();
|
||||
|
||||
OHIF.external.cornerstoneTools = cornerstoneTools;
|
||||
|
||||
// Set the tool font and font size
|
||||
// context.font = "[style] [variant] [weight] [size]/[line height] [font family]";
|
||||
const fontFamily =
|
||||
'Roboto, OpenSans, HelveticaNeue-Light, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif';
|
||||
cornerstoneTools.textStyle.setFont(`16px ${fontFamily}`);
|
||||
|
||||
// Set the tool width
|
||||
cornerstoneTools.toolStyle.setToolWidth(2);
|
||||
// Set color for inactive tools
|
||||
cornerstoneTools.toolColors.setToolColor('rgb(255, 255, 0)');
|
||||
|
||||
// Set color for active tools
|
||||
cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)');
|
||||
|
||||
cornerstoneTools.store.state.touchProximity = 40;
|
||||
@ -1,32 +0,0 @@
|
||||
import OHIF from "ohif-core";
|
||||
|
||||
const { plugins, utils } = OHIF;
|
||||
const { PLUGIN_TYPES } = plugins;
|
||||
|
||||
// TODO: Should probably use dcmjs for this
|
||||
const SOP_CLASS_UIDS = {
|
||||
ENCAPSULATED_PDF: '1.2.840.10008.5.1.4.1.1.104.1'
|
||||
};
|
||||
|
||||
const OHIFDicomPDFSopClassHandlerPlugin = {
|
||||
id: 'OHIFDicomPDFSopClassHandlerPlugin',
|
||||
type: PLUGIN_TYPES.SOP_CLASS_HANDLER,
|
||||
sopClassUids: [
|
||||
SOP_CLASS_UIDS.ENCAPSULATED_PDF
|
||||
],
|
||||
getDisplaySetFromSeries(series, study) {
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
return {
|
||||
plugin: 'pdf',
|
||||
displaySetInstanceUid: utils.guid(),
|
||||
wadoRoot: study.getData().wadoRoot,
|
||||
wadoUri: instance.getData().wadouri,
|
||||
sopInstanceUid: instance.getSOPInstanceUID(),
|
||||
seriesInstanceUid: series.getSeriesInstanceUID(),
|
||||
studyInstanceUid: study.getStudyInstanceUID()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default OHIFDicomPDFSopClassHandlerPlugin;
|
||||
@ -1,77 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
import OHIFComponentPlugin from '../OHIFComponentPlugin.js';
|
||||
import DicomPDFViewport from './DicomPDFViewport';
|
||||
|
||||
const { DICOMWeb } = OHIF;
|
||||
|
||||
class OHIFDicomPDFViewportPlugin extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.object,
|
||||
displaySet: PropTypes.object,
|
||||
viewportIndex: PropTypes.number,
|
||||
};
|
||||
|
||||
state = {
|
||||
byteArray: null,
|
||||
error: null
|
||||
}
|
||||
|
||||
static id = 'DicomPDFViewportPlugin';
|
||||
|
||||
static init() {
|
||||
console.log('DicomPDFViewportPlugin init()');
|
||||
}
|
||||
|
||||
static destroy() {
|
||||
console.log('DicomPDFViewportPlugin destroy()');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { displaySet } = this.props.viewportData;
|
||||
const { studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri } = displaySet;
|
||||
|
||||
this.retrieveDicomData(studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri).then(byteArray => {
|
||||
this.setState({
|
||||
byteArray
|
||||
});
|
||||
}, error => {
|
||||
this.setState({
|
||||
error
|
||||
});
|
||||
|
||||
throw new Error(error);
|
||||
});
|
||||
}
|
||||
|
||||
retrieveDicomData(studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri) {
|
||||
// TODO: Passing in a lot of data we aren't using
|
||||
|
||||
// TODO: Authorization header depends on the server. If we ever have multiple servers
|
||||
// we will need to figure out how / when to pass this information in.
|
||||
return fetch(wadoUri, {
|
||||
headers: DICOMWeb.getAuthorizationHeader()
|
||||
}).then(response => response.arrayBuffer()).then(arraybuffer => {
|
||||
debugger;
|
||||
return new Uint8Array(arraybuffer);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { id, init, destroy } = OHIFDicomPDFViewportPlugin;
|
||||
const pluginProps = { id, init, destroy };
|
||||
|
||||
return (
|
||||
<OHIFComponentPlugin {...pluginProps}>
|
||||
{this.state.byteArray && <DicomPDFViewport byteArray={this.state.byteArray}/>}
|
||||
{this.state.error &&
|
||||
<h2>{JSON.stringify(this.state.error)}</h2>
|
||||
}
|
||||
</OHIFComponentPlugin>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default OHIFDicomPDFViewportPlugin;
|
||||
@ -1,17 +0,0 @@
|
||||
.ToolbarRow {
|
||||
border-bottom: var(--ui-border-thickness) solid var(--ui-border-color);
|
||||
flex: 0 0 auto;
|
||||
height: var(--toolbar-height);
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
position: relative;
|
||||
transition: height 300ms ease;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
ToolbarRow.expanded {
|
||||
height: calc(var(--toolbar-height) + var(--toolbar-drawer-height));
|
||||
}
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import ConnectedToolbarSection from './ConnectedToolbarSection';
|
||||
import ConnectedLayoutButton from './ConnectedLayoutButton';
|
||||
import ConnectedCineDialog from './ConnectedCineDialog.js';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ToolbarButton, RoundedButtonGroup } from 'react-viewerbase';
|
||||
import './ToolbarRow.css';
|
||||
//import Icons from "../images/icons.svg"
|
||||
|
||||
const Icons = '/icons.svg';
|
||||
|
||||
class ToolbarRow extends Component {
|
||||
state = {
|
||||
cineDialogOpen: false
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
leftSidebarOpen: PropTypes.bool.isRequired,
|
||||
rightSidebarOpen: PropTypes.bool.isRequired,
|
||||
setLeftSidebarOpen: PropTypes.func,
|
||||
setRightSidebarOpen: PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
leftSidebarOpen: false,
|
||||
rightSidebarOpen: false
|
||||
};
|
||||
|
||||
onLeftSidebarValueChanged = (value) => {
|
||||
this.props.setLeftSidebarOpen(!!value);
|
||||
}
|
||||
|
||||
onClickCineToolbarButton = () => {
|
||||
this.setState({
|
||||
cineDialogOpen: !this.state.cineDialogOpen
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const leftSidebarToggle = [{
|
||||
value: 'studies',
|
||||
svgLink: `${Icons}#icon-studies`,
|
||||
svgWidth: 15,
|
||||
svgHeight: 13,
|
||||
bottomLabel: 'Series',
|
||||
}];
|
||||
|
||||
const leftSidebarValue = this.props.leftSidebarOpen ? leftSidebarToggle[0].value : null;
|
||||
|
||||
const cineDialogContainerStyle = {
|
||||
display: this.state.cineDialogOpen ? 'inline-block' : 'none'
|
||||
}
|
||||
|
||||
return (<div className="ToolbarRow">
|
||||
<div className="pull-left m-t-1 p-y-1" style={{ padding: '10px' }}>
|
||||
<RoundedButtonGroup options={leftSidebarToggle} value={leftSidebarValue} onValueChanged={this.onLeftSidebarValueChanged}/>
|
||||
</div>
|
||||
<ConnectedToolbarSection/>
|
||||
<ConnectedLayoutButton/>
|
||||
<ToolbarButton
|
||||
active={this.state.cineDialogOpen}
|
||||
onClick={this.onClickCineToolbarButton}
|
||||
text={'CINE'}
|
||||
iconClasses={'fa fa-youtube'}
|
||||
/>
|
||||
<div className='CineDialogContainer' style={cineDialogContainerStyle}>
|
||||
<ConnectedCineDialog/>
|
||||
</div>
|
||||
<div className="pull-right m-t-1 rm-x-1">
|
||||
{/* > roundedButtonGroup rightSidebarToggleButtonData */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ToolbarRow;
|
||||
@ -1,10 +0,0 @@
|
||||
#viewer {
|
||||
background-color: black;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loadingTextDiv {
|
||||
color: var(--text-secondary-color);
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
//import { CineDialog } from 'react-viewerbase';
|
||||
|
||||
import ConnectedFlexboxLayout from './ConnectedFlexboxLayout.js';
|
||||
import ConnectedToolbarRow from './ConnectedToolbarRow';
|
||||
import ConnectedStudyLoadingMonitor from './ConnectedStudyLoadingMonitor.js';
|
||||
import StudyPrefetcher from '../components/StudyPrefetcher.js';
|
||||
import './Viewer.css';
|
||||
import ConnectedHeader from "../components/Header/ConnectedHeader";
|
||||
|
||||
/**
|
||||
* Inits OHIF Hanging Protocol's onReady.
|
||||
* It waits for OHIF Hanging Protocol to be ready to instantiate the ProtocolEngine
|
||||
* Hanging Protocol will use OHIF LayoutManager to render viewports properly
|
||||
*/
|
||||
/*const initHangingProtocol = () => {
|
||||
// When Hanging Protocol is ready
|
||||
HP.ProtocolStore.onReady(() => {
|
||||
|
||||
// Gets all StudyMetadata objects: necessary for Hanging Protocol to access study metadata
|
||||
const studyMetadataList = OHIF.viewer.StudyMetadataList.all();
|
||||
|
||||
// Instantiate StudyMetadataSource: necessary for Hanging Protocol to get study metadata
|
||||
const studyMetadataSource = new OHIF.studies.classes.OHIFStudyMetadataSource();
|
||||
|
||||
// Get prior studies map
|
||||
const studyPriorsMap = OHIF.studylist.functions.getStudyPriorsMap(studyMetadataList);
|
||||
|
||||
// Creates Protocol Engine object with required arguments
|
||||
const ProtocolEngine = new HP.ProtocolEngine(layoutManager, studyMetadataList, studyPriorsMap, studyMetadataSource);
|
||||
|
||||
// Sets up Hanging Protocol engine
|
||||
HP.setEngine(ProtocolEngine);
|
||||
});
|
||||
};*/
|
||||
|
||||
/*const viewportUtils = OHIF.viewerbase.viewportUtils;
|
||||
|
||||
OHIF.viewer.functionList = {
|
||||
toggleCineDialog: viewportUtils.toggleCineDialog,
|
||||
toggleCinePlay: viewportUtils.toggleCinePlay,
|
||||
clearTools: viewportUtils.clearTools,
|
||||
resetViewport: viewportUtils.resetViewport,
|
||||
invert: viewportUtils.invert
|
||||
};*/
|
||||
|
||||
class Viewer extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.array
|
||||
};
|
||||
|
||||
render() {
|
||||
return (<>
|
||||
<ConnectedHeader home={false} />
|
||||
<div className='viewerDialogs'>
|
||||
</div>
|
||||
<div id="viewer" className='Viewer'>
|
||||
<ConnectedToolbarRow />
|
||||
<ConnectedStudyLoadingMonitor studies={this.props.studies} />
|
||||
<StudyPrefetcher studies={this.props.studies} />
|
||||
<ConnectedFlexboxLayout studies={this.props.studies} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default Viewer;
|
||||
@ -1,41 +0,0 @@
|
||||
#viewer {
|
||||
height: calc(100% - var(--top-bar-height));
|
||||
}
|
||||
|
||||
#viewer > .loadingTextDiv {
|
||||
color: var(--text-secondary-color);
|
||||
font-size: 30px;
|
||||
height: 100%;
|
||||
line-height: calc(100% - var(--top-bar-height));
|
||||
}
|
||||
|
||||
.ViewerMain {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.ViewerMain>div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ViewerMain #imageViewerViewports .viewportContainer {
|
||||
/*theme('border', '%s solid $uiBorderColorDark' % $viewportBorderThickness)*/
|
||||
/*float: left;
|
||||
position: relative;*/
|
||||
outline: 0; /* Prevent blue outline in Chrome */
|
||||
}
|
||||
|
||||
.ViewerMain #imageViewerViewports .viewportContainer:hover,
|
||||
.ViewerMain #imageViewerViewports .viewportContainer:active,
|
||||
.ViewerMain #imageViewerViewports .viewportContainer:hover.active {
|
||||
outline: 0; /* Prevent blue outline in Chrome */
|
||||
}
|
||||
|
||||
/* &:hover
|
||||
//theme('border', '%s solid $uiBorderColor' % $viewportBorderThickness)
|
||||
|
||||
&.active, &:hover.active
|
||||
//theme('border', '%s solid $uiBorderColorActive' % $viewportBorderThickness)
|
||||
*/
|
||||
@ -1,107 +0,0 @@
|
||||
import { Component } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { OHIF } from 'ohif-core';
|
||||
import ConnectedLayoutManager from './ConnectedLayoutManager.js';
|
||||
import './ViewerMain.css';
|
||||
|
||||
class ViewerMain extends Component {
|
||||
state = {
|
||||
viewportData: [],
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
studies: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
OHIF.hotkeysUtil.setup('viewer');
|
||||
}
|
||||
|
||||
getDisplaySets(studies) {
|
||||
const displaySets = [];
|
||||
studies.forEach((study) => {
|
||||
study.displaySets.forEach(dSet => {
|
||||
displaySets.push(dSet);
|
||||
});
|
||||
});
|
||||
|
||||
return displaySets;
|
||||
}
|
||||
|
||||
findDisplaySet(studies, studyInstanceUid, displaySetInstanceUid) {
|
||||
const study = studies.find(study => {
|
||||
return study.studyInstanceUid === studyInstanceUid;
|
||||
});
|
||||
|
||||
if (!study) {
|
||||
return;
|
||||
}
|
||||
|
||||
return study.displaySets.find(displaySet => {
|
||||
return displaySet.displaySetInstanceUid === displaySetInstanceUid;
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// Add beforeUnload event handler to check for unsaved changes
|
||||
//window.addEventListener('beforeunload', unloadHandlers.beforeUnload);
|
||||
|
||||
// Get all the display sets for the viewer studies
|
||||
const displaySets = this.getDisplaySets(this.props.studies);
|
||||
|
||||
this.setState({
|
||||
viewportData: displaySets
|
||||
});
|
||||
}
|
||||
|
||||
setViewportData = ({ viewportIndex, item }) => {
|
||||
// TODO: Replace this with mapDispatchToProps call
|
||||
// if we decide to put viewport info into redux
|
||||
|
||||
// Note: Use Slice because React does a shallow equality check. Mutating the array
|
||||
// would not trigger a re-render. We have to create a copy.
|
||||
const updatedViewportData = this.state.viewportData.slice(0);
|
||||
|
||||
const displaySet = this.findDisplaySet(this.props.studies, item.studyInstanceUid, item.displaySetInstanceUid);
|
||||
|
||||
updatedViewportData[viewportIndex] = Object.assign({}, displaySet);
|
||||
|
||||
this.setState({
|
||||
viewportData: updatedViewportData
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ViewerMain">
|
||||
<ConnectedLayoutManager
|
||||
studies={this.props.studies}
|
||||
viewportData={this.state.viewportData}
|
||||
setViewportData={this.setViewportData}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// Remove beforeUnload event handler...
|
||||
//window.removeEventListener('beforeunload', unloadHandlers.beforeUnload);
|
||||
|
||||
// Destroy the synchronizer used to update reference lines
|
||||
OHIF.viewer.updateImageSynchronizer.destroy();
|
||||
|
||||
// TODO: Instruct all plugins to clean up themselves
|
||||
|
||||
// @TypeSafeStudies
|
||||
// Clears OHIF.viewer.Studies collection
|
||||
//OHIF.viewer.Studies.removeAll();
|
||||
|
||||
// @TypeSafeStudies
|
||||
// Clears OHIF.viewer.StudyMetadataList collection
|
||||
//OHIF.viewer.StudyMetadataList.removeAll();
|
||||
}
|
||||
}
|
||||
|
||||
export default ViewerMain;
|
||||
@ -1,56 +0,0 @@
|
||||
import React, {Component} from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
import Viewer from "./Viewer.js";
|
||||
|
||||
const { createDisplaySets } = OHIF.utils;
|
||||
|
||||
class ViewerRetrieveStudyData extends Component {
|
||||
static propTypes = {
|
||||
studyInstanceUids: PropTypes.array.isRequired,
|
||||
seriesInstanceUids: PropTypes.array,
|
||||
server: PropTypes.object
|
||||
};
|
||||
|
||||
state = {
|
||||
studies: null,
|
||||
error: null
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// TODO: Avoid using timepoints here
|
||||
//const params = { studyInstanceUids, seriesInstanceUids, timepointId, timepointsFilter={} };
|
||||
const { studyInstanceUids, seriesInstanceUids, server } = this.props;
|
||||
const promise = OHIF.studies.retrieveStudiesMetadata(server, studyInstanceUids, seriesInstanceUids)
|
||||
|
||||
// Render the viewer when the data is ready
|
||||
promise.then(studies => {
|
||||
const updatedStudies = createDisplaySets(studies);
|
||||
|
||||
this.setState({
|
||||
studies: updatedStudies,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.setState({
|
||||
error: true,
|
||||
});
|
||||
|
||||
throw new Error(error);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return (<div>Error: {JSON.stringify(this.state.error)}</div>);
|
||||
} else if (!this.state.studies) {
|
||||
return (<div>Loading...</div>);
|
||||
}
|
||||
|
||||
return (
|
||||
<Viewer studies={this.state.studies}/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ViewerRetrieveStudyData;
|
||||
@ -1,15 +0,0 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>OHIF Viewer</title>
|
||||
<meta name="description" content="Open Health Imaging Foundation DICOM Viewer">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1,maximum-scale=1,user-scalable=no">
|
||||
<link rel="shortcut icon" type="image/png" href="/images/logo.png" sizes="16x16 32x32 64x64">
|
||||
<!--Best display for mobile devices-->
|
||||
<meta http-equiv="cleartype" content="on">
|
||||
<meta name="MobileOptimized" content="320">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
@ -1,234 +0,0 @@
|
||||
import React from "react";
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { Provider } from 'react-redux';
|
||||
import { createStore, combineReducers } from 'redux';
|
||||
import { loadUser, reducer as oidcReducer, OidcProvider, createUserManager } from 'redux-oidc';
|
||||
import OHIF from 'ohif-core';
|
||||
import './config';
|
||||
import ui from './redux/ui.js';
|
||||
import App from './App.js';
|
||||
import { loadState, saveState } from './redux/localStorageState.js';
|
||||
|
||||
import OHIFCornerstoneViewportPlugin from "./connectedComponents/OHIFCornerstoneViewportPlugin/OHIFCornerstoneViewportPlugin.js";
|
||||
//import ConnectedExampleViewportPlugin from './components/ConnectedExampleViewportPlugin.js';
|
||||
//import OHIFVTKViewportPlugin from './connectedComponents/OHIFVTKViewportPlugin/OHIFVTKViewportPlugin.js';
|
||||
import OHIFDicomPDFViewportPlugin from './connectedComponents/OHIFDicomPDFViewportPlugin/OHIFDicomPDFViewportPlugin.js';
|
||||
import OHIFDicomPDFSopClassHandlerPlugin from './connectedComponents/OHIFDicomPDFViewportPlugin/OHIFDicomPDFSopClassHandlerPlugin.js';
|
||||
|
||||
let reducers = OHIF.redux.reducers;
|
||||
reducers.ui = ui;
|
||||
reducers.oidc = oidcReducer;
|
||||
|
||||
const Icons = '/icons.svg';
|
||||
const combined = combineReducers(reducers);
|
||||
const store = createStore(combined, loadState());
|
||||
|
||||
// Subscribing store to save state of persistable data
|
||||
store.subscribe(() => {
|
||||
saveState({
|
||||
preferences: store.getState().preferences,
|
||||
});
|
||||
});
|
||||
|
||||
// Note: Run your build like this:
|
||||
// REACT_APP_CONFIG=$(cat ../config-react/ccc.json) yarn start
|
||||
//
|
||||
// If you change the JSON config, you need to re-run the command!
|
||||
let config;
|
||||
if (process.env.REACT_APP_CONFIG) {
|
||||
config = JSON.parse(process.env.REACT_APP_CONFIG);
|
||||
}
|
||||
|
||||
let userManager;
|
||||
if (config && config.oidc) {
|
||||
const oidcClient = config.oidc[0];
|
||||
|
||||
const settings = {
|
||||
authority: oidcClient.authServerUrl,
|
||||
client_id: oidcClient.clientId,
|
||||
redirect_uri: oidcClient.authRedirectUri,
|
||||
silent_redirect_uri: '/silent-refresh.html',
|
||||
post_logout_redirect_uri: oidcClient.postLogoutRedirectUri,
|
||||
response_type: oidcClient.responseType,
|
||||
scope: 'email profile openid', // Note: Request must have scope 'openid' to be considered an OpenID Connect request
|
||||
automaticSilentRenew: true,
|
||||
revokeAccessTokenOnSignout: true,
|
||||
filterProtocolClaims: true,
|
||||
loadUserInfo: true,
|
||||
extraQueryParams: oidcClient.extraQueryParams
|
||||
};
|
||||
|
||||
userManager = createUserManager(settings);
|
||||
|
||||
loadUser(store, userManager);
|
||||
}
|
||||
|
||||
if (config && config.servers) {
|
||||
OHIF.utils.addServers(config.servers, store);
|
||||
}
|
||||
|
||||
const defaultButtons = [
|
||||
{
|
||||
command: 'StackScroll',
|
||||
type: 'tool',
|
||||
text: 'Stack Scroll',
|
||||
svgUrl: `${Icons}#icon-tools-stack-scroll`,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'Zoom',
|
||||
type: 'tool',
|
||||
text: 'Zoom',
|
||||
svgUrl: `${Icons}#icon-tools-zoom`,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'Wwwc',
|
||||
type: 'tool',
|
||||
text: 'Levels',
|
||||
svgUrl: `${Icons}#icon-tools-levels`,
|
||||
active: true
|
||||
},
|
||||
{
|
||||
command: 'Pan',
|
||||
type: 'tool',
|
||||
text: 'Pan',
|
||||
svgUrl: `${Icons}#icon-tools-pan`,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'Length',
|
||||
type: 'tool',
|
||||
text: 'Length',
|
||||
svgUrl: `${Icons}#icon-tools-measure-temp`,
|
||||
active: false
|
||||
},
|
||||
/*{
|
||||
command: 'Annotate',
|
||||
type: 'tool',
|
||||
text: 'Annotate',
|
||||
svgUrl: `${Icons}#icon-tools-measure-non-target`,
|
||||
active: false
|
||||
},*/
|
||||
{
|
||||
command: 'Angle',
|
||||
type: 'tool',
|
||||
text: 'Angle',
|
||||
iconClasses: 'fa fa-angle-left',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'Bidirectional',
|
||||
type: 'tool',
|
||||
text: 'Bidirectional',
|
||||
svgUrl: `${Icons}#icon-tools-measure-target`,
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'reset',
|
||||
type: 'command',
|
||||
text: 'Reset',
|
||||
svgUrl: `${Icons}#icon-tools-reset`,
|
||||
active: false
|
||||
},
|
||||
];
|
||||
|
||||
const buttonsAction = OHIF.redux.actions.setAvailableButtons(defaultButtons);
|
||||
|
||||
store.dispatch(buttonsAction);
|
||||
|
||||
const { plugins } = OHIF;
|
||||
const { PLUGIN_TYPES } = plugins;
|
||||
|
||||
// Uncomment this and comment the Cornerstone version to see how the
|
||||
// example plugin works
|
||||
/*const pluginAction = OHIF.redux.actions.addPlugin({
|
||||
id: 'example',
|
||||
type: PLUGIN_TYPES.VIEWPORT,
|
||||
component: ConnectedExampleViewportPlugin
|
||||
});*/
|
||||
|
||||
const cornerstonePluginAction = OHIF.redux.actions.addPlugin({
|
||||
id: 'cornerstone',
|
||||
type: PLUGIN_TYPES.VIEWPORT,
|
||||
component: OHIFCornerstoneViewportPlugin
|
||||
});
|
||||
|
||||
/*const pluginAction = OHIF.redux.actions.addPlugin({
|
||||
id: 'vtk',
|
||||
type: PLUGIN_TYPES.VIEWPORT,
|
||||
component: OHIFVTKViewportPlugin
|
||||
});*/
|
||||
|
||||
const pdfPluginAction = OHIF.redux.actions.addPlugin({
|
||||
id: 'pdf',
|
||||
type: PLUGIN_TYPES.VIEWPORT,
|
||||
component: OHIFDicomPDFViewportPlugin
|
||||
});
|
||||
|
||||
const servers = {
|
||||
dicomWeb: [
|
||||
{
|
||||
"name": "DCM4CHEE",
|
||||
//"wadoUriRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||
//"qidoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
//"wadoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
"wadoUriRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||
"qidoRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
"wadoRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
// "wadoUriRoot": "https://cancer.crowds-cure.org/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||
// "qidoRoot": "https://cancer.crowds-cure.org/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
// "wadoRoot": "https://cancer.crowds-cure.org/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
"qidoSupportsIncludeField": true,
|
||||
"imageRendering": "wadors",
|
||||
"thumbnailRendering": "wadors",
|
||||
"requestOptions": {
|
||||
"requestFromBrowser": true,
|
||||
"logRequests": true,
|
||||
"logResponses": false,
|
||||
"logTiming": true,
|
||||
//"auth": "admin:admin"
|
||||
//"auth": "cloud:healthcare"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
OHIF.utils.addServers(servers, store);
|
||||
|
||||
const pdfPluginActionSopClass = OHIF.redux.actions.addPlugin({
|
||||
id: 'pdf_sopClassHandler',
|
||||
type: PLUGIN_TYPES.SOP_CLASS_HANDLER,
|
||||
component: OHIFDicomPDFSopClassHandlerPlugin
|
||||
});
|
||||
|
||||
store.dispatch(cornerstonePluginAction);
|
||||
store.dispatch(pdfPluginAction);
|
||||
store.dispatch(pdfPluginActionSopClass);
|
||||
|
||||
// TODO[react] Use a provider when the whole tree is React
|
||||
window.store = store;
|
||||
|
||||
if (userManager) {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<OidcProvider store={store} userManager={userManager}>
|
||||
<BrowserRouter>
|
||||
<App userManager={userManager} />
|
||||
</BrowserRouter>
|
||||
</OidcProvider>
|
||||
</Provider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
} else {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</Provider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
import loglevel from 'loglevel';
|
||||
|
||||
const log = loglevel.getLogger('OHIFViewer');
|
||||
log.setLevel('info');
|
||||
|
||||
export default log;
|
||||
@ -1,22 +0,0 @@
|
||||
export const setLeftSidebarOpen = state => ({
|
||||
type: 'SET_LEFT_SIDEBAR_OPEN',
|
||||
state
|
||||
});
|
||||
|
||||
export const setRightSidebarOpen = state => ({
|
||||
type: 'SET_RIGHT_SIDEBAR_OPEN',
|
||||
state
|
||||
});
|
||||
|
||||
export const setUserPreferencesModalOpen = state => ({
|
||||
type: 'SET_USER_PREFERENCES_MODAL_OPEN',
|
||||
state
|
||||
});
|
||||
|
||||
const actions = {
|
||||
setLeftSidebarOpen,
|
||||
setRightSidebarOpen,
|
||||
setUserPreferencesModalOpen
|
||||
};
|
||||
|
||||
export default actions;
|
||||
@ -1,21 +0,0 @@
|
||||
export const loadState = () => {
|
||||
try {
|
||||
const serializedState = window.localStorage.getItem('state');
|
||||
if (!serializedState) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return JSON.parse(serializedState)
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export const saveState = (state) => {
|
||||
try {
|
||||
const serializedState = JSON.stringify(state);
|
||||
localStorage.setItem('state', serializedState);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
const defaultState = {
|
||||
leftSidebarOpen: true,
|
||||
rightSidebarOpen: false,
|
||||
userPreferencesModalOpen: false
|
||||
}
|
||||
|
||||
const ui = (state = defaultState, action) => {
|
||||
switch (action.type) {
|
||||
case 'SET_LEFT_SIDEBAR_OPEN':
|
||||
return Object.assign({}, state, { leftSidebarOpen: action.state });
|
||||
case 'SET_RIGHT_SIDEBAR_OPEN':
|
||||
return Object.assign({}, state, { rightSidebarOpen: action.state });
|
||||
case 'SET_USER_PREFERENCES_MODAL_OPEN':
|
||||
return Object.assign({}, state, { userPreferencesModalOpen: action.state });
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default ui;
|
||||
@ -1,45 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ViewerRetrieveStudyData from "../connectedComponents/ViewerRetrieveStudyData.js";
|
||||
|
||||
function IHEInvokeImageDisplay({ match }) {
|
||||
const requestType = match.params.query.requestType;
|
||||
let studyInstanceUids;
|
||||
//let patientUids;
|
||||
let displayStudyList = false;
|
||||
|
||||
if (requestType === "STUDY") {
|
||||
studyInstanceUids = match.params.query.studyUID.split(';');
|
||||
} else if (requestType === "STUDYBASE64") {
|
||||
const uids = this.params.query.studyUID;
|
||||
const decodedData = window.atob(uids);
|
||||
studyInstanceUids = decodedData.split(';');
|
||||
} else if (requestType === "PATIENT") {
|
||||
//patientUidspatientUids = this.params.query.patientID.split(';');
|
||||
displayStudyList = true
|
||||
} else {
|
||||
displayStudyList = true
|
||||
}
|
||||
|
||||
if (displayStudyList) {
|
||||
return ('')//<StudyList patientUids={patientUids}/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<ViewerRetrieveStudyData studyInstanceUids={studyInstanceUids}/>
|
||||
);
|
||||
}
|
||||
|
||||
IHEInvokeImageDisplay.propTypes = {
|
||||
match: PropTypes.shape({
|
||||
params: PropTypes.shape({
|
||||
query: PropTypes.shape({
|
||||
requestType: PropTypes.string.isRequired,
|
||||
studyUID: PropTypes.string,
|
||||
patientID: PropTypes.string
|
||||
})
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
export default IHEInvokeImageDisplay;
|
||||
@ -1,104 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import qs from 'query-string'
|
||||
import Viewer from "../connectedComponents/Viewer";
|
||||
import OHIF from 'ohif-core';
|
||||
|
||||
const { createDisplaySets } = OHIF.utils;
|
||||
|
||||
class StandaloneRouting extends Component {
|
||||
state = {
|
||||
studies: null,
|
||||
error: null
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
location: PropTypes.object,
|
||||
store: PropTypes.object
|
||||
};
|
||||
|
||||
static parseQueryAndFetchStudies(query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = query.url;
|
||||
|
||||
if (!url) {
|
||||
reject(new Error('No URL was specified. Use ?url=$yourURL'));
|
||||
}
|
||||
|
||||
// Define a request to the server to retrieve the study data
|
||||
// as JSON, given a URL that was in the Route
|
||||
const oReq = new XMLHttpRequest();
|
||||
|
||||
// Add event listeners for request failure
|
||||
oReq.addEventListener('error', (error) => {
|
||||
OHIF.log.warn('An error occurred while retrieving the JSON data');
|
||||
reject(error)
|
||||
});
|
||||
|
||||
// When the JSON has been returned, parse it into a JavaScript Object
|
||||
// and render the OHIF Viewer with this data
|
||||
oReq.addEventListener('load', () => {
|
||||
// Parse the response content
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText
|
||||
if (!oReq.responseText) {
|
||||
OHIF.log.warn('Response was undefined');
|
||||
reject(new Error('Response was undefined'));
|
||||
}
|
||||
|
||||
OHIF.log.info(JSON.stringify(oReq.responseText, null, 2));
|
||||
|
||||
const data = JSON.parse(oReq.responseText);
|
||||
if (data.servers && query.studyInstanceUids) {
|
||||
const server = data.servers.dicomWeb[0];
|
||||
server.type = 'dicomWeb';
|
||||
|
||||
const studyInstanceUids = query.studyInstanceUids.split(';');
|
||||
const seriesInstanceUids = [];
|
||||
|
||||
OHIF.studies.retrieveStudiesMetadata(server, studyInstanceUids, seriesInstanceUids).then(studies => {
|
||||
resolve(studies);
|
||||
}, error => {
|
||||
reject(error);
|
||||
});
|
||||
} else {
|
||||
resolve(data.studies);
|
||||
}
|
||||
});
|
||||
|
||||
// Open the Request to the server for the JSON data
|
||||
// In this case we have a server-side route called /api/
|
||||
// which responds to GET requests with the study data
|
||||
OHIF.log.info(`Sending Request to: ${url}`);
|
||||
oReq.open('GET', url);
|
||||
oReq.setRequestHeader('Accept', 'application/json')
|
||||
|
||||
// Fire the request to the server
|
||||
oReq.send();
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const query = qs.parse(this.props.location.search);
|
||||
StandaloneRouting.parseQueryAndFetchStudies(query).then(studies => {
|
||||
const updatedStudies = createDisplaySets(studies);
|
||||
|
||||
this.setState({ studies: updatedStudies });
|
||||
}, error => {
|
||||
this.setState({ error });
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return (<div>Error: {JSON.stringify(this.state.error)}</div>);
|
||||
} else if (!this.state.studies) {
|
||||
return (<div>Loading...</div>);
|
||||
}
|
||||
|
||||
return (
|
||||
<Viewer studies={this.state.studies}/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default StandaloneRouting;
|
||||
@ -1,32 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ConnectedViewerRetrieveStudyData from "../connectedComponents/ConnectedViewerRetrieveStudyData";
|
||||
|
||||
function ViewerRouting({ match }) {
|
||||
const { studyInstanceUids, seriesInstanceUids } = match.params;
|
||||
|
||||
let studyUIDs;
|
||||
let seriesUIDs;
|
||||
|
||||
if (studyInstanceUids && !seriesInstanceUids) {
|
||||
studyUIDs = studyInstanceUids.split(';');
|
||||
} else if (studyInstanceUids && seriesInstanceUids) {
|
||||
studyUIDs = [match.params.studyInstanceUid];
|
||||
seriesUIDs = match.params.seriesInstanceUids.split(';');
|
||||
}
|
||||
|
||||
return (
|
||||
<ConnectedViewerRetrieveStudyData studyInstanceUids={studyUIDs} seriesInstanceUids={seriesUIDs}/>
|
||||
);
|
||||
}
|
||||
|
||||
ViewerRouting.propTypes = {
|
||||
match: PropTypes.shape({
|
||||
params: PropTypes.shape({
|
||||
studyInstanceUids: PropTypes.string.isRequired,
|
||||
seriesInstanceUids: PropTypes.string
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
export default ViewerRouting;
|
||||
@ -1,17 +0,0 @@
|
||||
import IHEInvokeImageDisplay from './IHEInvokeImageDisplay.js';
|
||||
import StandaloneRouting from './StandaloneRouting.js';
|
||||
import ViewerRouting from './ViewerRouting.js';
|
||||
|
||||
export {
|
||||
IHEInvokeImageDisplay,
|
||||
ViewerRouting,
|
||||
StandaloneRouting
|
||||
};
|
||||
|
||||
const routes = {
|
||||
IHEInvokeImageDisplay,
|
||||
ViewerRouting,
|
||||
StandaloneRouting
|
||||
};
|
||||
|
||||
export default routes;
|
||||
@ -1,21 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import StudyListWithData from './StudyListWithData.js';
|
||||
|
||||
const isActive = (a) => a.active === true;
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const activeServer = state.servers.servers.find(isActive);
|
||||
|
||||
return {
|
||||
server: activeServer,
|
||||
user: state.oidc.user,
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedStudyList = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(StudyListWithData);
|
||||
|
||||
export default ConnectedStudyList;
|
||||
@ -1,24 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ConnectedStudyList from "./ConnectedStudyList";
|
||||
|
||||
// TODO: Move to react-viewerbase
|
||||
|
||||
function StudyListRouting({ match }) {
|
||||
// TODO: Figure out which filters we want to pass in via a URL
|
||||
//const { patientId } = match.params;
|
||||
|
||||
return (
|
||||
<ConnectedStudyList/>
|
||||
);
|
||||
}
|
||||
|
||||
StudyListRouting.propTypes = {
|
||||
match: PropTypes.shape({
|
||||
params: PropTypes.shape({
|
||||
patientIds: PropTypes.string,
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
export default StudyListRouting;
|
||||
@ -1,113 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { StudyList } from 'react-viewerbase';
|
||||
import ConnectedHeader from "../components/Header/ConnectedHeader";
|
||||
|
||||
class StudyListWithData extends Component {
|
||||
state = {
|
||||
searchData: {},
|
||||
studies: null,
|
||||
error: null
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
patientId: PropTypes.string,
|
||||
server: PropTypes.object,
|
||||
user: PropTypes.object,
|
||||
history: PropTypes.object
|
||||
};
|
||||
|
||||
static rowsPerPage = 25;
|
||||
static defaultSort = { field: 'patientName', order: 'desc' };
|
||||
|
||||
componentDidMount() {
|
||||
// TODO: Avoid using timepoints here
|
||||
//const params = { studyInstanceUids, seriesInstanceUids, timepointId, timepointsFilter={} };
|
||||
|
||||
this.searchForStudies();
|
||||
}
|
||||
|
||||
searchForStudies = (searchData = {
|
||||
currentPage: 0,
|
||||
rowsPerPage: StudyListWithData.rowsPerPage
|
||||
}) => {
|
||||
const { server } = this.props;
|
||||
const filter = {
|
||||
patientId: searchData.patientId,
|
||||
patientName: searchData.patientName,
|
||||
accessionNumber: searchData.accessionNumber,
|
||||
studyDescription: searchData.studyDescription,
|
||||
modalitiesInStudy: searchData.modalitiesInStudy,
|
||||
limit: searchData.currentPage * searchData.rowsPerPage + searchData.rowsPerPage,
|
||||
offset: searchData.currentPage * searchData.rowsPerPage
|
||||
};
|
||||
|
||||
// TODO: add sorting
|
||||
const promise = OHIF.studies.searchStudies(server, filter)
|
||||
|
||||
// Render the viewer when the data is ready
|
||||
promise.then(studies => {
|
||||
if (!studies) {
|
||||
studies = [];
|
||||
}
|
||||
|
||||
// TODO: Fix casing of this property!
|
||||
const fixedStudies = studies.map(study => {
|
||||
const fixedStudy = study;
|
||||
fixedStudy.studyInstanceUID = study.studyInstanceUid;
|
||||
|
||||
return fixedStudy;
|
||||
})
|
||||
|
||||
this.setState({
|
||||
studies: fixedStudies,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.setState({
|
||||
error: true,
|
||||
});
|
||||
|
||||
throw new Error(error);
|
||||
});
|
||||
}
|
||||
|
||||
onImport = () => {
|
||||
//console.log('onImport');
|
||||
}
|
||||
|
||||
onSelectItem = (studyInstanceUID) => {
|
||||
this.props.history.push(`/viewer/${studyInstanceUID}`);
|
||||
}
|
||||
|
||||
onSearch = (searchData) => {
|
||||
// TODO: Update search filters
|
||||
this.searchForStudies(searchData);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return (<div>Error: {JSON.stringify(this.state.error)}</div>);
|
||||
} else if (this.state.studies === null) {
|
||||
return (<div>Loading...</div>);
|
||||
}
|
||||
|
||||
const studyCount = this.state.studies ? this.state.studies.length : 0;
|
||||
|
||||
return (<>
|
||||
<ConnectedHeader home={true} user={this.props.user} />
|
||||
<StudyList studies={this.state.studies}
|
||||
studyCount={studyCount}
|
||||
studyListFunctionsEnabled={false}
|
||||
onImport={this.onImport}
|
||||
onSelectItem={this.onSelectItem}
|
||||
pageSize={this.rowsPerPage}
|
||||
defaultSort={StudyListWithData.defaultSort}
|
||||
onSearch={this.onSearch} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(StudyListWithData);
|
||||
@ -1,52 +0,0 @@
|
||||
/* "Tide" theme */
|
||||
/* TODO:
|
||||
- Convert the other themes to CSS Variables
|
||||
- Allow user to set default CSS theme in JS config
|
||||
- Export the themes as identical JS objects
|
||||
- For theme switcher, update root-level CSS properties via JS (https://medium.com/@_bengarrison/accessing-and-modifying-css-variables-with-javascript-2ccb735bbff0)
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Interface UI Colors */
|
||||
--default-color: #9CCEF9;
|
||||
--hover-color: #ffffff;
|
||||
--active-color: #20A5D6;
|
||||
--ui-border-color: #44626F;
|
||||
--ui-border-color-dark: #3C5D80;
|
||||
--ui-border-color-active: #00a4d9;
|
||||
--primary-background-color: #000000;
|
||||
--box-background-color: #3E5975;
|
||||
|
||||
/* Common palette */
|
||||
--ui-yellow: #E29E4A;
|
||||
--ui-sky-blue: #6FBDE2;
|
||||
/* State palette */
|
||||
--ui-state-error: #FFCCCC;
|
||||
--ui-state-error-border: #993333;
|
||||
--ui-state-error-text: #661111;
|
||||
--ui-gray-light: #516873;
|
||||
--ui-gray: #263340;
|
||||
--ui-gray-dark: #16202B;
|
||||
--ui-gray-darker: #151A1F;
|
||||
--ui-gray-darkest: #14202A;
|
||||
|
||||
/* Text Colors */
|
||||
--text-color-active: #000000;
|
||||
--text-primary-color: #ffffff;
|
||||
--text-secondary-color: #91b9cd;
|
||||
--large-numbers-color: #6fbde2;
|
||||
--text-disabled-color: #878787;
|
||||
|
||||
--input-background-color: #2c363f;
|
||||
--input-placeholder-color: #d3d3d3;
|
||||
|
||||
--table-hover-color: #2c363f;
|
||||
--table-text-primary-color: #ffffff;
|
||||
--table-text-secondary-color: #91b9cd;
|
||||
|
||||
--large-numbers-color:#6FBDE2;
|
||||
|
||||
--state-error: #FFCCCC;
|
||||
--state-error-border: #FFCCCC;
|
||||
--state-error-text: #FFCCCC;
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
/* Sizes */
|
||||
:root {
|
||||
--top-bar-height: 40px;
|
||||
--top-bar-expanded-height: 160px;
|
||||
--toolbar-height: 78px;
|
||||
--toolbar-drawer-height: 62px;
|
||||
--left-sidebar-menu-width: 307px;
|
||||
--right-sidebar-menu-width: 323px;
|
||||
--study-list-padding: 8%;
|
||||
--study-list-padding-medium-screen: 10px;
|
||||
}
|
||||
|
||||
/* Fonts */
|
||||
:root {
|
||||
--logo-font-family: "Sanchez";
|
||||
--logo-font-weight: 300;
|
||||
}
|
||||
|
||||
/* Transitions */
|
||||
:root {
|
||||
--transition-duration: 0.3s;
|
||||
--transition-effect: ease;
|
||||
--sidebar-transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* Thicknesses */
|
||||
:root {
|
||||
--viewport-border-thickness: 1px;
|
||||
--ui-border-thickness: 1px;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"ie": "11"
|
||||
}
|
||||
}],
|
||||
"@babel/preset-react"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-transform-runtime"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
23
Packages-react/extensions/OHIFDicomMicroscopyExtension/.gitignore
vendored
Normal file
23
Packages-react/extensions/OHIFDicomMicroscopyExtension/.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
||||
# builds
|
||||
build
|
||||
dist
|
||||
.rpt2_cache
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.idea
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 9
|
||||
- 8
|
||||
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Open Health Imaging Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "ohif-dicom-microscopy-extension",
|
||||
"version": "0.0.3",
|
||||
"description": "OHIF extension for Dicom Microscopy",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
"repository": "OHIF/Viewers",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.es.js",
|
||||
"jsnext:main": "dist/index.es.js",
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"start": "rollup -c -w",
|
||||
"lint": "eslint -c .eslintrc --fix src && prettier --single-quote --write src/**/*.{js,jsx,json,css}"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.0.0 || ^16.0.0",
|
||||
"react-dom": "^15.0.0 || ^16.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.2.2",
|
||||
"@babel/plugin-external-helpers": "^7.2.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.2.3",
|
||||
"@babel/plugin-transform-runtime": "^7.2.0",
|
||||
"@babel/preset-env": "^7.2.3",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@svgr/rollup": "^4.1.0",
|
||||
"babel-eslint": "^9.0.0",
|
||||
"cross-env": "^5.2.0",
|
||||
"eslint": "5.6.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-node": "^8.0.0",
|
||||
"eslint-plugin-promise": "^4.0.1",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"gh-pages": "^2.0.1",
|
||||
"husky": "^1.3.1",
|
||||
"lint-staged": "^8.1.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"prettier": "^1.15.3",
|
||||
"react": "^16.6.3",
|
||||
"react-dom": "^16.6.3",
|
||||
"react-scripts": "^2.1.2",
|
||||
"rollup": "^0.68.2",
|
||||
"rollup-plugin-babel": "^4.2.0",
|
||||
"rollup-plugin-commonjs": "^9.2.0",
|
||||
"rollup-plugin-node-builtins": "^2.1.2",
|
||||
"rollup-plugin-node-resolve": "^4.0.0",
|
||||
"rollup-plugin-peer-deps-external": "^2.2.0",
|
||||
"rollup-plugin-postcss": "^1.6.3",
|
||||
"rollup-plugin-url": "^2.1.0",
|
||||
"stylelint": "^9.9.0",
|
||||
"stylelint-config-recommended": "^2.1.0",
|
||||
"stylus": "^0.54.5"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.{js,jsx,json,css}": [
|
||||
"prettier --single-quote --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
],
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"classnames": "^2.2.6",
|
||||
"dicom-microscopy-viewer": "^0.2.0",
|
||||
"dicomweb-client": "^0.4.1",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"ohif-core": "^0.2.3",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
import babel from 'rollup-plugin-babel'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import external from 'rollup-plugin-peer-deps-external'
|
||||
import postcss from 'rollup-plugin-postcss'
|
||||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import url from 'rollup-plugin-url'
|
||||
import svgr from '@svgr/rollup'
|
||||
import pkg from './package.json'
|
||||
// Deal with https://github.com/rollup/rollup-plugin-commonjs/issues/297
|
||||
import builtins from 'rollup-plugin-node-builtins';
|
||||
|
||||
export default {
|
||||
input: 'src/index.js',
|
||||
output: [
|
||||
{
|
||||
file: pkg.main,
|
||||
format: 'umd',
|
||||
name: 'ohif-dicom-pdf-extension',
|
||||
sourcemap: true,
|
||||
exports: 'named',
|
||||
globals: {
|
||||
'react': 'React',
|
||||
'react-dom': 'ReactDOM'
|
||||
}
|
||||
},
|
||||
{
|
||||
file: pkg.module,
|
||||
format: 'es',
|
||||
sourcemap: true
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
builtins(),
|
||||
external(),
|
||||
postcss({
|
||||
modules: false
|
||||
}),
|
||||
url(),
|
||||
svgr(),
|
||||
babel({
|
||||
exclude: 'node_modules/**',
|
||||
plugins: [ '@babel/external-helpers' ],
|
||||
externalHelpers: true,
|
||||
runtimeHelpers: true
|
||||
}),
|
||||
resolve(),
|
||||
commonjs({
|
||||
include: 'node_modules/**',
|
||||
namedExports: {
|
||||
'node_modules/dicom-microscopy-viewer/build/dicom-microscopy-viewer.js': [
|
||||
'api'
|
||||
]
|
||||
}
|
||||
})
|
||||
],
|
||||
external: ['hammerjs']
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
import OHIF from 'ohif-core';
|
||||
import { api } from 'dicomweb-client';
|
||||
|
||||
const { plugins, utils } = OHIF;
|
||||
const { PLUGIN_TYPES } = plugins;
|
||||
@ -8,20 +7,12 @@ const SOP_CLASS_UIDS = {
|
||||
VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6'
|
||||
};
|
||||
|
||||
const dwc = api.DICOMwebClient;
|
||||
|
||||
const DicomMicrscopySopClassHandlerPlugin = {
|
||||
const DicomMicrscopySopClassHandler = {
|
||||
id: 'DicomMicroscopySopClassHandlerPlugin',
|
||||
type: PLUGIN_TYPES.SOP_CLASS_HANDLER,
|
||||
sopClassUids: [SOP_CLASS_UIDS.VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE],
|
||||
getDisplaySetFromSeries(series, study) {
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient) {
|
||||
const instance = series.getFirstInstance();
|
||||
const headers = OHIF.DICOMWeb.getAuthorizationHeader();
|
||||
|
||||
const dicomWebClient = new dwc({
|
||||
url: study.getData().wadoRoot,
|
||||
headers
|
||||
});
|
||||
|
||||
// Note: We are passing the dicomweb client into each viewport!
|
||||
|
||||
@ -36,4 +27,4 @@ const DicomMicrscopySopClassHandlerPlugin = {
|
||||
}
|
||||
};
|
||||
|
||||
export default DicomMicrscopySopClassHandlerPlugin;
|
||||
export default DicomMicrscopySopClassHandler;
|
||||
@ -0,0 +1,27 @@
|
||||
import DicomMicroscopyViewport from './DicomMicroscopyViewport.js';
|
||||
import DicomMicroscopySopClassHandler from './DicomMicroscopySopClassHandler.js';
|
||||
|
||||
export default class OHIFDicomMicroscopyExtension {
|
||||
/**
|
||||
* Extension ID is a unique id, might be used for namespacing extension specific redux actions/reducers (?)
|
||||
*/
|
||||
getExtensionId() {
|
||||
return 'microscopy';
|
||||
}
|
||||
|
||||
getViewportModule() {
|
||||
return DicomMicroscopyViewport;
|
||||
}
|
||||
|
||||
getSopClassHandler() {
|
||||
return DicomMicroscopySopClassHandler;
|
||||
}
|
||||
|
||||
getPanelModule() {
|
||||
return null;
|
||||
}
|
||||
|
||||
getToolbarModule() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
import OHIFDicomMicroscopyExtension from './OHIFDicomMicroscopyExtension.js';
|
||||
|
||||
export {
|
||||
OHIFDicomMicroscopyExtension
|
||||
};
|
||||
|
||||
export default OHIFDicomMicroscopyExtension;
|
||||
File diff suppressed because it is too large
Load Diff
14
Packages-react/extensions/OHIFDicomPDFExtension/.babelrc
Normal file
14
Packages-react/extensions/OHIFDicomPDFExtension/.babelrc
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"ie": "11"
|
||||
}
|
||||
}],
|
||||
"@babel/preset-react"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-transform-runtime"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
16
Packages-react/extensions/OHIFDicomPDFExtension/.eslintrc
Normal file
16
Packages-react/extensions/OHIFDicomPDFExtension/.eslintrc
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": [
|
||||
"react-app",
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
"env": {
|
||||
"jest": true
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect",
|
||||
},
|
||||
},
|
||||
}
|
||||
23
Packages-react/extensions/OHIFDicomPDFExtension/.gitignore
vendored
Normal file
23
Packages-react/extensions/OHIFDicomPDFExtension/.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
||||
# builds
|
||||
build
|
||||
dist
|
||||
.rpt2_cache
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.idea
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 9
|
||||
- 8
|
||||
21
Packages-react/extensions/OHIFDicomPDFExtension/LICENSE
Normal file
21
Packages-react/extensions/OHIFDicomPDFExtension/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Open Health Imaging Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
86
Packages-react/extensions/OHIFDicomPDFExtension/package.json
Normal file
86
Packages-react/extensions/OHIFDicomPDFExtension/package.json
Normal file
@ -0,0 +1,86 @@
|
||||
{
|
||||
"name": "ohif-dicom-pdf-extension",
|
||||
"version": "0.0.3",
|
||||
"description": "OHIF extension for Dicom PDF",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
"repository": "OHIF/Viewers",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.es.js",
|
||||
"jsnext:main": "dist/index.es.js",
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"start": "rollup -c -w",
|
||||
"lint": "eslint -c .eslintrc --fix src && prettier --single-quote --write src/**/*.{js,jsx,json,css}"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.0.0 || ^16.0.0",
|
||||
"react-dom": "^15.0.0 || ^16.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.2.2",
|
||||
"@babel/plugin-external-helpers": "^7.2.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.2.3",
|
||||
"@babel/plugin-transform-runtime": "^7.2.0",
|
||||
"@babel/preset-env": "^7.2.3",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@svgr/rollup": "^4.1.0",
|
||||
"babel-eslint": "^9.0.0",
|
||||
"cross-env": "^5.2.0",
|
||||
"eslint": "5.6.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-node": "^8.0.0",
|
||||
"eslint-plugin-promise": "^4.0.1",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"gh-pages": "^2.0.1",
|
||||
"husky": "^1.3.1",
|
||||
"lint-staged": "^8.1.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"prettier": "^1.15.3",
|
||||
"react": "^16.6.3",
|
||||
"react-dom": "^16.6.3",
|
||||
"react-scripts": "^2.1.2",
|
||||
"rollup": "^0.68.2",
|
||||
"rollup-plugin-babel": "^4.2.0",
|
||||
"rollup-plugin-commonjs": "^9.2.0",
|
||||
"rollup-plugin-node-builtins": "^2.1.2",
|
||||
"rollup-plugin-node-resolve": "^4.0.0",
|
||||
"rollup-plugin-peer-deps-external": "^2.2.0",
|
||||
"rollup-plugin-postcss": "^1.6.3",
|
||||
"rollup-plugin-url": "^2.1.0",
|
||||
"stylelint": "^9.9.0",
|
||||
"stylelint-config-recommended": "^2.1.0",
|
||||
"stylus": "^0.54.5"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.{js,jsx,json,css}": [
|
||||
"prettier --single-quote --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
],
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"classnames": "^2.2.6",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"ohif-core": "^0.2.3",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
import babel from 'rollup-plugin-babel'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import external from 'rollup-plugin-peer-deps-external'
|
||||
import postcss from 'rollup-plugin-postcss'
|
||||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import url from 'rollup-plugin-url'
|
||||
import svgr from '@svgr/rollup'
|
||||
import pkg from './package.json'
|
||||
// Deal with https://github.com/rollup/rollup-plugin-commonjs/issues/297
|
||||
import builtins from 'rollup-plugin-node-builtins';
|
||||
|
||||
export default {
|
||||
input: 'src/index.js',
|
||||
output: [
|
||||
{
|
||||
file: pkg.main,
|
||||
format: 'umd',
|
||||
name: 'ohif-dicom-pdf-extension',
|
||||
sourcemap: true,
|
||||
exports: 'named',
|
||||
globals: {
|
||||
'react': 'React',
|
||||
'react-dom': 'ReactDOM'
|
||||
}
|
||||
},
|
||||
{
|
||||
file: pkg.module,
|
||||
format: 'es',
|
||||
sourcemap: true
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
builtins(),
|
||||
external(),
|
||||
postcss({
|
||||
modules: false
|
||||
}),
|
||||
url(),
|
||||
svgr(),
|
||||
babel({
|
||||
exclude: 'node_modules/**',
|
||||
plugins: [ '@babel/external-helpers' ],
|
||||
externalHelpers: true,
|
||||
runtimeHelpers: true
|
||||
}),
|
||||
resolve(),
|
||||
commonjs()
|
||||
],
|
||||
external: ['hammerjs']
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
import OHIFDicomPDFViewport from './OHIFDicomPDFViewport.js';
|
||||
import OHIFDicomPDFSopClassHandler from './OHIFDicomPDFSopClassHandler.js';
|
||||
|
||||
export default class OHIFDicomPDFExtension {
|
||||
/**
|
||||
* Extension ID is a unique id, might be used for namespacing extension specific redux actions/reducers (?)
|
||||
*/
|
||||
getExtensionId() {
|
||||
return 'pdf';
|
||||
}
|
||||
|
||||
getViewportModule() {
|
||||
return OHIFDicomPDFViewport;
|
||||
}
|
||||
|
||||
getSopClassHandler() {
|
||||
return OHIFDicomPDFSopClassHandler;
|
||||
}
|
||||
|
||||
getPanelModuleDefinition() {
|
||||
return null;
|
||||
}
|
||||
|
||||
getToolbarModuleDefinition() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -8,13 +8,14 @@ const SOP_CLASS_UIDS = {
|
||||
ENCAPSULATED_PDF: '1.2.840.10008.5.1.4.1.1.104.1'
|
||||
};
|
||||
|
||||
const OHIFDicomPDFSopClassHandlerPlugin = {
|
||||
const OHIFDicomPDFSopClassHandler = {
|
||||
id: 'OHIFDicomPDFSopClassHandlerPlugin',
|
||||
type: PLUGIN_TYPES.SOP_CLASS_HANDLER,
|
||||
sopClassUids: [
|
||||
SOP_CLASS_UIDS.ENCAPSULATED_PDF
|
||||
],
|
||||
getDisplaySetFromSeries(series, study) {
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient, authorizationHeaders) {
|
||||
debugger;
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
return {
|
||||
@ -24,9 +25,10 @@ const OHIFDicomPDFSopClassHandlerPlugin = {
|
||||
wadoUri: instance.getData().wadouri,
|
||||
sopInstanceUid: instance.getSOPInstanceUID(),
|
||||
seriesInstanceUid: series.getSeriesInstanceUID(),
|
||||
studyInstanceUid: study.getStudyInstanceUID()
|
||||
studyInstanceUid: study.getStudyInstanceUID(),
|
||||
authorizationHeaders: authorizationHeaders
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default OHIFDicomPDFSopClassHandlerPlugin;
|
||||
export default OHIFDicomPDFSopClassHandler;
|
||||
@ -1,12 +1,12 @@
|
||||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
import OHIFComponentPlugin from '../OHIFComponentPlugin.js';
|
||||
import OHIFComponentPlugin from './OHIFComponentPlugin.js';
|
||||
import DicomPDFViewport from './DicomPDFViewport';
|
||||
|
||||
const { DICOMWeb } = OHIF;
|
||||
|
||||
class OHIFDicomPDFViewportPlugin extends Component {
|
||||
class OHIFDicomPDFViewport extends Component {
|
||||
static propTypes = {
|
||||
studies: PropTypes.object,
|
||||
displaySet: PropTypes.object,
|
||||
@ -18,21 +18,21 @@ class OHIFDicomPDFViewportPlugin extends Component {
|
||||
error: null
|
||||
}
|
||||
|
||||
static id = 'DicomPDFViewportPlugin';
|
||||
static id = 'DicomPDFViewportPDF';
|
||||
|
||||
static init() {
|
||||
console.log('DicomPDFViewportPlugin init()');
|
||||
console.log('DicomPDFViewport init()');
|
||||
}
|
||||
|
||||
static destroy() {
|
||||
console.log('DicomPDFViewportPlugin destroy()');
|
||||
console.log('DicomPDFViewport destroy()');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { displaySet } = this.props.viewportData;
|
||||
const { studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri } = displaySet;
|
||||
const { studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri, authorizationHeaders} = displaySet;
|
||||
|
||||
this.retrieveDicomData(studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri).then(byteArray => {
|
||||
this.retrieveDicomData(studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri, authorizationHeaders).then(byteArray => {
|
||||
this.setState({
|
||||
byteArray
|
||||
});
|
||||
@ -45,21 +45,20 @@ class OHIFDicomPDFViewportPlugin extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
retrieveDicomData(studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri) {
|
||||
retrieveDicomData(studyInstanceUid, seriesInstanceUid, sopInstanceUid, wadoRoot, wadoUri, authorizationHeaders) {
|
||||
// TODO: Passing in a lot of data we aren't using
|
||||
|
||||
// TODO: Authorization header depends on the server. If we ever have multiple servers
|
||||
// we will need to figure out how / when to pass this information in.
|
||||
return fetch(wadoUri, {
|
||||
headers: DICOMWeb.getAuthorizationHeader()
|
||||
headers: authorizationHeaders
|
||||
}).then(response => response.arrayBuffer()).then(arraybuffer => {
|
||||
debugger;
|
||||
return new Uint8Array(arraybuffer);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { id, init, destroy } = OHIFDicomPDFViewportPlugin;
|
||||
const { id, init, destroy } = OHIFDicomPDFViewport;
|
||||
const pluginProps = { id, init, destroy };
|
||||
|
||||
return (
|
||||
@ -73,5 +72,4 @@ class OHIFDicomPDFViewportPlugin extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default OHIFDicomPDFViewportPlugin;
|
||||
export default OHIFDicomPDFViewport;
|
||||
@ -0,0 +1,7 @@
|
||||
import OHIFDicomPDFExtension from './OHIFDicomPDFExtension.js';
|
||||
|
||||
export {
|
||||
OHIFDicomPDFExtension
|
||||
};
|
||||
|
||||
export default OHIFDicomPDFExtension;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user