Compare commits

..
30 Commits
Author SHA1 Message Date
David Wire e73d009c21 fix(package.json): Resolve react/react-dom dependency conflict for embedded users (#734)
* fix(package.json): Resolve react/react-dom dependency conflict for embedded users

Some of the recent changes around the script-tag support for ohif/Viewers included moving react and
react-dom from peerDependencies to dependencies. This caused an error for embedded consumers of the
viewer because there could be multiple versions of react included. The error in the console points
to this link: https://reactjs.org/warnings/invalid-hook-call-warning.html. These changes are
necessary to resolve the issue for embedded users and don't seem to break the standalone version
either.

* fix(script-tag/index.html): Add `react` and `react-dom` as external scripts for cypress tests

The cyrpress tests won't pass unless we add the `react` and `react-dom` dependencies as external
scripts since they're no longer first order depdencies.
2019-07-30 08:30:23 +02:00
Erik Ziegler f826341631 fix(package.json): Bump VTK extension to fix jitter issues in MPR view 2019-07-29 21:20:11 +02:00
Erik Ziegler f8b52d0fee @ohif/extension-vtk: Update VTK to 9.0.1 2019-07-29 21:20:11 +02:00
Erik Ziegler 0e78836d55 fix(StandaloneRouter): Fix broken query string parsing in StandaloneRouter. Pass location object to
fix #731
2019-07-29 17:26:17 +02:00
Egor Lezhnin 40bf1a2efd feat(fuzzyMatching): fuzzymatching for query parameters if server config indicates support 2019-07-29 09:56:07 -04:00
Erik Ziegler 02c732aa15 fix(config): Stop crashes if window.config is not defined when script-tag viewer is loaded 2019-07-29 14:42:21 +02:00
Erik Ziegler c5f532159b ci(cypress): Remove duplicate React versions in end-to-end tests 2019-07-29 10:45:38 +02:00
Erik Ziegler b1df019c49 fix(package.json): Update @ohif/i18n to 0.2.3 2019-07-29 10:03:48 +02:00
Erik Ziegler 54b70e5fa4 @ohif/i18n: Update i18n locales from Locize source of truth (0.2.3) 2019-07-29 10:03:48 +02:00
Erik Ziegler 5802cf18eb fix(script-tag): Include React and ReactDOM as dependencies and add installViewer function to simplify script tag usage. (#721) 2019-07-29 08:20:07 +02:00
Danny Brown 210c2e8d2c fix: clear annotations toolbar button 2019-07-26 16:38:37 -04:00
Erik Ziegler da318c9c8c feat(DicomUploader): Make DICOM Uploader work with all DICOMWeb servers (#717)
* feat(DicomUploader): Make DICOM Uploader work with all DICOMWeb servers

* Bump viewerbase version
2019-07-26 15:04:28 +02:00
João Felipe de Medeiros Moreira 903c41d26f fix(Bootstrap): Remove bootstrap dependency (#708)
fix #636
2019-07-26 13:41:29 +02:00
Danny Brown ba261a0d54 fix: support for next/previous image hotkeys via cornerstone extension update
* Bump @ohif/extenions-cornerstone react-cornerstone-viewport dep and cut release

* fix: bump @ohif/extension-cornerstone version to latest

* Catching the yarn lock changes

* Cut new release for cornerstone extension and update Viewers to use it

* Add new commands to netlify dmeo

* Flip directions for next/previous image
2019-07-23 15:39:56 -04:00
David Wire 3398a894a3 feat(commandsModule): Add previousImage and nextImage actions and commands (#710)
* feat(commandsModule): Add `previousImage` and `nextImage` actions and commands

This change adds the keybindings for previousImage (down) and nextImage (up) to the default
configuration and adds the command and action necessary to support it. This pull request is
dependent upon https://github.com/cornerstonejs/cornerstoneTools/pull/1025 which exports the scroll
utility it uses.

* style(default.js): Switch tabs to spaces

* fix(commandsModule): import `scroll` through cornerstoneTools.import
2019-07-23 14:52:29 -04:00
Danny Brown 5a13194203 fix(react-cornerstone-viewport): Viewport resizes on stack scroll (#709)
* Bump @ohif/extenions-cornerstone react-cornerstone-viewport dep and cut release

* fix: bump @ohif/extension-cornerstone version to latest

* Catching the yarn lock changes
2019-07-23 13:00:02 -04:00
Erik Ziegler a2cc477a1a fix(package.json): Update @ohif/extension-microscopy to 0.0.12 2019-07-22 15:47:45 +02:00
Erik Ziegler 2e7a59f7f8 @ohif/extension-dicom-microscopy: Update dicom-microscopy-viewer dependency to 0.6.1 2019-07-22 15:47:45 +02:00
Erik Ziegler 83d7d59954 fix(package.json): Update ohif-core and dicomweb-client to fix Palette Color BulkData retrieval (#703) 2019-07-22 15:09:55 +02:00
Erik Ziegler 163fee8941 fix(Viewer): Set thumbnail to use altImageText for SEG images (#699) 2019-07-22 13:29:12 +02:00
Erik Ziegler f547fdf832 fix(OpenIDConnect): Stop storing tokens in sessionStorage. Prefix OIDC routes automatically. Add logout button (#698) 2019-07-21 16:43:42 +02:00
Erik Ziegler ac347849d0 fix(config/google.js): Add metadata endpoints and signingKeys to avoid CORS errors on Google's certificate endpoint (#696) 2019-07-21 10:46:11 +02:00
Erik Ziegler 54e0e32e22 fix(package.json): Bump ohif-core, extension-microscopy, and dicomweb-client (#697) 2019-07-21 10:04:07 +02:00
Erik Ziegler 690156d4b6 @ohif/extension-dicom-microscopy: Update dicom-microscopy-viewer dependency (#695) 2019-07-21 09:34:16 +02:00
Erik Ziegler 3b5fdb678a docs(googleCloud): Fix port in docs to correspond to defaults in config (Thanks @Stormert) 2019-07-21 09:13:23 +02:00
Erik Ziegler e7604c4418 fix(Viewer): Switch to middle of stack for image thumbnail 2019-07-20 16:41:27 +02:00
Erik Ziegler 71f11a4856 fix(package.json): Update microscopy, pdf, and html extensions to fix thumbnail labels 2019-07-19 18:24:43 +02:00
Erik Ziegler ae5d0587db @ohif/extension-dicom-pdf: Return modality from sopClassHandler (0.0.8) 2019-07-19 18:24:43 +02:00
Erik Ziegler fbc06329e2 @ohif/extension-dicom-html: Return modality from sopClassHandler (0.0.4) 2019-07-19 18:24:43 +02:00
Erik Ziegler 86732c8186 @ohif/extension-dicom-microscopy: Return modality from sopClassHandler (0.0.10) 2019-07-19 18:24:43 +02:00
85 changed files with 695 additions and 374 deletions

No files matched your search

+3
View File
@@ -28,3 +28,6 @@ docker/dcm4che/dcm4che-arc
# Cypress test results
cypress/videos/
# Locize settings
.locize
+3 -24
View File
@@ -17,9 +17,6 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css"
integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous" />
<title>OHIF Standalone Viewer</title>
</head>
@@ -31,24 +28,12 @@
<!-- Load React. -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="/dist/index.umd.js" crossorigin></script>
<script>
// Workaround to deal with react-router-dom complaining
// if process.env is not defined. Must be run before
// ohif-viewer package is included.
"use strict";
var process = {
env: {
NODE_ENV: "production"
}
};
window.process = process;
window.config = {
// default: '/'
routerBasename: '/',
// default: ''
relativeWebWorkerScriptsPath: '',
servers: {
dicomWeb: [
{
@@ -63,14 +48,8 @@
],
},
}
</script>
<script src="/dist/index.umd.js" crossorigin></script>
<script>
var Viewer = window.OHIFStandaloneViewer.App;
var app = React.createElement(Viewer, window.config, null);
ReactDOM.render(app, document.getElementById("root"));
window.OHIFStandaloneViewer.installViewer(window.config);
</script>
</body>
@@ -35,10 +35,10 @@ Images can even be transcoded on the fly if this is desired.
- Choose the "Web Application" type
- Set up an
[OAuth 2.0 Client ID](https://support.google.com/cloud/answer/6158849?hl=en)
- Add your domain (e.g. `http://localhost:3000`) to Authorized JavaScript
- Add your domain (e.g. `http://localhost:5000`) to Authorized JavaScript
origins.
- Add your domain, plus `callback` (e.g.
`http://localhost:3000/callback`) to Authorized Redirect URIs.
`http://localhost:5000/callback`) to Authorized Redirect URIs.
- Save your Client ID for later.
- (Optional): Enable Public Datasets that are being hosted by Google:
@@ -67,5 +67,5 @@ method to get up and running.
Client IDs look like `xyz.apps.googleusercontent.com`.
```bash
docker run --env CLIENT_ID=$CLIENT_ID --publish 3000:80 ohif/viewer:latest
docker run --env CLIENT_ID=$CLIENT_ID --publish 5000:80 ohif/viewer:latest
```
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "0.0.41",
"version": "0.0.43",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@@ -39,7 +39,7 @@
"@babel/runtime": "^7.2.0",
"classnames": "^2.2.6",
"lodash.throttle": "^4.1.1",
"react-cornerstone-viewport": "0.1.31"
"react-cornerstone-viewport": "0.1.32"
},
"devDependencies": {
"@babel/core": "^7.2.2",
@@ -1,6 +1,7 @@
import cornerstone from 'cornerstone-core';
import cornerstoneTools from 'cornerstone-tools';
import OHIF from 'ohif-core';
const scroll = cornerstoneTools.import('util/scroll');
const actions = {
rotateViewport: ({ viewports, rotation }) => {
@@ -145,6 +146,22 @@ const actions = {
});
});
},
nextImage: ({ viewports }) => {
const enabledElement = _getActiveViewportEnabledElement(
viewports.viewportSpecificData,
viewports.activeViewportIndex
);
scroll(enabledElement, 1);
},
previousImage: ({ viewports }) => {
const enabledElement = _getActiveViewportEnabledElement(
viewports.viewportSpecificData,
viewports.activeViewportIndex
);
scroll(enabledElement, -1);
}
};
const definitions = {
@@ -198,7 +215,16 @@ const definitions = {
storeContexts: ['viewports'],
options: {},
},
// TODO: Next/Previous image
nextImage: {
commandFn: actions.nextImage,
storeContexts: ['viewports'],
options: {},
},
previousImage: {
commandFn: actions.previousImage,
storeContexts: ['viewports'],
options: {},
},
// TODO: First/Last image
// Next/Previous series/DisplaySet
nextViewportDisplaySet: {
@@ -4421,10 +4421,10 @@ randomfill@^1.0.3:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
react-cornerstone-viewport@0.1.31:
version "0.1.31"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.31.tgz#ded8a688dad273846078b3336b72f59f134f30f2"
integrity sha512-e2A4FkoSpZiB2iwnYjC2UI98+KPY03ODp2jKmuJDE3pn3cIE581Bg/0NQyCKoAnRMO/TUsZSoq/GYTw/1C3kUg==
react-cornerstone-viewport@0.1.32:
version "0.1.32"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.32.tgz#0777d1f3497b27b017aa5eae3d1d4c078383219b"
integrity sha512-NdFsRq4kMgE6zpZo+DEnlQzC2B6OxOgFTkLCTDTYif0IxoXzKhngXP4xujwrUGjud98mTQKtiJOM0ah/fns3og==
dependencies:
lodash.debounce "^4.0.8"
moment "^2.23.0"
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-html",
"version": "0.0.3",
"version": "0.0.4",
"description": "OHIF extension for rendering structured reports to HTML",
"author": "OHIF",
"license": "MIT",
@@ -24,6 +24,7 @@ const OHIFDicomHtmlSopClassHandler = {
return {
plugin: 'html',
modality: 'SR',
displaySetInstanceUid: utils.guid(),
wadoRoot: study.getData().wadoRoot,
wadoUri: instance.getData().wadouri,
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-microscopy",
"version": "0.0.9",
"version": "0.0.12",
"description": "OHIF extension for Dicom Microscopy",
"author": "OHIF",
"license": "MIT",
@@ -82,7 +82,7 @@
"dependencies": {
"@babel/runtime": "^7.2.0",
"classnames": "^2.2.6",
"dicom-microscopy-viewer": "0.5.0",
"dicom-microscopy-viewer": "0.6.1",
"lodash.debounce": "^4.0.8"
}
}
@@ -16,6 +16,7 @@ const DicomMicroscopySopClassHandler = {
return {
plugin: 'microscopy',
modality: 'SM',
displaySetInstanceUid: utils.guid(),
dicomWebClient,
sopInstanceUid: instance.getSOPInstanceUID(),
@@ -1617,18 +1617,18 @@ des.js@^1.0.0:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
dicom-microscopy-viewer@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/dicom-microscopy-viewer/-/dicom-microscopy-viewer-0.5.0.tgz#e4f74261337d8a78d51490af0d17edc63997e619"
integrity sha512-r3BPLBvexv9v/Rr/FBTgXgp7orIFKLWW5uYM6IsYpz36ttU84Edk7Z2GAyk6887QNsfEMLzYV+5ik6HRrMg0cA==
dicom-microscopy-viewer@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/dicom-microscopy-viewer/-/dicom-microscopy-viewer-0.6.1.tgz#7b593da241d048154a9c1ebcbccf389742c2af18"
integrity sha512-ZQ1QsQswAh7Yw01ba3LZXCIh7WnEYDjhSxJt9vdfRZ5iHlbgW2ghvUHR7GP80UnWJg335scNmIcqJvwxVjlIsg==
dependencies:
dicomweb-client "^0.4.2"
dicomweb-client "^0.5.2"
ol "^5.3.0"
dicomweb-client@^0.4.2:
version "0.4.4"
resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.4.4.tgz#0ca0c7706556f3114330a3c40946ee66808148e4"
integrity sha512-5S7wLYxQgHnOyEgR1zlZlt79IjzOk+YDB/Jjzte6ijRZsAoj9RUiIZcsTyxvBD9gLMYs/954n2kYHdbz83Xbtw==
dicomweb-client@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.5.2.tgz#aa5a4a6a5044b0702bb0a8a2662c86cd16901951"
integrity sha512-e11n2+g7HfBuMyopWq76W11eSZJ707g4U1XiO8URA+23aoe0g1kGAtlPB29NKXl7zX7RznTJ7wfRBxFkW6EJDA==
diffie-hellman@^5.0.0:
version "5.0.3"
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-pdf",
"version": "0.0.7",
"version": "0.0.8",
"description": "OHIF extension for Dicom PDF",
"author": "OHIF",
"license": "MIT",
@@ -14,6 +14,7 @@ const OHIFDicomPDFSopClassHandler = {
return {
plugin: 'pdf',
modality: 'DOC',
displaySetInstanceUid: utils.guid(),
wadoRoot: study.getData().wadoRoot,
wadoUri: instance.getData().wadouri,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/i18n",
"version": "0.2.2",
"version": "0.2.3",
"description": "OHIF extension for internationalization",
"author": "OHIF",
"license": "MIT",
+2
View File
@@ -1,4 +1,6 @@
rm -rf src/locales/
mkdir -p src/locales/
cd src/locales/
npx locize --config-path ../../.locize download --ver latest
cd ../../
node ./writeLocaleIndexFiles.js
@@ -39,4 +39,4 @@
"Stop": "$t(Common:Stop)",
"Themes": "Themes",
"Zoom": "Zoom"
}
}
@@ -5,4 +5,4 @@
"Skip to first image": "Skip to first $t(Common:Image)",
"Skip to last image": "Skip, to last $t(Common:Image)",
"fps": "fps"
}
}
@@ -1,10 +1,15 @@
{
"Image": "Image",
"Layout": "Layout",
"Measurements": "Measurements",
"More": "More",
"Next": "Next",
"Play": "Play",
"Previous": "Previous",
"Reset": "Reset",
"Stop": "Stop"
}
"RowsPerPage": "rows per page",
"Series": "Series",
"Show": "Show",
"Stop": "Stop",
"StudyDate": "Study Date"
}
@@ -5,4 +5,4 @@
"Options": "Options",
"Preferences": "Preferences",
"Study list": "Study list"
}
}
@@ -6,4 +6,4 @@
"NonTargets": "NonTargets",
"Relabel": "Relabel",
"Targets": "Targets"
}
}
@@ -0,0 +1,10 @@
{
"AccessionNumber": "Accession #",
"Empty": "Empty",
"MRN": "MRN",
"Modality": "Modality",
"PatientName": "Patient Name",
"StudyDate": "Study Date",
"StudyDescription": "Description",
"StudyList": "Study List"
}
@@ -3,4 +3,4 @@
"Reset to Defaults": "$t(Buttons:Reset to Defaults)",
"Save": "$t(Buttons:Save)",
"User Preferences": "User Preferences"
}
}
@@ -1,17 +1,19 @@
import Buttons from './Buttons.json';
import CineDialog from './CineDialog.json';
import Common from './Common.json';
import Header from './Header.json';
import MeasurementTable from './MeasurementTable.json';
import UserPreferencesModal from './UserPreferencesModal.json';
import Buttons from "./Buttons.json";
import CineDialog from "./CineDialog.json";
import Common from "./Common.json";
import Header from "./Header.json";
import MeasurementTable from "./MeasurementTable.json";
import StudyList from "./StudyList.json";
import UserPreferencesModal from "./UserPreferencesModal.json";
export default {
export default {
'en-US': {
Buttons,
CineDialog,
Common,
Header,
MeasurementTable,
StudyList,
UserPreferencesModal,
},
};
}
};
@@ -1,27 +1,27 @@
{
"Acquired": "Acquired",
"Acquired": "Adquirido",
"Angle": "Ángulo",
"Axial": "Axial",
"Bidirectional": "Bidirectional",
"Brush": "Escoba",
"Bidirectional": "Bidireccional",
"Brush": "Cepillo",
"CINE": "CINE",
"Cancel": "Cancelar",
"Circle": "Circle",
"Circle": "Círculo",
"Clear": "Limpiar",
"Coronal": "Coronal",
"Crosshairs": "Cruces",
"Crosshairs": "Punto de mira",
"Ellipse": "Elipse",
"Elliptical": "Elliptical",
"Flip H": "Espejo Hor.",
"Flip V": "Espejo Ver.",
"Freehand": "Freehand",
"Invert": "Invertido",
"Elliptical": "Elíptico",
"Flip H": "Espejo H",
"Flip V": "Espejo V",
"Freehand": "Mano alzada",
"Invert": "Invertir",
"Layout": "$t(Common:Layout)",
"Length": "Medición",
"Length": "Longitud",
"Levels": "Niveles",
"Magnify": "Lupa",
"Magnify": "Aumentar",
"Manual": "Manual",
"Measurements": "Medidas",
"Measurements": "Mediciones",
"More": "$t(Common:More)",
"Next": "$t(Common:Next)",
"Pan": "Mover",
@@ -31,12 +31,12 @@
"ROI Window": "Ventana ROI",
"Rectangle": "Rectángulo",
"Reset": "$t(Common:Reset)",
"Reset to Defaults": "$t(Common:reset) por defectos",
"Reset to Defaults": "$t(Common:Reset) por defecto",
"Rotate Right": "Rotar ->",
"Sagittal": "Sagittal",
"Sagittal": "Sagital",
"Save": "Guardar",
"Stack Scroll": "Avance X slice",
"Stack Scroll": "Scroll en pila",
"Stop": "$t(Common:Stop)",
"Themes": "Temas",
"Zoom": "Zoom"
}
}
@@ -1,8 +1,8 @@
{
"Next image": "$t(Common:Play) $t(Common:Image)",
"Play / Stop": "$t(Common:Play) / $t(Common:Stop)",
"Previous image": "$t(Common:Previous) $t(Common:Image)",
"Skip to first image": "Avanza para la primera $t(Common:Image)",
"Skip to last image": "Pular para la ultima $t(Common:Image)",
"fps": "fps"
}
"Next image": " $t(Common:Image) $t(Common:Next)",
"Play / Stop": "$t(Common:Play) / Stop",
"Previous image": "$t(Common:Image) $t(Common:Previous)",
"Skip to first image": "Ir a la primera $t(Common:Image)",
"Skip to last image": "Ir a la última $t(Common:Image)",
"fps": "imágenes/seg."
}
@@ -1,10 +1,15 @@
{
"Image": "Imagen",
"Layout": "Esquema",
"Layout": "Disposición",
"Measurements": "Medidas",
"More": "Más",
"Next": "Próximo",
"Next": "Siguiente",
"Play": "Play",
"Previous": "Anterior",
"Reset": "Reiniciar",
"Stop": "Stop"
}
"Reset": "Resetear",
"RowsPerPage": "filas por página",
"Series": "Secuencia",
"Show": "Mostrar",
"Stop": "Detener",
"StudyDate": "Fecha de estudo"
}
@@ -1,8 +1,8 @@
{
"About": "Sobre",
"Back to Viewer": "Back to Viewer",
"INVESTIGATIONAL USE ONLY": "SOLO USO DE INVESTIGACIÓN",
"About": "Acerca de",
"Back to Viewer": "Volver al visor",
"INVESTIGATIONAL USE ONLY": "SOLO USO PARA INVESTIGACIÓN",
"Options": "Opciones",
"Preferences": "Preferencias",
"Study list": "Lista de estudio"
}
"Study list": "Lista de estudios"
}
@@ -1,9 +1,9 @@
{
"Criteria nonconformities": "Criterios de no conformidades",
"Criteria nonconformities": "Criterios disconformes",
"Delete": "Borrar",
"Description": "Descripción",
"MAX": "máximo",
"NonTargets": "NonObjetivos",
"Relabel": "Reetiquetar",
"MAX": "Máximo",
"NonTargets": "No objetivos",
"Relabel": "Re-etiquetar",
"Targets": "Objetivos"
}
}
@@ -0,0 +1,10 @@
{
"AccessionNumber": "Número de Adhesión",
"Empty": "vacío",
"MRN": "MRN",
"Modality": "Modalidad",
"PatientName": "Nombre del paciente",
"StudyDate": "Fetcha de estudio",
"StudyDescription": "Descripción",
"StudyList": "Lista de Estudio"
}
@@ -2,5 +2,5 @@
"Cancel": "$t(Buttons:Cancel)",
"Reset to Defaults": "$t(Buttons:Reset to Defaults)",
"Save": "$t(Buttons:Save)",
"User Preferences": "Preferencias de usuario"
}
"User Preferences": "Preferencias de Usuario"
}
+12 -10
View File
@@ -1,17 +1,19 @@
import Buttons from './Buttons.json';
import CineDialog from './CineDialog.json';
import Common from './Common.json';
import Header from './Header.json';
import MeasurementTable from './MeasurementTable.json';
import UserPreferencesModal from './UserPreferencesModal.json';
import Buttons from "./Buttons.json";
import CineDialog from "./CineDialog.json";
import Common from "./Common.json";
import Header from "./Header.json";
import MeasurementTable from "./MeasurementTable.json";
import StudyList from "./StudyList.json";
import UserPreferencesModal from "./UserPreferencesModal.json";
export default {
es: {
export default {
'es': {
Buttons,
CineDialog,
Common,
Header,
MeasurementTable,
StudyList,
UserPreferencesModal,
},
};
}
};
+5 -1
View File
@@ -1,9 +1,13 @@
import en_US from './en-US/';
import es from './es/';
import nl from './nl/';
import pt_BR from './pt-BR/';
import zh from './zh/';
export default {
...en_US,
...es,
...nl,
};
...pt_BR,
...zh,
};
@@ -3,4 +3,4 @@
"More": "Meer",
"Pan": "Pan",
"Zoom": "Inzoomen"
}
}
@@ -1,3 +1,3 @@
{
"More": "Meer"
}
}
@@ -4,4 +4,4 @@
"Options": "Opties",
"Preferences": "Voorkeuren",
"Study list": "Studie Overzicht"
}
}
+7 -7
View File
@@ -1,11 +1,11 @@
import Buttons from './Buttons.json';
import Common from './Common.json';
import Header from './Header.json';
import Buttons from "./Buttons.json";
import Common from "./Common.json";
import Header from "./Header.json";
export default {
nl: {
export default {
'nl': {
Buttons,
Common,
Header,
},
};
}
};
@@ -0,0 +1,42 @@
{
"Acquired": "Adquirido",
"Angle": "Ângulo",
"Axial": "Axial",
"Bidirectional": "Bidirecional",
"Brush": "Pincel",
"CINE": "CINE",
"Cancel": "Cancelar",
"Circle": "Círculo",
"Clear": "Limpar",
"Coronal": "Coronal",
"Crosshairs": "Localizador",
"Ellipse": "Elipse",
"Elliptical": "Elíptico",
"Flip H": "Inverter H",
"Flip V": "Inverter V",
"Freehand": "Desenho livre",
"Invert": "Inverter",
"Layout": "Layout",
"Length": "Tamanho",
"Levels": "Níveis",
"Magnify": "Ampliar",
"Manual": "Manual",
"Measurements": "Medidas",
"More": "Mais",
"Next": "Próximo",
"Pan": "Arrastar",
"Play": "Tocar",
"Previous": "Anterior",
"Probe": "Prova",
"ROI Window": "Janela ROI",
"Rectangle": "Retângulo",
"Reset": "Resetar",
"Reset to Defaults": "Restaurar para o Padrão",
"Rotate Right": "Girar à direita",
"Sagittal": "Sagital",
"Save": "Salvar",
"Stack Scroll": "Navegar Stacks",
"Stop": "Parar",
"Themes": "Temas",
"Zoom": "Zoom"
}
@@ -0,0 +1,8 @@
{
"Next image": "Próxima imagem",
"Play / Stop": "Tocar / Parar",
"Previous image": "Imagem Anterior",
"Skip to first image": "Pular para a primeira imagem",
"Skip to last image": "Pular para a última imagem",
"fps": "fps"
}
@@ -0,0 +1,10 @@
{
"Image": "Imagem",
"Layout": "Layout",
"More": "Mais",
"Next": "Próximo",
"Play": "Play",
"Previous": "Anterior",
"Reset": "Reset",
"Stop": "Stop"
}
@@ -0,0 +1,8 @@
{
"About": "Quem somos",
"Back to Viewer": "Voltar para o Viewer",
"INVESTIGATIONAL USE ONLY": "APENAS PARA USO INVESTIGATIVO",
"Options": "Opções",
"Preferences": "Preferências",
"Study list": "Lista de estudos"
}
@@ -0,0 +1,6 @@
{
"Cancel": "Cancelar",
"Reset to Defaults": "Restaurar Default",
"Save": "Salvar",
"User Preferences": "Preferências do Usuário"
}
@@ -0,0 +1,15 @@
import Buttons from "./Buttons.json";
import CineDialog from "./CineDialog.json";
import Common from "./Common.json";
import Header from "./Header.json";
import UserPreferencesModal from "./UserPreferencesModal.json";
export default {
'pt-BR': {
Buttons,
CineDialog,
Common,
Header,
UserPreferencesModal,
}
};
@@ -0,0 +1,13 @@
{
"Angle": "线角测量",
"CINE": "播放",
"Length": "长度测量",
"Levels": "窗宽/窗位",
"Measurements": "测量",
"More": "更多",
"Pan": "平移",
"Play": "播放",
"Reset": "重置",
"Rotate Right": "顺时针",
"Zoom": "缩放"
}
@@ -0,0 +1,3 @@
{
"Play": "播放"
}
@@ -0,0 +1,3 @@
{
"Study list": "检查"
}
@@ -0,0 +1,11 @@
import Buttons from "./Buttons.json";
import Common from "./Common.json";
import Header from "./Header.json";
export default {
'zh': {
Buttons,
Common,
Header,
}
};
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "0.1.5",
"version": "0.1.6",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@@ -40,7 +40,7 @@
"dependencies": {
"@babel/runtime": "^7.4.5",
"react-vtkjs-viewport": "0.0.11",
"vtk.js": "^8.13.0"
"vtk.js": "^9.0.1"
},
"devDependencies": {
"@babel/core": "^7.4.5",
+4 -4
View File
@@ -6974,10 +6974,10 @@ void-elements@^2.0.1:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
vtk.js@^8.13.0:
version "8.13.0"
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-8.13.0.tgz#d22bbe3403d86f979703506f9be83ab8e5099248"
integrity sha512-uoq2U0Yu2XjuKeeduuGRXlphHR6cdIvtZ5useNMJ8FobK9dpeFTT4ncoyPXx77KvwOMSueT8W+ngm/e9+FGZtA==
vtk.js@^9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-9.0.1.tgz#fa769e2f14c2e4546a205417ae861cc9d715e5ff"
integrity sha512-4GG2xu9gVXoL6Q0yyKMCIs09/yJcVLinDvHY33MBeMslKf3u6dO3qVMIh0lAXYJQcVKi/mFrMfary3PPF/JmDA==
dependencies:
base64-js "1.2.1"
blueimp-md5 "2.10.0"
+13 -12
View File
@@ -78,12 +78,12 @@
},
"dependencies": {
"@babel/runtime": "^7.4.5",
"@ohif/extension-cornerstone": "0.0.41",
"@ohif/extension-dicom-html": "0.0.3",
"@ohif/extension-dicom-microscopy": "0.0.9",
"@ohif/extension-dicom-pdf": "0.0.7",
"@ohif/extension-vtk": "0.1.5",
"@ohif/i18n": "0.2.2",
"@ohif/extension-cornerstone": "0.0.43",
"@ohif/extension-dicom-html": "0.0.4",
"@ohif/extension-dicom-microscopy": "0.0.12",
"@ohif/extension-dicom-pdf": "0.0.8",
"@ohif/extension-vtk": "0.1.6",
"@ohif/i18n": "0.2.3",
"@tanem/react-nprogress": "^1.1.25",
"classnames": "^2.2.6",
"cornerstone-core": "^2.2.8",
@@ -92,14 +92,14 @@
"cornerstone-wado-image-loader": "^2.2.3",
"dcmjs": "^0.4.7",
"dicom-parser": "^1.8.3",
"dicomweb-client": "^0.4.4",
"dicomweb-client": "^0.5.2",
"hammerjs": "^2.0.8",
"i18next": "^17.0.3",
"i18next-browser-languagedetector": "^3.0.1",
"lodash.isequal": "4.5.0",
"moment": "^2.24.0",
"ohif-core": "0.9.1",
"oidc-client": "1.7.x",
"ohif-core": "0.11.0",
"oidc-client": "1.8.x",
"prop-types": "^15.7.2",
"react-dropzone": "^10.1.5",
"react-i18next": "^10.11.0",
@@ -108,7 +108,7 @@
"react-router": "^5.0.1",
"react-router-dom": "^5.0.1",
"react-transition-group": "^4.1.1",
"react-viewerbase": "0.17.0",
"react-viewerbase": "0.17.6",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-oidc": "3.1.x",
@@ -146,8 +146,8 @@
"lodash": "4.17.11",
"lodash.clonedeep": "4.5.0",
"prettier": "1.18.x",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "^3.0.1",
"rollup": "^1.15.5",
"rollup-plugin-babel": "^4.3.2",
@@ -157,6 +157,7 @@
"rollup-plugin-node-resolve": "^5.0.2",
"rollup-plugin-peer-deps-external": "^2.2.0",
"rollup-plugin-postcss": "^2.0.3",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-serve": "^1.0.1",
"rollup-plugin-url": "^2.2.2",
"semantic-release": "15.13.x",
+2 -2
View File
@@ -54,8 +54,8 @@ window.config = {
{ commandName: 'fitViewportToWindow', label: 'Zoom to Fit', keys: ['='] },
{ commandName: 'resetViewport', label: 'Reset', keys: ['space'] },
// clearAnnotations
// nextImage
// previousImage
{ commandName: 'nextImage', label: 'Next Image', keys: ['down'] },
{ commandName: 'previousImage', label: 'Previous Image', keys: ['up'] },
// firstImage
// lastImage
{
+4 -3
View File
@@ -13,14 +13,15 @@ window.config = {
// Authorization Server URL
authority: 'https://accounts.google.com',
client_id: 'YOURCLIENTID.apps.googleusercontent.com',
redirect_uri: `${window.location}callback`, // `OHIFStandaloneViewer.js`
redirect_uri: '/callback', // `OHIFStandaloneViewer.js`
response_type: 'id_token token',
scope: 'email profile openid https://www.googleapis.com/auth/cloudplatformprojects.readonly https://www.googleapis.com/auth/cloud-healthcare', // email profile openid
// ~ OPTIONAL
post_logout_redirect_uri: '/logout-redirect.html',
revoke_uri: 'https://accounts.google.com/o/oauth2/revoke?token=',
"automaticSilentRenew": true,
"revokeAccessTokenOnSignout": true,
automaticSilentRenew: true,
revokeAccessTokenOnSignout: true,
},
],
studyListFunctionsEnabled: true,
}
+1
View File
@@ -21,4 +21,5 @@ window.config = {
},
],
},
studyListFunctionsEnabled: true,
}
+2 -2
View File
@@ -49,8 +49,8 @@ window.config = {
{ commandName: 'fitViewportToWindow', label: 'Zoom to Fit', keys: ['='] },
{ commandName: 'resetViewport', label: 'Reset', keys: ['space'] },
// clearAnnotations
// nextImage
// previousImage
{ commandName: 'nextImage', label: 'Next Image', keys: ['down'] },
{ commandName: 'previousImage', label: 'Previous Image', keys: ['up'] },
// firstImage
// lastImage
{
-8
View File
@@ -16,14 +16,6 @@
<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=Roboto:100,300,400,500,700|Sanchez&display=swap"
-25
View File
@@ -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>
+37 -2
View File
@@ -9,12 +9,13 @@ 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'
import replace from 'rollup-plugin-replace';
import serve from 'rollup-plugin-serve'
const globals = {
react: 'React',
'react-dom': 'ReactDOM',
}
};
const startServer = process.env.START_SERVER === 'true';
@@ -40,6 +41,9 @@ export default {
],
plugins: [
external(),
replace({
'process.env.NODE_ENV': JSON.stringify('production')
}),
postcss({
modules: false,
}),
@@ -54,6 +58,32 @@ export default {
commonjs({
include: 'node_modules/**',
namedExports: {
'node_modules/react/index.js': [
'createContext',
'createElement',
'createRef',
'cloneElement',
'Children',
'Fragment',
'forwardRef',
'useCallback',
'isValidElement',
'memo',
'useContext',
'useState',
'useEffect',
'useLayoutEffect',
'Component',
'PureComponent',
'useRef',
'useReducer',
'useMemo',
],
'node_modules/react-dom/index.js': [
'unstable_batchedUpdates',
'findDOMNode',
'render',
],
'node_modules/react-is/index.js': [
'isValidElementType',
'isContextConsumer',
@@ -61,15 +91,20 @@ export default {
'node_modules/redux-oidc/dist/redux-oidc.js': [
'reducer',
'CallbackComponent',
'SignoutCallbackComponent',
'loadUser',
'OidcProvider',
'createUserManager',
],
'node_modules/oidc-client/lib/oidc-client.min.js': [
'WebStorageStateStore',
'InMemoryWebStorage',
],
'node_modules/cornerstoneTools/dist/cornerstoneTools.min.js': [
'cornerstoneTools',
],
'node_modules/dcmjs/build/dcmjs.js': ['data', 'adapters'],
'node_modules/prop-types/index.js': ['bool', 'number', 'string', 'shape', 'func', 'any', 'node']
'node_modules/prop-types/index.js': ['oneOfType', 'element', 'bool', 'number', 'string', 'shape', 'func', 'any', 'node']
},
}),
builtins(),
+43 -9
View File
@@ -37,6 +37,7 @@ import { getActiveContexts } from './store/layout/selectors.js';
import i18n from '@ohif/i18n';
import setupTools from './setupTools.js';
import store from './store';
import UserManagerContext from './UserManagerContext';
// ~~~~ APP SETUP
initCornerstoneTools({
@@ -71,7 +72,7 @@ extensionManager.registerExtensions([
]);
// Must run after extension commands are registered
if (window.config.hotkeys) {
if (window.config && window.config.hotkeys) {
hotkeysManager.setHotkeys(window.config.hotkeys, true);
}
@@ -84,6 +85,23 @@ function handleServers(servers) {
}
}
function isAbsoluteUrl(url) {
return url.includes('http://') || url.includes('https://');
}
function makeAbsoluteIfNecessary(url, base_url) {
if (isAbsoluteUrl(url)) {
return url;
}
// Make sure base_url and url are not duplicating slashes
if (base_url[base_url.length - 1] === "/") {
base_url = base_url.slice(0, base_url.length - 1);
}
return base_url + url;
}
class App extends Component {
static propTypes = {
routerBasename: PropTypes.string.isRequired,
@@ -104,9 +122,23 @@ class App extends Component {
if (this.props.oidc.length) {
const firstOpenIdClient = this.props.oidc[0];
const { protocol, host } = window.location;
const { routerBasename } = this.props;
const baseUri = `${protocol}//${host}${routerBasename}`;
const redirect_uri = firstOpenIdClient.redirect_uri || '/callback';
const silent_redirect_uri = firstOpenIdClient.silent_redirect_uri || '/silent-refresh.html';
const post_logout_redirect_uri = firstOpenIdClient.post_logout_redirect_uri || '/';
const openIdConnectConfiguration = Object.assign({}, firstOpenIdClient, {
redirect_uri: makeAbsoluteIfNecessary(redirect_uri, baseUri),
silent_redirect_uri: makeAbsoluteIfNecessary(silent_redirect_uri, baseUri),
post_logout_redirect_uri: makeAbsoluteIfNecessary(post_logout_redirect_uri, baseUri),
});
this.userManager = getUserManagerForOpenIdConnectClient(
store,
firstOpenIdClient
openIdConnectConfiguration,
);
}
handleServers(this.props.servers);
@@ -124,13 +156,15 @@ class App extends Component {
<Provider store={store}>
<I18nextProvider i18n={i18n}>
<OidcProvider store={store} userManager={userManager}>
<Router basename={this.props.routerBasename}>
<WhiteLabellingContext.Provider
value={this.props.whiteLabelling}
>
<OHIFStandaloneViewer userManager={userManager} />
</WhiteLabellingContext.Provider>
</Router>
<UserManagerContext.Provider value={userManager}>
<Router basename={this.props.routerBasename}>
<WhiteLabellingContext.Provider
value={this.props.whiteLabelling}
>
<OHIFStandaloneViewer userManager={userManager} />
</WhiteLabellingContext.Provider>
</Router>
</UserManagerContext.Provider>
</OidcProvider>
</I18nextProvider>
</Provider>
+5
View File
@@ -13,6 +13,11 @@ body,
Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif;
}
body {
font-size: 14px;
line-height: 1.42857143;
}
#root .fade-enter {
opacity: 0;
}
+20 -4
View File
@@ -5,6 +5,7 @@ import { Route, Switch } from 'react-router-dom';
import { NProgress } from '@tanem/react-nprogress';
import { CSSTransition } from 'react-transition-group';
import { connect } from 'react-redux';
import { SignoutCallbackComponent } from 'redux-oidc';
import { ViewerbaseDragDropContext } from 'react-viewerbase';
// import asyncComponent from './components/AsyncComponent.js'
import IHEInvokeImageDisplay from './routes/IHEInvokeImageDisplay.js';
@@ -74,14 +75,29 @@ class OHIFStandaloneViewer extends Component {
return (
<Switch>
<Route exact path="/silent-refresh.html" onEnter={reload} />
<Route exact path="/logout-redirect.html" onEnter={reload} />
<Route exact path="/logout-redirect" render={() =>
<SignoutCallbackComponent
userManager={userManager}
successCallback={() => console.log('Signout successful')}
errorCallback={(error) => {
console.warn(error);
console.warn('Signout failed');
}}
/>
}/>
<Route
path="/callback"
render={() => <CallbackPage userManager={userManager} />}
/>
<Route
component={() => {
userManager.signinRedirect();
userManager.getUser().then(user => {
if (user) {
userManager.signinSilent();
} else {
userManager.signinRedirect();
}
});
return null;
}}
@@ -120,7 +136,7 @@ class OHIFStandaloneViewer extends Component {
];
const showStudyList =
window.config.showStudyList !== undefined
window.config && window.config.showStudyList !== undefined
? window.config.showStudyList
: true;
if (showStudyList) {
@@ -172,7 +188,7 @@ class OHIFStandaloneViewer extends Component {
this.setState({ isLoading: false });
}}
>
{match === null ? <></> : <Component match={match} />}
{match === null ? <></> : <Component match={match} location={this.props.location}/>}
</CSSTransition>
)}
</Route>
+5
View File
@@ -0,0 +1,5 @@
import React from 'react';
const UserManagerContext = React.createContext();
export default UserManagerContext;
+11
View File
@@ -17,6 +17,7 @@ class Header extends Component {
location: PropTypes.object.isRequired,
children: PropTypes.node,
t: PropTypes.func.isRequired,
userManager: PropTypes.object
};
static defaultProps = {
@@ -59,6 +60,16 @@ class Header extends Component {
},
];
if (this.props.user && this.props.userManager) {
this.options.push({
title: t('Logout'),
icon: { name: 'power-off' },
onClick: () => {
this.props.userManager.signoutRedirect();
},
});
}
this.hotKeysData = hotkeysManager.hotkeyDefinitions;
}
+7 -1
View File
@@ -4,9 +4,15 @@ import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
import dicomParser from 'dicom-parser';
import version from './version.js';
let homepage;
const { process } = window;
if (process && process.env && process.env.PUBLIC_URL) {
homepage = process.env.PUBLIC_URL;
}
window.info = {
version,
homepage: `${process.env.PUBLIC_URL}`,
homepage,
};
// For debugging
@@ -3,6 +3,7 @@ import { connect } from 'react-redux';
const mapStateToProps = state => {
return {
user: state.oidc && state.oidc.user,
isOpen: state.ui.userPreferencesModalOpen,
};
};
+19 -7
View File
@@ -13,6 +13,7 @@ import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
import ConnectedViewerMain from './ConnectedViewerMain.js';
import SidePanel from './../components/SidePanel.js';
import { extensionManager } from './../App.js';
import UserManagerContext from '../UserManagerContext';
import './Viewer.css';
/**
* Inits OHIF Hanging Protocol's onReady.
@@ -230,9 +231,14 @@ class Viewer extends Component {
{/* HEADER */}
<WhiteLabellingContext.Consumer>
{whiteLabelling => (
<ConnectedHeader home={false}>
{whiteLabelling.logoComponent}
</ConnectedHeader>
<UserManagerContext.Consumer>
{ userManager => (
<ConnectedHeader home={false} userManager={userManager}>
{whiteLabelling.logoComponent}
</ConnectedHeader>
)
}
</UserManagerContext.Consumer>
)}
</WhiteLabellingContext.Consumer>
@@ -319,7 +325,6 @@ export default Viewer;
*
* TODO[react]:
* - Add sorting of display sets
* - Add useMiddleSeriesInstanceAsThumbnail
* - Add showStackLoadingProgressBar option
*
* @param {Study[]} studies
@@ -339,10 +344,17 @@ const _mapStudiesToThumbnails = function(studies) {
} = displaySet;
let imageId;
let altImageText = ' '; // modality
let altImageText;
if (displaySet.images && displaySet.images.length) {
imageId = displaySet.images[0].getImageId();
if (displaySet.modality && displaySet.modality === 'SEG') {
// TODO: We want to replace this with a thumbnail showing
// the segmentation map on the image, but this is easier
// and better than what we have right now.
altImageText = 'SEG';
} else if (displaySet.images && displaySet.images.length) {
const imageIndex = Math.floor(displaySet.images.length / 2);
imageId = displaySet.images[imageIndex].getImageId();
} else {
altImageText = displaySet.modality ? displaySet.modality : 'UN';
}
@@ -1,15 +1,18 @@
import { connect } from 'react-redux';
import DicomFileUploaderModal from './DicomFileUploaderModal.js';
import OHIF from 'ohif-core';
const isActive = a => a.active === true;
const mapStateToProps = state => {
const activeServer = state.servers.servers.find(isActive);
const { authority, client_id } = window.config.oidc[0];
const oidcStorageKey = `oidc.user:${authority}:${client_id}`;
// TODO: Not sure I like this approach since it means we are recreating
// this function every time redux changes
const retrieveAuthHeaderFunction = () => OHIF.DICOMWeb.getAuthorizationHeader(activeServer);
return {
oidcStorageKey,
retrieveAuthHeaderFunction,
url: activeServer && activeServer.qidoRoot,
};
};
+1 -3
View File
@@ -5,11 +5,9 @@ const isActive = a => a.active === true;
const mapStateToProps = state => {
const activeServer = state.servers.servers.find(isActive);
const { authority, client_id } = window.config.oidc[0];
const oidcStorageKey = `oidc.user:${authority}:${client_id}`;
return {
oidcStorageKey,
user: state.oidc && state.oidc.user,
url: activeServer && activeServer.qidoRoot,
};
};
+2 -2
View File
@@ -15,11 +15,11 @@ export default class DatasetPicker extends Component {
project: PropTypes.object,
location: PropTypes.object,
onSelect: PropTypes.func,
oidcKey: PropTypes.string,
accessToken: PropTypes.string,
};
async componentDidMount() {
api.setOidcStorageKey(this.props.oidcKey);
api.setAccessToken(this.props.accessToken);
const response = await api.loadDatasets(
this.props.project.projectId,
+7 -5
View File
@@ -19,7 +19,7 @@ class DatasetSelector extends Component {
static propTypes = {
id: PropTypes.string,
event: PropTypes.string,
oidcKey: PropTypes.string,
user: PropTypes.object,
canClose: PropTypes.string,
setServers: PropTypes.func.isRequired,
};
@@ -79,6 +79,8 @@ class DatasetSelector extends Component {
};
render() {
const accessToken = this.props.user.access_token;
const { project, location, dataset } = this.state;
const {
onProjectClick,
@@ -121,21 +123,21 @@ class DatasetSelector extends Component {
{projectBreadcrumbs}
{!project && (
<ProjectPicker
oidcKey={this.props.oidcKey}
accessToken={accessToken}
onSelect={onProjectSelect}
/>
)}
{project && !location && (
<LocationPicker
oidcKey={this.props.oidcKey}
accessToken={accessToken}
project={project}
onSelect={onLocationSelect}
/>
)}
{project && location && !dataset && (
<DatasetPicker
oidcKey={this.props.oidcKey}
accessToken={accessToken}
project={project}
location={location}
onSelect={onDatasetSelect}
@@ -143,7 +145,7 @@ class DatasetSelector extends Component {
)}
{project && location && dataset && (
<DicomStorePicker
oidcKey={this.props.oidcKey}
accessToken={accessToken}
dataset={dataset}
onSelect={onDicomStoreSelect}
/>
+3 -3
View File
@@ -7,7 +7,7 @@ import { withTranslation } from 'react-i18next';
class DicomFileUploaderModal extends Component {
static propTypes = {
url: PropTypes.string,
oidcStorageKey: PropTypes.string.isRequired,
retrieveAuthHeaderFunction: PropTypes.func,
onClose: PropTypes.func,
};
@@ -32,13 +32,13 @@ class DicomFileUploaderModal extends Component {
>
<Modal.Header closeButton>
<Modal.Title>
{this.props.t('Google Cloud Healthcare API - DICOM Upload')}
{this.props.t('Upload DICOM Files')}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<DicomUploader
url={this.props.url}
oidcKey={this.props.oidcStorageKey}
retrieveAuthHeaderFunction={this.props.retrieveAuthHeaderFunction}
/>
</Modal.Body>
</Modal>
+3 -3
View File
@@ -15,12 +15,12 @@ export default class DicomStorePicker extends Component {
static propTypes = {
dataset: PropTypes.object,
onSelect: PropTypes.func,
accessToken: PropTypes.string.isRequired
};
async componentDidMount() {
const { authority, client_id } = window.config.oidc[0];
const oidcStorageKey = `oidc.user:${authority}:${client_id}`;
api.setOidcStorageKey(oidcStorageKey);
api.setAccessToken(this.props.accessToken);
const response = await api.loadDicomStores(this.props.dataset.name);
if (response.isError) {
+3 -2
View File
@@ -8,7 +8,7 @@ import { withTranslation } from 'react-i18next';
class DicomStorePickerModal extends Component {
static propTypes = {
url: PropTypes.string,
oidcStorageKey: PropTypes.string.isRequired,
user: PropTypes.object.isRequired,
setServers: PropTypes.func.isRequired,
isOpen: PropTypes.bool.isRequired,
onClose: PropTypes.func,
@@ -30,6 +30,7 @@ class DicomStorePickerModal extends Component {
wadoRoot: data.wadoRoot,
wadoUriRoot: data.wadoUriRoot,
active: true,
supportsFuzzyMatching: false,
},
];
@@ -55,7 +56,7 @@ class DicomStorePickerModal extends Component {
<Modal.Body>
<DatasetSelector
setServers={this.handleEvent}
oidcKey={this.props.oidcStorageKey}
user={this.props.user}
url={this.props.url}
/>
</Modal.Body>
+20
View File
@@ -0,0 +1,20 @@
.dicom-uploader .button {
float: left;
margin: 5px;
}
.invisible-input {
position: absolute;
display: none;
z-index: -1000;
max-width: 0 !important;
max-height: 0 !important;
}
.dicom-uploader .table-header {
color: #ffffff;
font-size: 16px;
font-weight: 28px;
text-align: left;
margin: 20px auto;
}
+9 -9
View File
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { formatFileSize } from './utils/helpers';
import CancellationToken from './utils/CancellationToken';
import dicomUploader from './api/DicomUploadService';
import './googleCloud.css';
import './DicomUploader.css';
export default class DicomUploader extends Component {
state = {
@@ -26,7 +26,7 @@ export default class DicomUploader extends Component {
id: PropTypes.string,
event: PropTypes.string,
url: PropTypes.string,
oidcKey: PropTypes.string,
retrieveAuthHeaderFunction: PropTypes.func,
};
filesLeft() {
@@ -94,11 +94,12 @@ export default class DicomUploader extends Component {
const uploadCallback = (fileId, error) =>
uploadContext === this.state.uploadContext &&
this.uploadCallback.call(this, fileId, error);
dicomUploader.setOidcStorageKey(this.props.oidcKey);
dicomUploader.setRetrieveAuthHeaderFunction(this.props.retrieveAuthHeaderFunction);
dicomUploader.smartUpload(
files.target.files,
this.props.url,
this.props.oidcKey,
uploadCallback,
cancellationToken
);
@@ -137,14 +138,13 @@ export default class DicomUploader extends Component {
render() {
if (this.state.files === null) {
return (
<div className="gcp-dicom-uploader">
<div className="dicom-uploader">
<div className="button">
<label htmlFor="file">
<img src="./assets/Button_File.svg" alt="upload file"></img>
</label>
<input
className="gcp-invisible-input"
accept=".dcm"
className="invisible-input"
onChange={this.uploadFiles}
type="file"
id="file"
@@ -157,7 +157,7 @@ export default class DicomUploader extends Component {
<img src="./assets/Button_Folder.svg" alt="upload folder"></img>
</label>
<input
className="gcp-invisible-input"
className="invisible-input"
type="file"
onChange={this.uploadFiles}
id="folder"
@@ -174,7 +174,7 @@ export default class DicomUploader extends Component {
<table id="tblProjectList" className="table noselect">
<thead>
<tr>
<th className="gcp-picker--path">
<th className="table-header">
{this.percents()}% {this.filesLeft()}
</th>
</tr>
+2 -2
View File
@@ -14,11 +14,11 @@ export default class LocationPicker extends Component {
static propTypes = {
project: PropTypes.object,
onSelect: PropTypes.func,
oidcKey: PropTypes.string,
accessToken: PropTypes.string,
};
async componentDidMount() {
api.setOidcStorageKey(this.props.oidcKey);
api.setAccessToken(this.props.accessToken);
const response = await api.loadLocations(this.props.project.projectId);
+2 -2
View File
@@ -13,11 +13,11 @@ export default class ProjectPicker extends Component {
static propTypes = {
onSelect: PropTypes.func,
oidcKey: PropTypes.string,
accessToken: PropTypes.string,
};
async componentDidMount() {
api.setOidcStorageKey(this.props.oidcKey);
api.setAccessToken(this.props.accessToken);
const response = await api.loadProjects();
if (response.isError) {
+17 -20
View File
@@ -1,23 +1,16 @@
import { httpErrorToStr, getOidcToken, checkDicomFile } from '../utils/helpers';
import { httpErrorToStr, checkDicomFile } from '../utils/helpers';
import { api } from 'dicomweb-client';
class DicomUploadService {
setOidcStorageKey(oidcStorageKey) {
/* eslint-disable */
if (!oidcStorageKey) console.error('OIDC storage key is empty');
this.oidcStorageKey = oidcStorageKey;
}
async smartUpload(files, url, authToken, uploadCallback, cancellationToken) {
/* eslint-disable */
async smartUpload(files, url, uploadCallback, cancellationToken) {
const CHUNK_SIZE = 1; // Only one file per request is supported so far
const MAX_PARALLEL_JOBS = 50; // FIXME: tune MAX_PARALLEL_JOBS number
//
let filesArray = Array.from(files);
if (filesArray.length === 0) {
console.warn('No files are supplied for uploading');
return;
throw new Error('No files were provided.');
}
let parallelJobsCount = Math.min(filesArray.length, MAX_PARALLEL_JOBS);
let completed = false;
@@ -30,7 +23,7 @@ class DicomUploadService {
try {
if (chunk.length > 1) throw new Error('Not implemented');
if (chunk.length === 1)
await this.simpleUpload(chunk[0], url, authToken);
await this.simpleUpload(chunk[0], url);
} catch (err) {
// It looks like a stupid bug of Babel that err is not an actual Exception object
error = httpErrorToStr(err);
@@ -51,13 +44,13 @@ class DicomUploadService {
});
}
async simpleUpload(file, url, authToken) {
/* eslint-disable */
async simpleUpload(file, url) {
const client = this.getClient(url);
const loadedFile = await this.readFile(file);
const content = loadedFile.content;
if (!checkDicomFile(content))
throw new Error('The file has a wrong DICOM header');
throw new Error('This is not a valid DICOM file.');
await client.storeInstances({ datasets: [content] });
}
@@ -77,13 +70,17 @@ class DicomUploadService {
});
}
setRetrieveAuthHeaderFunction(func) {
this.retrieveAuthHeaderFunc = func;
}
getClient(url) {
if (!this.oidcStorageKey) throw new Error('OIDC storage key is not set');
const accessToken = getOidcToken(this.oidcStorageKey);
if (!accessToken) throw new Error('OIDC access_token is not set');
const headers = this.retrieveAuthHeaderFunc();
// TODO: a bit weird we are creating a new dicomweb client instance for every upload
return new api.DICOMwebClient({
url,
headers: { Authorization: 'Bearer ' + accessToken },
headers
});
}
}
+5 -9
View File
@@ -1,19 +1,15 @@
import { getOidcToken } from '../utils/helpers';
class GoogleCloudApi {
setOidcStorageKey(oidcStorageKey) {
if (!oidcStorageKey) console.error('OIDC storage key is empty');
this.oidcStorageKey = oidcStorageKey;
setAccessToken(accessToken) {
if (!accessToken) console.error('Access token is empty');
this.accessToken = accessToken;
}
get fetchConfig() {
if (!this.oidcStorageKey) throw new Error('OIDC storage key is not set');
const accessToken = getOidcToken(this.oidcStorageKey);
if (!accessToken) throw new Error('OIDC access_token is not set');
if (!this.accessToken) throw new Error('OIDC access_token is not set');
return {
method: 'GET',
headers: {
Authorization: 'Bearer ' + accessToken,
Authorization: 'Bearer ' + this.accessToken,
},
};
}
-11
View File
@@ -94,13 +94,6 @@
background-color: #000000;
}
.gcp-invisible-input {
position: absolute;
display: none;
z-index: -1000;
max-width: 0 !important;
max-height: 0 !important;
}
.gcp-hidden {
display: none;
}
@@ -148,7 +141,3 @@
margin: 20px auto;
}
.gcp-dicom-uploader .button {
float: left;
margin: 5px;
}
-5
View File
@@ -26,11 +26,6 @@ export function httpErrorToStr(error) {
return error.message || 'Unknown error.';
}
export function getOidcToken(oidcStorageKey) {
const oidcConfigStr = sessionStorage.getItem(oidcStorageKey);
if (oidcConfigStr) return JSON.parse(oidcConfigStr).access_token;
}
/* eslint-disable */
export function checkDicomFile(arrayBuffer) {
if (arrayBuffer.length <= 132) return false;
+15 -1
View File
@@ -2,5 +2,19 @@
* Entry point index.js for rollup packaging
*/
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
export { App };
function installViewer(props, containerId = "root", callback) {
const container = document.getElementById(containerId);
if (!container) {
throw new Error("No root element found to install viewer. Please add a <div> with the id 'root', or pass a DOM element into the installViewer function.");
}
return ReactDOM.render(<App {...props}/>, container, callback);
}
export { App, installViewer };
+6 -1
View File
@@ -90,7 +90,12 @@ class StandaloneRouting extends Component {
async componentDidMount() {
try {
const query = qs.parse(this.props.location.search);
let { search } = this.props.location;
// Remove ? prefix which is included for some reason
search = search.slice(1, search.length);
const query = qs.parse(search);
const studies = await StandaloneRouting.parseQueryAndFetchStudies(query);
studyMetadataManager.purge();
+8 -1
View File
@@ -24,7 +24,14 @@ function getFilters({ search }) {
function StudyListRouting({ location }) {
const filters = location ? getFilters(location) : undefined;
return <ConnectedStudyList filters={filters} />;
let studyListFunctionsEnabled = false;
if (window.config && window.config.studyListFunctionsEnabled) {
studyListFunctionsEnabled = window.config.studyListFunctionsEnabled;
}
return <ConnectedStudyList
filters={filters}
studyListFunctionsEnabled={studyListFunctionsEnabled}
/>;
}
StudyListRouting.propTypes = {
+38 -24
View File
@@ -10,6 +10,8 @@ import moment from 'moment';
import ConnectedDicomFilesUploader from '../googleCloud/ConnectedDicomFilesUploader';
import ConnectedDicomStorePicker from '../googleCloud/ConnectedDicomStorePicker';
import filesToStudies from '../lib/filesToStudies.js';
import UserManagerContext from '../UserManagerContext';
import WhiteLabellingContext from '../WhiteLabellingContext';
class StudyListWithData extends Component {
state = {
@@ -25,6 +27,11 @@ class StudyListWithData extends Component {
server: PropTypes.object,
user: PropTypes.object,
history: PropTypes.object,
studyListFunctionsEnabled: PropTypes.bool,
};
static defaultProps = {
studyListFunctionsEnabled: true,
};
static rowsPerPage = 25;
@@ -85,6 +92,10 @@ class StudyListWithData extends Component {
offset: searchData.currentPage * searchData.rowsPerPage,
};
if (server.supportsFuzzyMatching) {
filter.fuzzymatching = true;
}
// TODO: add sorting
const promise = OHIF.studies.searchStudies(server, filter);
@@ -145,7 +156,7 @@ class StudyListWithData extends Component {
};
onImport = () => {
//console.log('onImport');
this.openModal('DicomFilesUploader');
};
openModal = modalComponentId => {
@@ -174,9 +185,6 @@ class StudyListWithData extends Component {
render() {
const onDrop = async acceptedFiles => {
// Do something with the files
console.warn(acceptedFiles);
try {
const studies = await filesToStudies(acceptedFiles);
@@ -198,16 +206,10 @@ class StudyListWithData extends Component {
// TODO: This should probably be a prop
if (window.config.enableGoogleCloudAdapter) {
healthCareApiWindows = (
<>
<ConnectedDicomStorePicker
isOpen={this.state.modalComponentId === 'DicomStorePicker'}
onClose={this.closeModals}
/>
<ConnectedDicomFilesUploader
isOpen={this.state.modalComponentId === 'DicomFilesUploader'}
onClose={this.closeModals}
/>
</>
<ConnectedDicomStorePicker
isOpen={this.state.modalComponentId === 'DicomStorePicker'}
onClose={this.closeModals}
/>
);
healthCareApiButtons = (
@@ -221,24 +223,16 @@ class StudyListWithData extends Component {
>
{this.props.t('Change DICOM Store')}
</button>
<button
className="btn btn-primary"
onClick={() => this.openModal('DicomFilesUploader')}
>
{this.props.t('Upload Studies')}
</button>
</div>
);
}
console.warn(this.state.studies);
const studyList = (
<div className="paginationArea">
{this.state.studies ? (
<StudyList
studies={this.state.studies}
studyListFunctionsEnabled={false}
studyListFunctionsEnabled={this.props.studyListFunctionsEnabled}
onImport={this.onImport}
onSelectItem={this.onSelectItem}
pageSize={this.rowsPerPage}
@@ -248,6 +242,12 @@ class StudyListWithData extends Component {
}
onSearch={this.onSearch}
>
{this.props.studyListFunctionsEnabled ? (
<ConnectedDicomFilesUploader
isOpen={this.state.modalComponentId === 'DicomFilesUploader'}
onClose={this.closeModals}
/>
) : null}
{healthCareApiButtons}
{healthCareApiWindows}
</StudyList>
@@ -272,7 +272,21 @@ class StudyListWithData extends Component {
);
return (
<>
<ConnectedHeader home={true} user={this.props.user} />
<WhiteLabellingContext.Consumer>
{whiteLabelling => (
<UserManagerContext.Consumer>
{userManager => (
<ConnectedHeader
home={true}
user={this.props.user}
userManager={userManager}
>
{whiteLabelling.logoComponent}
</ConnectedHeader>
)}
</UserManagerContext.Consumer>
)}
</WhiteLabellingContext.Consumer>
{studyList}
</>
);
@@ -1,5 +1,6 @@
// https://github.com/maxmantz/redux-oidc/blob/master/docs/API.md
import { loadUser, createUserManager } from 'redux-oidc';
import { WebStorageStateStore, InMemoryWebStorage } from 'oidc-client';
/**
* Creates a userManager from oidcSettings;
@@ -20,13 +21,17 @@ export default function(store, oidcSettings) {
return;
}
// Do not store tokens in localStorage or sessionStorage
// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#local-storage
const userStore = new WebStorageStateStore({ store: new InMemoryWebStorage() });
const settings = {
...oidcSettings,
silent_redirect_uri: '/silent-refresh.html',
automaticSilentRenew: true,
revokeAccessTokenOnSignout: true,
filterProtocolClaims: true,
loadUserInfo: true,
userStore,
};
const userManager = createUserManager(settings);
+70 -60
View File
@@ -1237,50 +1237,50 @@
universal-user-agent "^2.0.0"
url-template "^2.0.8"
"@ohif/extension-cornerstone@0.0.41":
version "0.0.41"
resolved "https://registry.yarnpkg.com/@ohif/extension-cornerstone/-/extension-cornerstone-0.0.41.tgz#6b4ca0218705aee30ca1c83f869e8f993608fed3"
integrity sha512-8jhtnT02rScz+Px54tYj02a6nMq8jaVDWuX8cMTXwLGHM4au6BzOOwEMrtFP0SWfce814TATAZu1XTemGje1cA==
"@ohif/extension-cornerstone@0.0.43":
version "0.0.43"
resolved "https://registry.yarnpkg.com/@ohif/extension-cornerstone/-/extension-cornerstone-0.0.43.tgz#b7f65402e3f35be47e89849d250aff334c396443"
integrity sha512-TqwK471pVrR5WS84mhZ8Lihkzn+JXo94ZvtypQUJ1o6s9rzBpsdpA9YT0UEq5VKgcbWzE3lYd/k2k5y+1sXOIQ==
dependencies:
"@babel/runtime" "^7.2.0"
classnames "^2.2.6"
lodash.throttle "^4.1.1"
react-cornerstone-viewport "0.1.31"
react-cornerstone-viewport "0.1.32"
"@ohif/extension-dicom-html@0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@ohif/extension-dicom-html/-/extension-dicom-html-0.0.3.tgz#1d085f603379599cf07801ec003e3d5050e2d659"
integrity sha512-S+Mg9OFHNvllDDza55y4/NmBV1bFJ+NLbpcnsw45QyfgT3KAg8v/8ht1QYM9IcBGqhxMTJs8OqBuJI9sAiTWlw==
"@ohif/extension-dicom-html@0.0.4":
version "0.0.4"
resolved "https://registry.yarnpkg.com/@ohif/extension-dicom-html/-/extension-dicom-html-0.0.4.tgz#f547b0778f127e873fee0dba0bfb2806da12bbb9"
integrity sha512-5HbDG/1Q0CHQRAPhgvmXTNfwoaGPkl8T5+pSvUvkTHWxLfnUVJltuHny4OKjYdprrYstfbB+Sj8TxA5gjyQYwA==
dependencies:
"@babel/runtime" "^7.2.0"
"@ohif/extension-dicom-microscopy@0.0.9":
version "0.0.9"
resolved "https://registry.yarnpkg.com/@ohif/extension-dicom-microscopy/-/extension-dicom-microscopy-0.0.9.tgz#23cfbc44e06a51d94ab0b08db8e051720dbc9017"
integrity sha512-vqx25gHcT+MK+j77qTocGjSV8CstjCwQ2RDs1RuHrR3rUHdHOSbBkkyAjqMDF5GZWp0UY5JZV85aNuPK/9saqg==
"@ohif/extension-dicom-microscopy@0.0.12":
version "0.0.12"
resolved "https://registry.yarnpkg.com/@ohif/extension-dicom-microscopy/-/extension-dicom-microscopy-0.0.12.tgz#24bcfe2b47f2f73bff549c9faa54a7ae280ffc81"
integrity sha512-YTCQMKC4UoxP3T7zVS0sUzdEQrWe0xa449rrX/MDxf5dppoUF+JqKYB5kYCLJAkb5tTyxDN5HCk8SOASkTNntg==
dependencies:
"@babel/runtime" "^7.2.0"
classnames "^2.2.6"
dicom-microscopy-viewer "0.5.0"
dicom-microscopy-viewer "0.6.1"
lodash.debounce "^4.0.8"
"@ohif/extension-dicom-pdf@0.0.7":
version "0.0.7"
resolved "https://registry.yarnpkg.com/@ohif/extension-dicom-pdf/-/extension-dicom-pdf-0.0.7.tgz#ba80a77235d43876e25485e1a964f36ebf104b94"
integrity sha512-uOevtxH6Vm2p+2xgo+ER3+oV1zfnUqHYoeqrICaKP3PKXGcVanWFE8W/RWiNZ+PS2/LNpSjJyLfuSxwZ3IBUVw==
"@ohif/extension-dicom-pdf@0.0.8":
version "0.0.8"
resolved "https://registry.yarnpkg.com/@ohif/extension-dicom-pdf/-/extension-dicom-pdf-0.0.8.tgz#7d9cca5b0532e05279638ab5ba592e1e9f0bd8b3"
integrity sha512-I+PL2ZdvZQw9VzunjloHm4wsP6+OtFPjEkaAFwD4IijnP2+PXcA90ckBUjgVA3BUnHU4iZltJWEVxQpUEbisBQ==
dependencies:
"@babel/runtime" "^7.2.0"
classnames "^2.2.6"
lodash.isequal "^4.5.0"
"@ohif/extension-vtk@0.1.5":
version "0.1.5"
resolved "https://registry.yarnpkg.com/@ohif/extension-vtk/-/extension-vtk-0.1.5.tgz#0e7e8eb4f9b9860fd30b08611ecdf454b68626e1"
integrity sha512-KLeXxVvZ3ryLqbq9LjbBsKBxQJtFS1y7tmj5fKAUnfRCLypQ95T/zQf0v71caEITavxZxxe8O6G+nb5zdroxrg==
"@ohif/extension-vtk@0.1.6":
version "0.1.6"
resolved "https://registry.yarnpkg.com/@ohif/extension-vtk/-/extension-vtk-0.1.6.tgz#2216a64568bd3e0d5e4338be6d35bc98ae02a0c0"
integrity sha512-4mnnOOvPsDaVeAWa/aPZmnO0ajZH806yUSw5U4oFsl50kIRg05qLSsX0MymT5TU7mZLsCrbyG2+CUQBG4Jn98Q==
dependencies:
"@babel/runtime" "^7.4.5"
react-vtkjs-viewport "0.0.11"
vtk.js "^8.13.0"
vtk.js "^9.0.1"
"@ohif/i18n@0.2.1":
version "0.2.1"
@@ -1294,10 +1294,10 @@
locize-lastused "^1.1.0"
rollup-plugin-json "^4.0.0"
"@ohif/i18n@0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@ohif/i18n/-/i18n-0.2.2.tgz#dfb747d07d5cf009f72c3462d779413ebd16bf89"
integrity sha512-HYP0kOZ3oIEvWV6lYaorR9VQGtOUw9r3Z++EYbAAAapiq0IPZDbhVqDIr2RGxcrmEK0jIbyQEqotllf2KAj/nA==
"@ohif/i18n@0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@ohif/i18n/-/i18n-0.2.3.tgz#ce8d4b5c26973be864c9ebbea1a6564950d6ce2c"
integrity sha512-Qo73rU2RzpJOainiR4uy2mCiJG9zCOkhduhHsATfX+1zfFKEz90I7YH2Lba8SSolg08ABQ/a/W4s74zsocoK4g==
dependencies:
"@babel/runtime" "^7.2.0"
classnames "^2.2.6"
@@ -4557,12 +4557,12 @@ dezalgo@^1.0.0, dezalgo@~1.0.3:
asap "^2.0.0"
wrappy "1"
dicom-microscopy-viewer@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/dicom-microscopy-viewer/-/dicom-microscopy-viewer-0.5.0.tgz#e4f74261337d8a78d51490af0d17edc63997e619"
integrity sha512-r3BPLBvexv9v/Rr/FBTgXgp7orIFKLWW5uYM6IsYpz36ttU84Edk7Z2GAyk6887QNsfEMLzYV+5ik6HRrMg0cA==
dicom-microscopy-viewer@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/dicom-microscopy-viewer/-/dicom-microscopy-viewer-0.6.1.tgz#7b593da241d048154a9c1ebcbccf389742c2af18"
integrity sha512-ZQ1QsQswAh7Yw01ba3LZXCIh7WnEYDjhSxJt9vdfRZ5iHlbgW2ghvUHR7GP80UnWJg335scNmIcqJvwxVjlIsg==
dependencies:
dicomweb-client "^0.4.2"
dicomweb-client "^0.5.2"
ol "^5.3.0"
dicom-parser@^1.8.1, dicom-parser@^1.8.3:
@@ -4570,10 +4570,10 @@ dicom-parser@^1.8.1, dicom-parser@^1.8.3:
resolved "https://registry.yarnpkg.com/dicom-parser/-/dicom-parser-1.8.3.tgz#6e4b862898112304db30143147562011c1ce6a4d"
integrity sha512-CMeUr+jea7Ml70N+/Z5Pd2MYtvLp6IU+TnvdLe6VRVKzZuTeYLYyuAQa9R+sFK4v4N39hig+hKHN+Wfi9sQ6GA==
dicomweb-client@^0.4.2, dicomweb-client@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.4.4.tgz#0ca0c7706556f3114330a3c40946ee66808148e4"
integrity sha512-5S7wLYxQgHnOyEgR1zlZlt79IjzOk+YDB/Jjzte6ijRZsAoj9RUiIZcsTyxvBD9gLMYs/954n2kYHdbz83Xbtw==
dicomweb-client@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.5.2.tgz#aa5a4a6a5044b0702bb0a8a2662c86cd16901951"
integrity sha512-e11n2+g7HfBuMyopWq76W11eSZJ707g4U1XiO8URA+23aoe0g1kGAtlPB29NKXl7zX7RznTJ7wfRBxFkW6EJDA==
diff-sequences@^24.3.0:
version "24.3.0"
@@ -10501,24 +10501,26 @@ octokit-pagination-methods@^1.1.0:
resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4"
integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==
ohif-core@0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.9.1.tgz#72f3ebf1293b39c5dba7a58554fb6b4aa6be7dba"
integrity sha512-x6guTsYFB4H6cOUhexKDszH8lwiWDRronMtnLd/NbsHVonD60FEKatwaJRmxa5ZhH87dLCDacoQUGyFHa43OnQ==
ohif-core@0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.11.0.tgz#7abd1e62c037209f3029aa8fc7cc5ecd5788dada"
integrity sha512-SeJ/w+j2CIsv7dbFsnZXtdshbR6AZM13MJKv7nFtrSUnYX6O8nG5TBFm/61Qj4fN/uZ3Nq0I45NB7GD0slOZ4A==
dependencies:
"@babel/runtime" "^7.2.0"
ajv "^6.10.0"
dicomweb-client "^0.4.2"
dicomweb-client "^0.5.2"
isomorphic-base64 "^1.0.2"
lodash.clonedeep "^4.5.0"
lodash.merge "^4.6.1"
mousetrap "^1.6.3"
validate.js "^0.12.0"
oidc-client@1.7.x:
version "1.7.1"
resolved "https://registry.yarnpkg.com/oidc-client/-/oidc-client-1.7.1.tgz#8b9d8d50fd7f878968b1cda17712c1747eef9a54"
integrity sha512-qsPBQVa/BY6AmdY89erANJbfDXrX1dqu9lKgvYZzkVDzIj5mmw6wGjFeQuV2HDm4TiJA0VT5HSTWOWnXZUYu0g==
oidc-client@1.8.x:
version "1.8.2"
resolved "https://registry.yarnpkg.com/oidc-client/-/oidc-client-1.8.2.tgz#5a73c33858fe0e25489fdc6de31c8ce3075f6e0b"
integrity sha512-WwoSY8S6QyNN3qpne88YurjNqjTf6z1Xr0y+OrFVvdnVPYcefkTtXlZ5iOwR2JrmP4vBuq2j8eTjUJyDZFrFNQ==
dependencies:
uuid "^3.3.2"
ol@^5.3.0:
version "5.3.3"
@@ -12408,10 +12410,10 @@ react-bootstrap-modal@4.2.0:
react-overlays "^0.8.0"
react-transition-group "^2.0.0"
react-cornerstone-viewport@0.1.31:
version "0.1.31"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.31.tgz#ded8a688dad273846078b3336b72f59f134f30f2"
integrity sha512-e2A4FkoSpZiB2iwnYjC2UI98+KPY03ODp2jKmuJDE3pn3cIE581Bg/0NQyCKoAnRMO/TUsZSoq/GYTw/1C3kUg==
react-cornerstone-viewport@0.1.32:
version "0.1.32"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.32.tgz#0777d1f3497b27b017aa5eae3d1d4c078383219b"
integrity sha512-NdFsRq4kMgE6zpZo+DEnlQzC2B6OxOgFTkLCTDTYif0IxoXzKhngXP4xujwrUGjud98mTQKtiJOM0ah/fns3og==
dependencies:
lodash.debounce "^4.0.8"
moment "^2.23.0"
@@ -12487,7 +12489,7 @@ react-dnd@8.0.3:
hoist-non-react-statics "^3.3.0"
shallowequal "^1.1.0"
react-dom@^16.7.0:
react-dom@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==
@@ -12698,10 +12700,10 @@ react-transition-group@^4.1.1:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-viewerbase@0.17.0:
version "0.17.0"
resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.17.0.tgz#e741f94b24b6cef419fdd32b9bcfcdcfe81783dc"
integrity sha512-fy51pHrdhdXcPg6Pb1l8S5fzxlenFVhRUe80ZFq1aK9omrQXgaBF0uhm537WREyx2CS0/ZOD/wQnnbyjqEvYdQ==
react-viewerbase@0.17.6:
version "0.17.6"
resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.17.6.tgz#21dcc3a2a48174d235bda47aad97c339dcf3135a"
integrity sha512-8kbXBbz1sIqlpLBWGjeSyua/axeAxNqy28DLPVVZlBuoTjDwyhdliuZhkDiQOHpv0POuYn3zxZdZcus7jAd5iQ==
dependencies:
"@babel/runtime" "7.2.0"
"@ohif/i18n" "0.2.1"
@@ -12758,7 +12760,7 @@ react-with-styles@^3.2.0:
prop-types "^15.6.2"
react-with-direction "^1.3.0"
react@^16.7.0:
react@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==
@@ -13541,6 +13543,14 @@ rollup-plugin-postcss@^2.0.3:
rollup-pluginutils "^2.0.1"
style-inject "^0.3.0"
rollup-plugin-replace@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-replace/-/rollup-plugin-replace-2.2.0.tgz#f41ae5372e11e7a217cde349c8b5d5fd115e70e3"
integrity sha512-/5bxtUPkDHyBJAKketb4NfaeZjL5yLZdeUihSfbF2PQMz+rSTEb8ARKoOl3UBT4m7/X+QOXJo3sLTcq+yMMYTA==
dependencies:
magic-string "^0.25.2"
rollup-pluginutils "^2.6.0"
rollup-plugin-serve@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/rollup-plugin-serve/-/rollup-plugin-serve-1.0.1.tgz#2da2a784a916c5564609c7696cd9dacdbf17f6cc"
@@ -13558,7 +13568,7 @@ rollup-plugin-url@^2.2.2:
mkpath "^1.0.0"
rollup-pluginutils "^2.8.1"
rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.5.0, rollup-pluginutils@^2.8.1:
rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.5.0, rollup-pluginutils@^2.6.0, rollup-pluginutils@^2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz#8fa6dd0697344938ef26c2c09d2488ce9e33ce97"
integrity sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==
@@ -15600,10 +15610,10 @@ void-elements@^2.0.1:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
vtk.js@^8.13.0:
version "8.13.0"
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-8.13.0.tgz#d22bbe3403d86f979703506f9be83ab8e5099248"
integrity sha512-uoq2U0Yu2XjuKeeduuGRXlphHR6cdIvtZ5useNMJ8FobK9dpeFTT4ncoyPXx77KvwOMSueT8W+ngm/e9+FGZtA==
vtk.js@^9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-9.0.1.tgz#fa769e2f14c2e4546a205417ae861cc9d715e5ff"
integrity sha512-4GG2xu9gVXoL6Q0yyKMCIs09/yJcVLinDvHY33MBeMslKf3u6dO3qVMIh0lAXYJQcVKi/mFrMfary3PPF/JmDA==
dependencies:
base64-js "1.2.1"
blueimp-md5 "2.10.0"