Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72ec0bffb5 | ||
|
|
82c6c3c353 | ||
|
|
1d38fe30a4 | ||
|
|
666964b6d7 | ||
|
|
fa4ee5c559 | ||
|
|
cd58560e9c | ||
|
|
16afa740b6 | ||
|
|
6715ad9bd6 |
No files matched your search
@@ -1,6 +1,5 @@
|
||||
server {
|
||||
listen ${PORT} default_server;
|
||||
listen [::]:${PORT} default_server;
|
||||
listen ${PORT};
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
server {
|
||||
listen ${SSL_PORT} ssl http2 default_server;
|
||||
listen [::]:${SSL_PORT} ssl http2 default_server;
|
||||
ssl_certificate /etc/ssl/certs/ssl-certificate.crt;
|
||||
ssl_certificate_key /etc/ssl/private/ssl-private-key.key;
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cross-Origin-Opener-Policy same-origin;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
add_header Cross-Origin-Resource-Policy same-origin;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||
}
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -n "$SSL_PORT" ]
|
||||
then
|
||||
envsubst '${SSL_PORT}:${PORT}' < /usr/src/default.ssl.conf.template > /etc/nginx/conf.d/default.conf
|
||||
else
|
||||
envsubst '${PORT}' < /usr/src/default.conf.template > /etc/nginx/conf.d/default.conf
|
||||
fi
|
||||
|
||||
if [ -n "$APP_CONFIG" ]
|
||||
then
|
||||
echo "$APP_CONFIG" > /usr/share/nginx/html/app-config.js
|
||||
fi
|
||||
envsubst '${PORT}' < /usr/src/default.conf.template > /etc/nginx/conf.d/default.conf
|
||||
|
||||
if [ -n "$CLIENT_ID" ] || [ -n "$HEALTHCARE_API_ENDPOINT" ]
|
||||
then
|
||||
|
||||
@@ -73,6 +73,15 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
devServer: {
|
||||
open: true,
|
||||
port: 3000,
|
||||
historyApiFallback: true,
|
||||
headers: {
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
},
|
||||
},
|
||||
cache: {
|
||||
type: 'filesystem',
|
||||
},
|
||||
|
||||
+1
-6
@@ -61,7 +61,7 @@ RUN yarn run build
|
||||
|
||||
# Stage 3: Bundle the built application into a Docker container
|
||||
# which runs Nginx using Alpine Linux
|
||||
FROM nginxinc/nginx-unprivileged:1.25-alpine as final
|
||||
FROM nginxinc/nginx-unprivileged:1.23.1-alpine as final
|
||||
#RUN apk add --no-cache bash
|
||||
ENV PORT=80
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
@@ -69,10 +69,5 @@ USER nginx
|
||||
COPY --chown=nginx:nginx .docker/Viewer-v3.x /usr/src
|
||||
RUN chmod 777 /usr/src/entrypoint.sh
|
||||
COPY --from=builder /usr/src/app/platform/app/dist /usr/share/nginx/html
|
||||
# In entrypoint.sh, app-config.js might be overwritten, so chmod it to be writeable.
|
||||
# The nginx user cannot chmod it, so change to root.
|
||||
USER root
|
||||
RUN chmod 666 /usr/share/nginx/html/app-config.js
|
||||
USER nginx
|
||||
ENTRYPOINT ["/usr/src/entrypoint.sh"]
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -17,6 +17,10 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
|
||||
<div align="center">
|
||||
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
|
||||
</div>
|
||||
<div align="center">
|
||||
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
@@ -34,16 +38,7 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
|
||||
<!-- [](#contributors) -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
||||
| | | |
|
||||
| :-: | :--- | :--- |
|
||||
| <img src="platform/docs/docs/assets/img/demo-measurements.jpg" alt="Measurement tracking" width="350"/> | Measurement Tracking | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5) |
|
||||
| <img src="platform/docs/docs/assets/img/demo-segmentation.png" alt="Segmentations" width="350"/> | Labelmap Segmentations | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046) |
|
||||
| <img src="platform/docs/docs/assets/img/demo-ptct.png" alt="Hanging Protocols" width="350"/> | Fusion and Custom Hanging protocols | [Demo](https://viewer.ohif.org/tmtv?StudyInstanceUIDs=1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463) |
|
||||
| <img src="platform/docs/docs/assets/img/demo-microscopy.png" alt="Microscopy" width="350"/> | Slide Microscopy | [Demo](https://viewer.ohif.org/microscopy?StudyInstanceUIDs=2.25.275741864483510678566144889372061815320) |
|
||||
| <img src="platform/docs/docs/assets/img/demo-volumeRendering.png" alt="Volume Rendering" width="350"/> | Volume Rendering | [Demo](https://viewer.ohif.org/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5&hangingprotocolId=mprAnd3DVolumeViewport) |
|
||||
|
||||
|
||||

|
||||
|
||||
## About
|
||||
|
||||
@@ -90,14 +85,17 @@ forking).
|
||||
|
||||
### Support
|
||||
|
||||
We offer support through
|
||||
[GitHub Issues](https://github.com/OHIF/Viewers/issues/new/choose). You can:
|
||||
|
||||
- [Report a Bug 🐛](https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Community%3A+Report+%3Abug%3A%2CAwaiting+Reproduction&projects=&template=bug-report.yml&title=%5BBug%5D+)
|
||||
- [Request a Feature 🚀](https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Community%3A+Request+%3Ahand%3A&projects=&template=feature-request.yml&title=%5BFeature+Request%5D+)
|
||||
- [Ask a Question 🤗](community.ohif.org)
|
||||
- [Slack Channel](https://join.slack.com/t/cornerstonejs/shared_invite/zt-1r8xb2zau-dOxlD6jit3TN0Uwf928w9Q)
|
||||
|
||||
For commercial support, academic collaborations, and answers to common
|
||||
questions; please use [Get Support](https://ohif.org/get-support/) to contact
|
||||
us.
|
||||
questions; please read our
|
||||
[documented FAQ](https://docs.ohif.org/faq/index.html#does-ohif-offer-commercial-support).
|
||||
|
||||
|
||||
## Developing
|
||||
@@ -130,6 +128,9 @@ Here is a schematic representation of our development workflow:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Requirements
|
||||
|
||||
- [Yarn 1.17.3+](https://yarnpkg.com/en/docs/install)
|
||||
@@ -221,6 +222,15 @@ you'll see the following:
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
Want to better understand why and how we've structured this repository? Read
|
||||
more about it in our [Architecture Documentation][ohif-architecture].
|
||||
|
||||
|
||||
|
||||
| Name | Description | Links |
|
||||
| ---------------------------------------------------- | ----------------------------------------------------- | ---------------------- |
|
||||
| [@ohif/extension-cornerstone][extension-cornerstone] | 2D image viewing, annotation, and segementation tools | [NPM][cornerstone-npm] |
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
To acknowledge the OHIF Viewer in an academic publication, please cite
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
060085805510a046da3f5a5bb7dd2952e40d9b91
|
||||
1d38fe30a490010c7de487c7a0b1a5bfe3bc75a4
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "DICOM RT read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -31,10 +31,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/i18n": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/i18n": "3.6.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -181,6 +181,12 @@ export default async function loadRTStruct(
|
||||
ContourGeometricType,
|
||||
} = ContourSequenceArray[c];
|
||||
|
||||
const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID;
|
||||
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
|
||||
|
||||
if (!imageId) {
|
||||
continue;
|
||||
}
|
||||
let isSupported = false;
|
||||
|
||||
const points = [];
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
import hydrateRTDisplaySet from './_hydrateRT';
|
||||
|
||||
const RESPONSE = {
|
||||
@@ -39,12 +38,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
|
||||
const message = 'Do you want to open this Segmentation?';
|
||||
const actions = [
|
||||
{
|
||||
type: ButtonEnums.type.secondary,
|
||||
type: 'secondary',
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: ButtonEnums.type.primary,
|
||||
type: 'primary',
|
||||
text: 'Yes',
|
||||
value: RESPONSE.HYDRATE_SEG,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "DICOM SEG read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -31,10 +31,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/i18n": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/i18n": "3.6.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
|
||||
import { Input, Dialog } from '@ohif/ui';
|
||||
|
||||
function callInputDialog(uiDialogService, label, callback) {
|
||||
const dialogId = 'enter-segment-label';
|
||||
@@ -29,8 +29,8 @@ function callInputDialog(uiDialogService, label, callback) {
|
||||
noCloseButton: true,
|
||||
onClose: () => uiDialogService.dismiss({ id: dialogId }),
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Confirm', type: ButtonEnums.type.primary },
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Confirm', type: 'secondary' },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
body: ({ value, setValue }) => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
import hydrateSEGDisplaySet from './_hydrateSEG';
|
||||
|
||||
const RESPONSE = {
|
||||
@@ -7,7 +6,11 @@ const RESPONSE = {
|
||||
HYDRATE_SEG: 5,
|
||||
};
|
||||
|
||||
function promptHydrateSEG({ servicesManager, segDisplaySet, viewportIndex }) {
|
||||
function promptHydrateSEG({
|
||||
servicesManager,
|
||||
segDisplaySet,
|
||||
viewportIndex,
|
||||
}) {
|
||||
const { uiViewportDialogService } = servicesManager.services;
|
||||
|
||||
return new Promise(async function(resolve, reject) {
|
||||
@@ -33,12 +36,12 @@ function _askHydrate(uiViewportDialogService, viewportIndex) {
|
||||
const message = 'Do you want to open this Segmentation?';
|
||||
const actions = [
|
||||
{
|
||||
type: ButtonEnums.type.secondary,
|
||||
type: 'secondary',
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: ButtonEnums.type.primary,
|
||||
type: 'primary',
|
||||
text: 'Yes',
|
||||
value: RESPONSE.HYDRATE_SEG,
|
||||
},
|
||||
|
||||
@@ -71,8 +71,7 @@ function OHIFCornerstoneSEGViewport(props) {
|
||||
|
||||
const referencedDisplaySet = segDisplaySet.getReferenceDisplaySet();
|
||||
const referencedDisplaySetMetadata = _getReferencedDisplaySetMetadata(
|
||||
referencedDisplaySet,
|
||||
segDisplaySet
|
||||
referencedDisplaySet
|
||||
);
|
||||
|
||||
referencedDisplaySetRef.current = {
|
||||
@@ -344,10 +343,10 @@ function OHIFCornerstoneSEGViewport(props) {
|
||||
patientSex: PatientSex || '',
|
||||
patientAge: PatientAge || '',
|
||||
MRN: PatientID || '',
|
||||
thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}mm` : '',
|
||||
thickness: SliceThickness ? `${SliceThickness.toFixed(2)}mm` : '',
|
||||
spacing:
|
||||
SpacingBetweenSlices !== undefined
|
||||
? `${parseFloat(SpacingBetweenSlices).toFixed(2)}mm`
|
||||
? `${SpacingBetweenSlices.toFixed(2)}mm`
|
||||
: '',
|
||||
scanner: ManufacturerModelName || '',
|
||||
},
|
||||
@@ -382,28 +381,20 @@ OHIFCornerstoneSEGViewport.defaultProps = {
|
||||
customProps: {},
|
||||
};
|
||||
|
||||
function _getReferencedDisplaySetMetadata(referencedDisplaySet, segDisplaySet) {
|
||||
const {
|
||||
SharedFunctionalGroupsSequence: [SharedFunctionalGroup],
|
||||
} = segDisplaySet.instance;
|
||||
const {
|
||||
PixelMeasuresSequence: [PixelMeasures],
|
||||
} = SharedFunctionalGroup;
|
||||
const { SpacingBetweenSlices, SliceThickness } = PixelMeasures;
|
||||
|
||||
function _getReferencedDisplaySetMetadata(referencedDisplaySet) {
|
||||
const image0 = referencedDisplaySet.images[0];
|
||||
const referencedDisplaySetMetadata = {
|
||||
PatientID: image0.PatientID,
|
||||
PatientName: image0.PatientName,
|
||||
PatientSex: image0.PatientSex,
|
||||
PatientAge: image0.PatientAge,
|
||||
SliceThickness: image0.SliceThickness || SliceThickness,
|
||||
SliceThickness: image0.SliceThickness,
|
||||
StudyDate: image0.StudyDate,
|
||||
SeriesDescription: image0.SeriesDescription,
|
||||
SeriesInstanceUID: image0.SeriesInstanceUID,
|
||||
SeriesNumber: image0.SeriesNumber,
|
||||
ManufacturerModelName: image0.ManufacturerModelName,
|
||||
SpacingBetweenSlices: image0.SpacingBetweenSlices || SpacingBetweenSlices,
|
||||
SpacingBetweenSlices: image0.SpacingBetweenSlices,
|
||||
};
|
||||
|
||||
return referencedDisplaySetMetadata;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF extension for an SR Cornerstone Viewport",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -32,10 +32,10 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-measurement-tracking": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
@@ -44,9 +44,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^1.4.1",
|
||||
"@cornerstonejs/core": "^1.4.1",
|
||||
"@cornerstonejs/tools": "^1.4.1",
|
||||
"@cornerstonejs/adapters": "^1.1.0",
|
||||
"@cornerstonejs/core": "^1.1.0",
|
||||
"@cornerstonejs/tools": "^1.1.0",
|
||||
"classnames": "^2.3.2"
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,6 @@ function OHIFCornerstoneSRViewport(props) {
|
||||
}}
|
||||
onElementEnabled={onElementEnabled}
|
||||
initialImageIndex={initialImageIndex}
|
||||
isJumpToMeasurementDisabled={true}
|
||||
></Component>
|
||||
);
|
||||
}, [activeImageDisplaySetData, viewportIndex, measurementSelected]);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -36,9 +36,9 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^1.4.1",
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@cornerstonejs/dicom-image-loader": "^0.6.8",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"dcmjs": "^0.29.6",
|
||||
"dicom-parser": "^1.8.21",
|
||||
"hammerjs": "^2.0.8",
|
||||
@@ -52,10 +52,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^1.4.1",
|
||||
"@cornerstonejs/core": "^1.4.1",
|
||||
"@cornerstonejs/streaming-image-volume-loader": "^1.4.1",
|
||||
"@cornerstonejs/tools": "^1.4.1",
|
||||
"@cornerstonejs/adapters": "^1.1.0",
|
||||
"@cornerstonejs/core": "^1.1.0",
|
||||
"@cornerstonejs/streaming-image-volume-loader": "^1.1.0",
|
||||
"@cornerstonejs/tools": "^1.1.0",
|
||||
"@kitware/vtk.js": "27.3.1",
|
||||
"html2canvas": "^1.4.1",
|
||||
"lodash.debounce": "4.0.8",
|
||||
|
||||
@@ -119,7 +119,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
servicesManager,
|
||||
onElementEnabled,
|
||||
onElementDisabled,
|
||||
isJumpToMeasurementDisabled,
|
||||
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
|
||||
// of the imageData in the OHIFCornerstoneViewport. This prop is used
|
||||
// to set the initial state of the viewport's first image to render
|
||||
@@ -455,10 +454,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
* the cache for jumping to see if there is any jump queued, then we jump to the correct slice.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (isJumpToMeasurementDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unsubscribeFromJumpToMeasurementEvents = _subscribeToJumpToMeasurementEvents(
|
||||
measurementService,
|
||||
displaySetService,
|
||||
@@ -721,10 +716,6 @@ function _jumpToMeasurement(
|
||||
// Component displayName
|
||||
OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
|
||||
|
||||
OHIFCornerstoneViewport.defaultProps = {
|
||||
isJumpToMeasurementDisabled: false,
|
||||
};
|
||||
|
||||
OHIFCornerstoneViewport.propTypes = {
|
||||
viewportIndex: PropTypes.number.isRequired,
|
||||
displaySets: PropTypes.array.isRequired,
|
||||
@@ -733,7 +724,6 @@ OHIFCornerstoneViewport.propTypes = {
|
||||
displaySetOptions: PropTypes.arrayOf(PropTypes.any),
|
||||
servicesManager: PropTypes.object.isRequired,
|
||||
onElementEnabled: PropTypes.func,
|
||||
isJumpToMeasurementDisabled: PropTypes.bool,
|
||||
// Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation
|
||||
// of the imageData in the OHIFCornerstoneViewport. This prop is used
|
||||
// to set the initial state of the viewport's first image to render
|
||||
|
||||
@@ -379,7 +379,7 @@ function _getViewportInstance(viewportData, imageIndex) {
|
||||
if (viewportData.viewportType === Enums.ViewportType.STACK) {
|
||||
imageId = viewportData.data.imageIds[imageIndex];
|
||||
} else if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
|
||||
const volumes = viewportData.data;
|
||||
const volumes = viewportData.volumes;
|
||||
if (volumes && volumes.length == 1) {
|
||||
const volume = volumes[0];
|
||||
imageId = volume.imageIds[imageIndex];
|
||||
|
||||
@@ -457,9 +457,11 @@ function commandsModule({
|
||||
|
||||
const { viewport } = enabledElement;
|
||||
|
||||
const { invert } = viewport.getProperties();
|
||||
viewport.setProperties({ invert: !invert });
|
||||
viewport.render();
|
||||
if (viewport instanceof StackViewport) {
|
||||
const { invert } = viewport.getProperties();
|
||||
viewport.setProperties({ invert: !invert });
|
||||
viewport.render();
|
||||
}
|
||||
},
|
||||
resetViewport: () => {
|
||||
const enabledElement = _getActiveViewportEnabledElement();
|
||||
|
||||
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import DicomFileUploader from '../../utils/DicomFileUploader';
|
||||
import DicomUploadProgress from './DicomUploadProgress';
|
||||
import { Button, ButtonEnums } from '@ohif/ui';
|
||||
import { Button } from '@ohif/ui';
|
||||
import './DicomUpload.css';
|
||||
|
||||
type DicomUploadProps = {
|
||||
@@ -46,7 +46,12 @@ function DicomUpload({
|
||||
<Dropzone onDrop={onDrop} noDrag>
|
||||
{({ getRootProps, getInputProps }) => (
|
||||
<div {...getRootProps()}>
|
||||
<Button disabled={false} onClick={() => {}}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={false}
|
||||
onClick={() => {}}
|
||||
>
|
||||
{'Add files'}
|
||||
<input {...getInputProps()} />
|
||||
</Button>
|
||||
@@ -57,7 +62,9 @@ function DicomUpload({
|
||||
{({ getRootProps, getInputProps }) => (
|
||||
<div {...getRootProps()}>
|
||||
<Button
|
||||
type={ButtonEnums.type.secondary}
|
||||
variant="contained"
|
||||
color="primaryDark"
|
||||
border="primaryActive"
|
||||
disabled={false}
|
||||
onClick={() => {}}
|
||||
>
|
||||
|
||||
@@ -308,7 +308,13 @@ function DicomUploadProgress({
|
||||
} ${
|
||||
dicomFileUploaderArr.length > 1 ? 'files' : 'file'
|
||||
} completed.`}</span>
|
||||
<Button disabled={false} className="ml-auto" onClick={onComplete}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={false}
|
||||
className="ml-auto"
|
||||
onClick={onComplete}
|
||||
>
|
||||
{'Close'}
|
||||
</Button>
|
||||
</>
|
||||
|
||||
@@ -27,6 +27,7 @@ const DicomUploadProgressItem = memo(
|
||||
const [failedReason, setFailedReason] = useState('');
|
||||
const [status, setStatus] = useState(dicomFileUploader.getStatus());
|
||||
|
||||
console.info(`${dicomFileUploader.getFileId()}`);
|
||||
const isComplete = useCallback(() => {
|
||||
return (
|
||||
status === UploadStatus.Failed ||
|
||||
|
||||
@@ -24,6 +24,7 @@ import { toolNames } from './initCornerstoneTools';
|
||||
import { getEnabledElement, reset as enabledElementReset } from './state';
|
||||
import dicomLoaderService from './utils/dicomLoaderService';
|
||||
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
|
||||
import { registerColormap } from './utils/colormap/transferFunctionHelpers';
|
||||
|
||||
import { id } from './id';
|
||||
import * as csWADOImageLoader from './initWADOImageLoader.js';
|
||||
|
||||
@@ -26,7 +26,6 @@ import nthLoader from './utils/nthLoader';
|
||||
import interleaveTopToBottom from './utils/interleaveTopToBottom';
|
||||
import initContextMenu from './initContextMenu';
|
||||
import initDoubleClick from './initDoubleClick';
|
||||
import { CornerstoneServices } from './types';
|
||||
|
||||
// TODO: Cypress tests are currently grabbing this from the window?
|
||||
window.cornerstone = cornerstone;
|
||||
@@ -70,7 +69,10 @@ export default async function init({
|
||||
|
||||
const {
|
||||
userAuthenticationService,
|
||||
measurementService,
|
||||
customizationService,
|
||||
displaySetService,
|
||||
uiDialogService,
|
||||
uiModalService,
|
||||
uiNotificationService,
|
||||
cineService,
|
||||
@@ -79,7 +81,7 @@ export default async function init({
|
||||
toolGroupService,
|
||||
viewportGridService,
|
||||
stateSyncService,
|
||||
} = servicesManager.services as CornerstoneServices;
|
||||
} = servicesManager.services;
|
||||
|
||||
window.services = servicesManager.services;
|
||||
window.extensionManager = extensionManager;
|
||||
@@ -164,7 +166,7 @@ export default async function init({
|
||||
prefetch: appConfig?.maxNumRequests?.prefetch || 10,
|
||||
};
|
||||
|
||||
initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);
|
||||
initWADOImageLoader(userAuthenticationService, appConfig);
|
||||
|
||||
/* Measurement Service */
|
||||
this.measurementServiceSource = connectToolsToMeasurementService(
|
||||
|
||||
@@ -5,7 +5,7 @@ import dicomImageLoader, {
|
||||
webWorkerManager,
|
||||
} from '@cornerstonejs/dicom-image-loader';
|
||||
import dicomParser from 'dicom-parser';
|
||||
import { errorHandler, utils } from '@ohif/core';
|
||||
import { errorHandler } from '@ohif/core';
|
||||
|
||||
const { registerVolumeLoader } = volumeLoader;
|
||||
|
||||
@@ -35,8 +35,7 @@ function initWebWorkers(appConfig) {
|
||||
|
||||
export default function initWADOImageLoader(
|
||||
userAuthenticationService,
|
||||
appConfig,
|
||||
extensionManager
|
||||
appConfig
|
||||
) {
|
||||
dicomImageLoader.external.cornerstone = cornerstone;
|
||||
dicomImageLoader.external.dicomParser = dicomParser;
|
||||
@@ -56,18 +55,18 @@ export default function initWADOImageLoader(
|
||||
convertFloatPixelDataToInt: false,
|
||||
},
|
||||
beforeSend: function(xhr) {
|
||||
//TODO should be removed in the future and request emitted by DicomWebDataSource
|
||||
const sourceConfig =
|
||||
extensionManager.getActiveDataSource()?.[0].getConfig() ?? {};
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
const acceptHeader = utils.generateAcceptHeader(
|
||||
sourceConfig.acceptHeader,
|
||||
sourceConfig.requestTransferSyntaxUID,
|
||||
sourceConfig.omitQuotationForMultipartRequest
|
||||
);
|
||||
|
||||
// Request:
|
||||
// JPEG-LS Lossless (1.2.840.10008.1.2.4.80) if available, otherwise accept
|
||||
// whatever transfer-syntax the origin server provides.
|
||||
// For now we use image/jls and image/x-jls because some servers still use the old type
|
||||
// http://dicom.nema.org/medical/dicom/current/output/html/part18.html
|
||||
const xhrRequestHeaders = {
|
||||
Accept: acceptHeader,
|
||||
Accept: appConfig.omitQuotationForMultipartRequest
|
||||
? 'multipart/related; type=application/octet-stream'
|
||||
: 'multipart/related; type="application/octet-stream"',
|
||||
// 'multipart/related; type="image/x-jls", multipart/related; type="image/jls"; transfer-syntax="1.2.840.10008.1.2.4.80", multipart/related; type="image/x-jls", multipart/related; type="application/octet-stream"; transfer-syntax=*',
|
||||
};
|
||||
|
||||
if (headers) {
|
||||
|
||||
@@ -117,7 +117,7 @@ class SegmentationService extends PubSubService {
|
||||
* -- opacity: the opacity of the segment
|
||||
* -- visibility: the visibility of the segment (boolean)
|
||||
* -- isLocked: whether the segment is locked for editing
|
||||
* -- active: whether the segment is currently the active segment to be edited
|
||||
* -- active: whether the segment is currently the active segment to be edited or not
|
||||
*/
|
||||
public addSegment(
|
||||
segmentationId: string,
|
||||
@@ -542,7 +542,6 @@ class SegmentationService extends PubSubService {
|
||||
id: segmentationId,
|
||||
displaySetInstanceUID: segDisplaySet.displaySetInstanceUID,
|
||||
type: representationType,
|
||||
label: segDisplaySet.SeriesDescription,
|
||||
representationData: {
|
||||
[LABELMAP]: {
|
||||
volumeId: segmentationId,
|
||||
@@ -790,7 +789,6 @@ class SegmentationService extends PubSubService {
|
||||
id: segmentationId,
|
||||
displaySetInstanceUID: rtDisplaySetUID,
|
||||
type: representationType,
|
||||
label: rtDisplaySet.SeriesDescription,
|
||||
representationData: {
|
||||
[CONTOUR]: {
|
||||
geometryIds,
|
||||
@@ -818,54 +816,45 @@ class SegmentationService extends PubSubService {
|
||||
const segmentsCachedStats = {};
|
||||
const initializeContour = async rtStructData => {
|
||||
const { data, id, color, segmentIndex, geometryId } = rtStructData;
|
||||
|
||||
// catch error instead of failing to allow loading to continue
|
||||
try {
|
||||
const geometry = await geometryLoader.createAndCacheGeometry(
|
||||
geometryId,
|
||||
{
|
||||
geometryData: {
|
||||
data,
|
||||
id,
|
||||
color,
|
||||
frameOfReferenceUID: structureSet.frameOfReferenceUID,
|
||||
segmentIndex,
|
||||
},
|
||||
type: csEnums.GeometryType.CONTOUR,
|
||||
}
|
||||
);
|
||||
|
||||
const contourSet = geometry.data;
|
||||
const centroid = contourSet.getCentroid();
|
||||
|
||||
segmentsCachedStats[segmentIndex] = {
|
||||
center: { world: centroid },
|
||||
modifiedTime: rtDisplaySet.SeriesDate, // we use the SeriesDate as the modifiedTime since this is the first time we are creating the segmentation
|
||||
};
|
||||
|
||||
segmentation.segments[segmentIndex] = {
|
||||
label: id,
|
||||
segmentIndex,
|
||||
const geometry = await geometryLoader.createAndCacheGeometry(geometryId, {
|
||||
geometryData: {
|
||||
data,
|
||||
id,
|
||||
color,
|
||||
...SEGMENT_CONSTANT,
|
||||
};
|
||||
frameOfReferenceUID: structureSet.frameOfReferenceUID,
|
||||
segmentIndex,
|
||||
},
|
||||
type: csEnums.GeometryType.CONTOUR,
|
||||
});
|
||||
|
||||
const numInitialized = Object.keys(segmentsCachedStats).length;
|
||||
const contourSet = geometry.data;
|
||||
const centroid = contourSet.getCentroid();
|
||||
|
||||
// Calculate percentage completed
|
||||
const percentComplete = Math.round(
|
||||
(numInitialized / allRTStructData.length) * 100
|
||||
);
|
||||
segmentsCachedStats[segmentIndex] = {
|
||||
center: { world: centroid },
|
||||
modifiedTime: rtDisplaySet.SeriesDate, // we use the SeriesDate as the modifiedTime since this is the first time we are creating the segmentation
|
||||
};
|
||||
|
||||
this._broadcastEvent(EVENTS.SEGMENT_LOADING_COMPLETE, {
|
||||
percentComplete,
|
||||
// Note: this is not the geometryIds length since there might be
|
||||
// some missing ROINumbers
|
||||
numSegments: allRTStructData.length,
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
segmentation.segments[segmentIndex] = {
|
||||
label: id,
|
||||
segmentIndex,
|
||||
color,
|
||||
...SEGMENT_CONSTANT,
|
||||
};
|
||||
|
||||
const numInitialized = Object.keys(segmentsCachedStats).length;
|
||||
|
||||
// Calculate percentage completed
|
||||
const percentComplete = Math.round(
|
||||
(numInitialized / allRTStructData.length) * 100
|
||||
);
|
||||
|
||||
this._broadcastEvent(EVENTS.SEGMENT_LOADING_COMPLETE, {
|
||||
percentComplete,
|
||||
// Note: this is not the geometryIds length since there might be
|
||||
// some missing ROINumbers
|
||||
numSegments: allRTStructData.length,
|
||||
});
|
||||
};
|
||||
|
||||
const promiseArray = [];
|
||||
|
||||
@@ -15,7 +15,7 @@ const EVENTS = {
|
||||
* sync group declared.
|
||||
*/
|
||||
export type SyncCreator = (
|
||||
id: string,
|
||||
type: string,
|
||||
options?: Record<string, unknown>
|
||||
) => Synchronizer;
|
||||
|
||||
@@ -83,7 +83,7 @@ export default class SyncGroupService {
|
||||
* @param type is the type of the synchronizer to create
|
||||
* @param creator
|
||||
*/
|
||||
public addSynchronizerType(type: string, creator: SyncCreator): void {
|
||||
public setSynchronizer(type: string, creator: SyncCreator): void {
|
||||
this.synchronizerCreators[type.toLowerCase()] = creator;
|
||||
}
|
||||
|
||||
|
||||
@@ -745,7 +745,7 @@ class CornerstoneViewportService extends PubSubService
|
||||
const viewport = this.getCornerstoneViewport(viewportId);
|
||||
const viewportCamera = viewport.getCamera();
|
||||
|
||||
if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
|
||||
if (viewport instanceof VolumeViewport) {
|
||||
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
|
||||
if (keepCamera) {
|
||||
viewport.setCamera(viewportCamera);
|
||||
|
||||
@@ -198,9 +198,7 @@ class ViewportInfo {
|
||||
// via cornerstoneViewportService
|
||||
let viewportData = this.getViewportData();
|
||||
|
||||
if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC ||
|
||||
viewportData.viewportType === Enums.ViewportType.VOLUME_3D
|
||||
) {
|
||||
if (viewportData.viewportType === Enums.ViewportType.ORTHOGRAPHIC) {
|
||||
viewportData = viewportData as VolumeViewportData;
|
||||
return viewportData.data.some(
|
||||
({ displaySetInstanceUID: dsUID }) => dsUID === displaySetInstanceUID
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Types } from '@ohif/core';
|
||||
import ToolGroupService from '../services/ToolGroupService';
|
||||
import SyncGroupService from '../services/SyncGroupService';
|
||||
import SegmentationService from '../services/SegmentationService';
|
||||
import CornerstoneCacheService from '../services/CornerstoneCacheService';
|
||||
import CornerstoneViewportService from '../services/ViewportService/CornerstoneViewportService';
|
||||
import ToolGroupService from './services/ToolGroupService';
|
||||
import SyncGroupService from './services/SyncGroupService';
|
||||
import SegmentationService from './services/SegmentationService';
|
||||
import CornerstoneCacheService from './services/CornerstoneCacheService';
|
||||
import CornerstoneViewportService from './services/ViewportService/CornerstoneViewportService';
|
||||
|
||||
interface CornerstoneServices extends Types.Services {
|
||||
cornerstoneViewportService: CornerstoneViewportService;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
|
||||
import { Input, Dialog } from '@ohif/ui';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -60,8 +60,8 @@ function callInputDialog(
|
||||
noCloseButton: true,
|
||||
onClose: () => uiDialogService.dismiss({ id: dialogId }),
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
body: ({ value, setValue }) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-default",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "Common/default features and functionality for basic image viewing",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -30,8 +30,8 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/i18n": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/i18n": "3.6.0",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicomweb-client": "^0.10.2",
|
||||
"prop-types": "^15.6.2",
|
||||
|
||||
@@ -60,42 +60,15 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
supportsReject,
|
||||
staticWado,
|
||||
singlepart,
|
||||
omitQuotationForMultipartRequest,
|
||||
acceptHeader,
|
||||
requestTransferSyntaxUID,
|
||||
} = dicomWebConfig;
|
||||
|
||||
const dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));
|
||||
|
||||
const getAuthrorizationHeader = () => {
|
||||
const xhrRequestHeaders = {};
|
||||
const authHeaders = userAuthenticationService.getAuthorizationHeader();
|
||||
if (authHeaders && authHeaders.Authorization) {
|
||||
xhrRequestHeaders.Authorization = authHeaders.Authorization;
|
||||
}
|
||||
return xhrRequestHeaders;
|
||||
};
|
||||
|
||||
const generateWadoHeader = () => {
|
||||
let authorizationHeader = getAuthrorizationHeader();
|
||||
//Generate accept header depending on config params
|
||||
let formattedAcceptHeader = utils.generateAcceptHeader(
|
||||
acceptHeader,
|
||||
requestTransferSyntaxUID,
|
||||
omitQuotationForMultipartRequest
|
||||
);
|
||||
|
||||
return {
|
||||
...authorizationHeader,
|
||||
Accept: formattedAcceptHeader,
|
||||
};
|
||||
};
|
||||
|
||||
const qidoConfig = {
|
||||
url: qidoRoot,
|
||||
staticWado,
|
||||
singlepart,
|
||||
headers: getAuthrorizationHeader(),
|
||||
headers: userAuthenticationService.getAuthorizationHeader(),
|
||||
errorInterceptor: errorHandler.getHTTPErrorHandler(),
|
||||
};
|
||||
|
||||
@@ -103,7 +76,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
url: wadoRoot,
|
||||
staticWado,
|
||||
singlepart,
|
||||
headers: generateWadoHeader(),
|
||||
headers: userAuthenticationService.getAuthorizationHeader(),
|
||||
errorInterceptor: errorHandler.getHTTPErrorHandler(),
|
||||
};
|
||||
|
||||
@@ -137,7 +110,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
studies: {
|
||||
mapParams: mapParams.bind(),
|
||||
search: async function(origParams) {
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
qidoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
const { studyInstanceUid, seriesInstanceUid, ...mappedParams } =
|
||||
mapParams(origParams, {
|
||||
supportsFuzzyMatching,
|
||||
@@ -158,7 +135,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
series: {
|
||||
// mapParams: mapParams.bind(),
|
||||
search: async function(studyInstanceUid) {
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
qidoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
const results = await seriesInStudy(
|
||||
qidoDicomWebClient,
|
||||
studyInstanceUid
|
||||
@@ -170,7 +151,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
},
|
||||
instances: {
|
||||
search: (studyInstanceUid, queryParameters) => {
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
qidoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
qidoSearch.call(
|
||||
undefined,
|
||||
qidoDicomWebClient,
|
||||
@@ -197,7 +182,6 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
return getDirectURL({ wadoRoot, singlepart }, params);
|
||||
},
|
||||
bulkDataURI: async ({ StudyInstanceUID, BulkDataURI }) => {
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const options = {
|
||||
multipart: false,
|
||||
BulkDataURI,
|
||||
@@ -216,6 +200,11 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
sortFunction,
|
||||
madeInClient = false,
|
||||
} = {}) => {
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
wadoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
if (!StudyInstanceUID) {
|
||||
throw new Error(
|
||||
'Unable to query for SeriesMetadata without StudyInstanceUID'
|
||||
@@ -245,12 +234,17 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
|
||||
store: {
|
||||
dicom: async (dataset, request) => {
|
||||
wadoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
const headers = userAuthenticationService.getAuthorizationHeader();
|
||||
if (headers) {
|
||||
wadoDicomWebClient.headers = headers;
|
||||
}
|
||||
|
||||
if (dataset instanceof ArrayBuffer) {
|
||||
const options = {
|
||||
datasets: [dataset],
|
||||
request,
|
||||
};
|
||||
|
||||
await wadoDicomWebClient.storeInstances(options);
|
||||
} else {
|
||||
const meta = {
|
||||
@@ -288,7 +282,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
madeInClient
|
||||
) => {
|
||||
const enableStudyLazyLoad = false;
|
||||
wadoDicomWebClient.headers = generateWadoHeader();
|
||||
|
||||
// data is all SOPInstanceUIDs
|
||||
const data = await retrieveStudyMetadata(
|
||||
wadoDicomWebClient,
|
||||
@@ -359,7 +353,6 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
madeInClient = false
|
||||
) => {
|
||||
const enableStudyLazyLoad = true;
|
||||
wadoDicomWebClient.headers = generateWadoHeader();
|
||||
// Get Series
|
||||
const {
|
||||
preLoadData: seriesSummaryMetadata,
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { LegacyButton, ButtonGroup } from '@ohif/ui';
|
||||
import { Button, ButtonGroup } from '@ohif/ui';
|
||||
|
||||
function ActionButtons({ onExportClick, onCreateReportClick }) {
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
@@ -10,16 +10,12 @@ function ActionButtons({ onExportClick, onCreateReportClick }) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ButtonGroup color="black" size="inherit">
|
||||
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
|
||||
<LegacyButton className="px-2 py-2 text-base" onClick={onExportClick}>
|
||||
<Button className="px-2 py-2 text-base" onClick={onExportClick}>
|
||||
{t('Export CSV')}
|
||||
</LegacyButton>
|
||||
<LegacyButton
|
||||
className="px-2 py-2 text-base"
|
||||
onClick={onCreateReportClick}
|
||||
>
|
||||
</Button>
|
||||
<Button className="px-2 py-2 text-base" onClick={onCreateReportClick}>
|
||||
{t('Create Report')}
|
||||
</LegacyButton>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import classnames from 'classnames';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAppConfig } from '@state';
|
||||
|
||||
import { Button, ButtonEnums } from '@ohif/ui';
|
||||
import { Button } from '@ohif/ui';
|
||||
|
||||
function DataSourceSelector() {
|
||||
const [appConfig] = useAppConfig();
|
||||
@@ -33,8 +33,7 @@ function DataSourceSelector() {
|
||||
<div key={ds.sourceName}>
|
||||
<h1 className="text-white">{ds.friendlyName}</h1>
|
||||
<Button
|
||||
type={ButtonEnums.type.primary}
|
||||
className={classnames('ml-2')}
|
||||
className={classnames('font-bold', 'ml-2')}
|
||||
onClick={() => {
|
||||
navigate({
|
||||
pathname: '/',
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { utils, ServicesManager } from '@ohif/core';
|
||||
import {
|
||||
MeasurementTable,
|
||||
Dialog,
|
||||
Input,
|
||||
useViewportGrid,
|
||||
ButtonEnums,
|
||||
} from '@ohif/ui';
|
||||
import { MeasurementTable, Dialog, Input, useViewportGrid } from '@ohif/ui';
|
||||
import ActionButtons from './ActionButtons';
|
||||
import debounce from 'lodash.debounce';
|
||||
|
||||
@@ -195,8 +189,9 @@ export default function PanelMeasurementTable({
|
||||
);
|
||||
},
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
// temp: swap button types until colors are updated
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import React from 'react';
|
||||
import { ButtonEnums, Dialog, Input, Select } from '@ohif/ui';
|
||||
import { Dialog, Input, Select } from '@ohif/ui';
|
||||
|
||||
export const CREATE_REPORT_DIALOG_RESPONSE = {
|
||||
CANCEL: 0,
|
||||
@@ -81,8 +81,8 @@ export default function createReportDialogPrompt(
|
||||
noCloseButton: true,
|
||||
onClose: _handleClose,
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
],
|
||||
// TODO: Should be on button press...
|
||||
onSubmit: _handleFormSubmit,
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function Toolbar({ servicesManager }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{toolbarButtons.map(toolDef => {
|
||||
{toolbarButtons.map((toolDef, index) => {
|
||||
const { id, Component, componentProps } = toolDef;
|
||||
// TODO: ...
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-microscopy",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF extension for DICOM microscopy",
|
||||
"author": "Bill Wallace, md-prog",
|
||||
"license": "MIT",
|
||||
@@ -28,10 +28,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/i18n": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/i18n": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
|
||||
import { Input, Dialog } from '@ohif/ui';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -14,7 +14,7 @@ export default function callInputDialog({
|
||||
uiDialogService,
|
||||
title = 'Annotation',
|
||||
defaultValue = '',
|
||||
callback = (value: string, action: string) => {},
|
||||
callback = (value: string, action: string) => {}
|
||||
}) {
|
||||
const dialogId = 'microscopy-input-dialog';
|
||||
|
||||
@@ -43,8 +43,8 @@ export default function callInputDialog({
|
||||
noCloseButton: true,
|
||||
onClose: () => uiDialogService.dismiss({ id: dialogId }),
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
body: ({ value, setValue }) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-pdf",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF extension for PDF display",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -28,8 +28,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-video",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF extension for video display",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -28,8 +28,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-measurement-tracking",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "Tracking features and functionality for basic image viewing",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -30,11 +30,11 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cornerstonejs/core": "^1.4.1",
|
||||
"@cornerstonejs/tools": "^1.4.1",
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@cornerstonejs/core": "^1.1.0",
|
||||
"@cornerstonejs/tools": "^1.1.0",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"classnames": "^2.3.2",
|
||||
"dcmjs": "^0.29.5",
|
||||
"lodash.debounce": "^4.17.21",
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"@xstate/react": "^0.8.1",
|
||||
"xstate": "^4.10.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import React from 'react';
|
||||
import { ButtonEnums, Dialog, Input } from '@ohif/ui';
|
||||
import { Dialog, Input } from '@ohif/ui';
|
||||
import RESPONSE from './PROMPT_RESPONSES';
|
||||
|
||||
export default function createReportDialogPrompt(uiDialogService) {
|
||||
@@ -20,19 +20,12 @@ export default function createReportDialogPrompt(uiDialogService) {
|
||||
* @param {string} param0.value - value from input field
|
||||
*/
|
||||
const _handleFormSubmit = ({ action, value }) => {
|
||||
uiDialogService.dismiss({ id: dialogId });
|
||||
switch (action.id) {
|
||||
case 'save':
|
||||
// Only save if description is not blank otherwise ignore
|
||||
if (value.label && value.label.trim() !== '') {
|
||||
resolve({
|
||||
action: RESPONSE.CREATE_REPORT,
|
||||
value: value.label.trim(),
|
||||
});
|
||||
uiDialogService.dismiss({ id: dialogId });
|
||||
}
|
||||
resolve({ action: RESPONSE.CREATE_REPORT, value: value.label });
|
||||
break;
|
||||
case 'cancel':
|
||||
uiDialogService.dismiss({ id: dialogId });
|
||||
resolve({ action: RESPONSE.CANCEL, value: undefined });
|
||||
break;
|
||||
}
|
||||
@@ -50,8 +43,8 @@ export default function createReportDialogPrompt(uiDialogService) {
|
||||
noCloseButton: true,
|
||||
onClose: _handleClose,
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
],
|
||||
// TODO: Should be on button press...
|
||||
onSubmit: _handleFormSubmit,
|
||||
@@ -62,8 +55,8 @@ export default function createReportDialogPrompt(uiDialogService) {
|
||||
};
|
||||
const onKeyPressHandler = event => {
|
||||
if (event.key === 'Enter') {
|
||||
// Trigger form submit
|
||||
_handleFormSubmit({ action: { id: 'save' }, value });
|
||||
uiDialogService.dismiss({ id: dialogId });
|
||||
resolve({ action: RESPONSE.CREATE_REPORT, value: value.label });
|
||||
}
|
||||
};
|
||||
return (
|
||||
|
||||
+3
-5
@@ -1,5 +1,3 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
|
||||
const RESPONSE = {
|
||||
NO_NEVER: -1,
|
||||
CANCEL: 0,
|
||||
@@ -33,19 +31,19 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
|
||||
const actions = [
|
||||
{
|
||||
id: 'prompt-begin-tracking-cancel',
|
||||
type: ButtonEnums.type.secondary,
|
||||
type: 'cancel',
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
id: 'prompt-begin-tracking-no-do-not-ask-again',
|
||||
type: ButtonEnums.type.secondary,
|
||||
type: 'secondary',
|
||||
text: 'No, do not ask again',
|
||||
value: RESPONSE.NO_NEVER,
|
||||
},
|
||||
{
|
||||
id: 'prompt-begin-tracking-yes',
|
||||
type: ButtonEnums.type.primary,
|
||||
type: 'primary',
|
||||
text: 'Yes',
|
||||
value: RESPONSE.SET_STUDY_AND_SERIES,
|
||||
},
|
||||
|
||||
+2
-3
@@ -1,5 +1,4 @@
|
||||
import { hydrateStructuredReport } from '@ohif/extension-cornerstone-dicom-sr';
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
|
||||
const RESPONSE = {
|
||||
NO_NEVER: -1,
|
||||
@@ -62,12 +61,12 @@ function _askTrackMeasurements(uiViewportDialogService, viewportIndex) {
|
||||
'Do you want to continue tracking measurements for this study?';
|
||||
const actions = [
|
||||
{
|
||||
type: ButtonEnums.type.secondary,
|
||||
type: 'secondary',
|
||||
text: 'No',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: ButtonEnums.type.primary,
|
||||
type: 'primary',
|
||||
text: 'Yes',
|
||||
value: RESPONSE.HYDRATE_REPORT,
|
||||
},
|
||||
|
||||
+3
-9
@@ -1,5 +1,3 @@
|
||||
import { ButtonEnums } from '@ohif/ui';
|
||||
|
||||
const RESPONSE = {
|
||||
NO_NEVER: -1,
|
||||
CANCEL: 0,
|
||||
@@ -40,18 +38,14 @@ function _askShouldAddMeasurements(uiViewportDialogService, viewportIndex) {
|
||||
const message =
|
||||
'Do you want to add this measurement to the existing report?';
|
||||
const actions = [
|
||||
{ type: 'cancel', text: 'Cancel', value: RESPONSE.CANCEL },
|
||||
{
|
||||
type: ButtonEnums.type.secondary,
|
||||
text: 'Cancel',
|
||||
value: RESPONSE.CANCEL,
|
||||
},
|
||||
{
|
||||
type: ButtonEnums.type.primary,
|
||||
type: 'secondary',
|
||||
text: 'Create new report',
|
||||
value: RESPONSE.CREATE_REPORT,
|
||||
},
|
||||
{
|
||||
type: ButtonEnums.type.primary,
|
||||
type: 'primary',
|
||||
text: 'Add to existing report',
|
||||
value: RESPONSE.ADD_SERIES,
|
||||
},
|
||||
|
||||
+11
-6
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button, ButtonEnums } from '@ohif/ui';
|
||||
import { Button, ButtonGroup } from '@ohif/ui';
|
||||
|
||||
function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
@@ -10,18 +10,23 @@ function ActionButtons({ onExportClick, onCreateReportClick, disabled }) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button
|
||||
className="text-base px-2 py-2"
|
||||
size="initial"
|
||||
variant={disabled ? 'disabled' : 'outlined'}
|
||||
color="black"
|
||||
border="primaryActive"
|
||||
onClick={onExportClick}
|
||||
disabled={disabled}
|
||||
type={ButtonEnums.type.secondary}
|
||||
size={ButtonEnums.size.small}
|
||||
>
|
||||
{t('Export')}
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
className="ml-2 px-2 text-base"
|
||||
variant={disabled ? 'disabled' : 'outlined'}
|
||||
size="initial"
|
||||
color="black"
|
||||
border="primaryActive"
|
||||
onClick={onCreateReportClick}
|
||||
type={ButtonEnums.type.secondary}
|
||||
size={ButtonEnums.size.small}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t('Create Report')}
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
Dialog,
|
||||
Input,
|
||||
useViewportGrid,
|
||||
ButtonEnums,
|
||||
} from '@ohif/ui';
|
||||
import { DicomMetadataStore, utils } from '@ohif/core';
|
||||
import { useDebounce } from '@hooks';
|
||||
@@ -218,8 +217,9 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
||||
);
|
||||
},
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
// temp: swap button types until colors are updated
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
},
|
||||
|
||||
+3
-11
@@ -1,5 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import PropTypes from 'prop-types';
|
||||
import { utils } from '@ohif/core';
|
||||
import {
|
||||
@@ -7,7 +6,6 @@ import {
|
||||
useImageViewer,
|
||||
useViewportGrid,
|
||||
Dialog,
|
||||
ButtonEnums,
|
||||
} from '@ohif/ui';
|
||||
import { useTrackedMeasurements } from '../../getContextModule';
|
||||
|
||||
@@ -32,8 +30,6 @@ function PanelStudyBrowserTracking({
|
||||
uiNotificationService,
|
||||
} = servicesManager.services;
|
||||
|
||||
const { t } = useTranslation('Common');
|
||||
|
||||
// Normally you nest the components so the tree isn't so deep, and the data
|
||||
// doesn't have to have such an intense shape. This works well enough for now.
|
||||
// Tabs --> Studies --> DisplaySets --> Thumbnails
|
||||
@@ -137,7 +133,7 @@ function PanelStudyBrowserTracking({
|
||||
const actuallyMappedStudies = mappedStudies.map(qidoStudy => {
|
||||
return {
|
||||
studyInstanceUid: qidoStudy.StudyInstanceUID,
|
||||
date: formatDate(qidoStudy.StudyDate) || t('NoStudyDate'),
|
||||
date: formatDate(qidoStudy.StudyDate),
|
||||
description: qidoStudy.StudyDescription,
|
||||
modalities: qidoStudy.ModalitiesInStudy,
|
||||
numInstances: qidoStudy.NumInstances,
|
||||
@@ -511,15 +507,11 @@ function _mapDisplaySets(
|
||||
</div>
|
||||
),
|
||||
actions: [
|
||||
{
|
||||
id: 'cancel',
|
||||
text: 'Cancel',
|
||||
type: ButtonEnums.type.secondary,
|
||||
},
|
||||
{ id: 'cancel', text: 'Cancel', type: 'secondary' },
|
||||
{
|
||||
id: 'yes',
|
||||
text: 'Yes',
|
||||
type: ButtonEnums.type.primary,
|
||||
type: 'primary',
|
||||
classes: ['reject-yes-button'],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -22,7 +22,7 @@ function TrackedCornerstoneViewport(props) {
|
||||
viewportOptions,
|
||||
} = props;
|
||||
|
||||
const { t } = useTranslation('Common');
|
||||
const { t } = useTranslation('TrackedViewport');
|
||||
|
||||
const {
|
||||
measurementService,
|
||||
@@ -54,7 +54,6 @@ function TrackedCornerstoneViewport(props) {
|
||||
PatientAge,
|
||||
SliceThickness,
|
||||
SpacingBetweenSlices,
|
||||
StudyDate,
|
||||
ManufacturerModelName,
|
||||
} = displaySet.images[0];
|
||||
|
||||
@@ -195,8 +194,7 @@ function TrackedCornerstoneViewport(props) {
|
||||
getStatusComponent={() => _getStatusComponent(isTracked)}
|
||||
studyData={{
|
||||
label: viewportLabel,
|
||||
studyDate:
|
||||
formatDate(SeriesDate) || formatDate(StudyDate) || t('NoStudyDate'),
|
||||
studyDate: formatDate(SeriesDate), // TODO: This is series date. Is that ok?
|
||||
currentSeries: SeriesNumber, // TODO - switch entire currentSeries to be UID based or actual position based
|
||||
seriesDescription: SeriesDescription,
|
||||
patientInformation: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-test",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF extension used inside e2e testing",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -28,8 +28,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"dcmjs": "0.29.4",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-tmtv",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF extension for Total Metabolic Tumor Volume",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -28,8 +28,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
||||
@@ -225,7 +225,9 @@ export default function PanelPetSUV({ servicesManager, commandsManager }) {
|
||||
value={metadata.SeriesTime || ''}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
<Button onClick={updateMetadata}>Reload Data</Button>
|
||||
<Button color="primary" onClick={updateMetadata}>
|
||||
Reload Data
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { LegacyButton, ButtonGroup } from '@ohif/ui';
|
||||
import { Button, ButtonGroup } from '@ohif/ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
@@ -9,9 +9,8 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
<>
|
||||
{segmentations?.length ? (
|
||||
<div className="flex justify-center mt-4 space-x-2">
|
||||
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
|
||||
<ButtonGroup color="black" size="inherit">
|
||||
<LegacyButton
|
||||
<Button
|
||||
className="px-2 py-2 text-base"
|
||||
disabled={tmtvValue === null}
|
||||
onClick={() => {
|
||||
@@ -23,10 +22,10 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
}}
|
||||
>
|
||||
{t('Export CSV')}
|
||||
</LegacyButton>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup color="black" size="inherit">
|
||||
<LegacyButton
|
||||
<Button
|
||||
className="px-2 py-2 text-base"
|
||||
onClick={() => {
|
||||
commandsManager.runCommand('createTMTVRTReport');
|
||||
@@ -34,7 +33,7 @@ function ExportReports({ segmentations, tmtvValue, config, commandsManager }) {
|
||||
disabled={tmtvValue === null}
|
||||
>
|
||||
{t('Create RT Report')}
|
||||
</LegacyButton>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
+4
-1
@@ -181,6 +181,7 @@ export default function PanelRoiThresholdSegmentation({
|
||||
<div className="overflow-x-hidden overflow-y-auto invisible-scrollbar">
|
||||
<div className="flex mx-4 my-4 mb-4 space-x-4">
|
||||
<Button
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
setLabelmapLoading(true);
|
||||
setTimeout(() => {
|
||||
@@ -193,7 +194,9 @@ export default function PanelRoiThresholdSegmentation({
|
||||
>
|
||||
{labelmapLoading ? 'loading ...' : 'New Label'}
|
||||
</Button>
|
||||
<Button onClick={handleROIThresholding}>Run</Button>
|
||||
<Button color="primary" onClick={handleROIThresholding}>
|
||||
Run
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center justify-around h-8 mb-2 border-t outline-none cursor-pointer select-none bg-secondary-dark first:border-0 border-secondary-light"
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Input, Label, Select, LegacyButton, ButtonGroup } from '@ohif/ui';
|
||||
import { Input, Label, Select, Button, ButtonGroup } from '@ohif/ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ROI_STAT = 'roi_stat';
|
||||
@@ -38,9 +38,8 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
/>
|
||||
</div>
|
||||
<div className="w-1/2">
|
||||
{/* TODO Revisit design of ButtonGroup later - for now use LegacyButton for its children.*/}
|
||||
<ButtonGroup>
|
||||
<LegacyButton
|
||||
<Button
|
||||
size="initial"
|
||||
className="px-2 py-2 text-base text-white"
|
||||
color="primaryLight"
|
||||
@@ -48,8 +47,8 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
onClick={() => runCommand('setStartSliceForROIThresholdTool')}
|
||||
>
|
||||
{t('Start')}
|
||||
</LegacyButton>
|
||||
<LegacyButton
|
||||
</Button>
|
||||
<Button
|
||||
size="initial"
|
||||
color="primaryLight"
|
||||
variant="outlined"
|
||||
@@ -57,7 +56,7 @@ function ROIThresholdConfiguration({ config, dispatch, runCommand }) {
|
||||
onClick={() => runCommand('setEndSliceForROIThresholdTool')}
|
||||
>
|
||||
{t('End')}
|
||||
</LegacyButton>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+15
-12
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Input, Dialog, ButtonEnums } from '@ohif/ui';
|
||||
import { Input, Dialog } from '@ohif/ui';
|
||||
|
||||
function segmentationItemEditHandler({ id, servicesManager }) {
|
||||
const { segmentationService, uiDialogService } = servicesManager.services;
|
||||
@@ -44,20 +44,23 @@ function segmentationItemEditHandler({ id, servicesManager }) {
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Input
|
||||
autoFocus
|
||||
className="bg-black border-primary-main"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={value.label}
|
||||
onChange={onChangeHandler}
|
||||
onKeyPress={onKeyPressHandler}
|
||||
/>
|
||||
<div className="p-4 bg-primary-dark">
|
||||
<Input
|
||||
autoFocus
|
||||
className="mt-2 bg-black border-primary-main"
|
||||
type="text"
|
||||
containerClassName="mr-2"
|
||||
value={value.label}
|
||||
onChange={onChangeHandler}
|
||||
onKeyPress={onKeyPressHandler}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
actions: [
|
||||
{ id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },
|
||||
{ id: 'save', text: 'Save', type: ButtonEnums.type.primary },
|
||||
// temp: swap button types until colors are updated
|
||||
{ id: 'cancel', text: 'Cancel', type: 'primary' },
|
||||
{ id: 'save', text: 'Save', type: 'secondary' },
|
||||
],
|
||||
onSubmit: onSubmitHandler,
|
||||
},
|
||||
|
||||
@@ -553,16 +553,7 @@ const commandsModule = ({
|
||||
commandsManager.runCommand('setViewportColormap', {
|
||||
viewportIndex,
|
||||
displaySetInstanceUID: ptDisplaySet.displaySetInstanceUID,
|
||||
colormap: {
|
||||
name: colormap,
|
||||
// TODO: This opacity mapping matches that in hpViewports, but
|
||||
// ideally making this editable in a side panel would be useful
|
||||
opacity: [
|
||||
{ value: 0, opacity: 0 },
|
||||
{ value: 0.1, opacity: 0.9 },
|
||||
{ value: 1, opacity: 0.95 },
|
||||
],
|
||||
},
|
||||
colormap,
|
||||
});
|
||||
|
||||
viewports.push(
|
||||
|
||||
@@ -254,20 +254,16 @@ const fusionAXIAL = {
|
||||
id: 'ctDisplaySet',
|
||||
},
|
||||
{
|
||||
id: 'ptDisplaySet',
|
||||
options: {
|
||||
colormap: {
|
||||
name: 'hsv',
|
||||
opacity: [
|
||||
{ value: 0, opacity: 0 },
|
||||
{ value: 0.1, opacity: 0.9 },
|
||||
{ value: 1, opacity: 0.95 },
|
||||
],
|
||||
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
|
||||
},
|
||||
voi: {
|
||||
custom: 'getPTVOIRange',
|
||||
},
|
||||
},
|
||||
id: 'ptDisplaySet',
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -314,20 +310,16 @@ const fusionSAGITTAL = {
|
||||
id: 'ctDisplaySet',
|
||||
},
|
||||
{
|
||||
id: 'ptDisplaySet',
|
||||
options: {
|
||||
colormap: {
|
||||
name: 'hsv',
|
||||
opacity: [
|
||||
{ value: 0, opacity: 0 },
|
||||
{ value: 0.1, opacity: 0.9 },
|
||||
{ value: 1, opacity: 0.95 },
|
||||
],
|
||||
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
|
||||
},
|
||||
voi: {
|
||||
custom: 'getPTVOIRange',
|
||||
},
|
||||
},
|
||||
id: 'ptDisplaySet',
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -374,20 +366,16 @@ const fusionCORONAL = {
|
||||
id: 'ctDisplaySet',
|
||||
},
|
||||
{
|
||||
id: 'ptDisplaySet',
|
||||
options: {
|
||||
colormap: {
|
||||
name: 'hsv',
|
||||
opacity: [
|
||||
{ value: 0, opacity: 0 },
|
||||
{ value: 0.1, opacity: 0.9 },
|
||||
{ value: 1, opacity: 0.95 },
|
||||
],
|
||||
opacityMapping: [{ value: 0.1, opacity: 0.9 }],
|
||||
},
|
||||
voi: {
|
||||
custom: 'getPTVOIRange',
|
||||
},
|
||||
},
|
||||
id: 'ptDisplaySet',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"packages": ["extensions/*", "platform/*", "modes/*"],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-basic-dev-mode",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "Basic OHIF Viewer Using Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -29,12 +29,12 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.27"
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/extension-dicom-pdf": "3.6.0",
|
||||
"@ohif/extension-dicom-video": "3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-test",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "Basic mode for testing",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -32,14 +32,14 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.27",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.27",
|
||||
"@ohif/extension-test": "3.7.0-beta.27"
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/extension-dicom-pdf": "3.6.0",
|
||||
"@ohif/extension-dicom-video": "3.6.0",
|
||||
"@ohif/extension-measurement-tracking": "3.6.0",
|
||||
"@ohif/extension-test": "3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-longitudinal",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "Longitudinal Workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -32,15 +32,15 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.27",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.27"
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/extension-dicom-pdf": "3.6.0",
|
||||
"@ohif/extension-dicom-video": "3.6.0",
|
||||
"@ohif/extension-measurement-tracking": "3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-microscopy",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "OHIF mode for DICOM microscopy",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -33,8 +33,8 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-microscopy": "3.7.0-beta.27"
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-dicom-microscopy": "3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/mode-tmtv",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "Total Metabolic Tumor Volume Workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -32,13 +32,13 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.27",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.27"
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/extension-dicom-pdf": "3.6.0",
|
||||
"@ohif/extension-dicom-video": "3.6.0",
|
||||
"@ohif/extension-measurement-tracking": "3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13"
|
||||
|
||||
@@ -220,8 +220,7 @@ function modeFactory({ modeConfiguration }) {
|
||||
return {
|
||||
id: ohif.layout,
|
||||
props: {
|
||||
leftPanels: [ohif.thumbnailList],
|
||||
leftPanelDefaultClosed: true,
|
||||
// leftPanels: [ohif.thumbnailList],
|
||||
rightPanels: [tmtv.ROIThresholdPanel, tmtv.petSUV],
|
||||
viewports: [
|
||||
{
|
||||
|
||||
@@ -24,8 +24,9 @@ function _createButton(type, id, icon, label, commands, tooltip) {
|
||||
|
||||
function _createColormap(label, colormap) {
|
||||
return {
|
||||
id: label,
|
||||
label,
|
||||
id: label.toString(),
|
||||
title: label,
|
||||
subtitle: label,
|
||||
type: 'action',
|
||||
commands: [
|
||||
{
|
||||
@@ -35,6 +36,13 @@ function _createColormap(label, colormap) {
|
||||
colormap,
|
||||
},
|
||||
},
|
||||
{
|
||||
commandName: 'setFusionPTColormap',
|
||||
commandOptions: {
|
||||
toolGroupId: toolGroupIds.Fusion,
|
||||
colormap,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -305,8 +313,7 @@ const toolbarButtons = [
|
||||
commandName: 'displayNotification',
|
||||
commandOptions: {
|
||||
title: 'RectangleROI Threshold Tip',
|
||||
text:
|
||||
'RectangleROI Threshold tool should be used on PT Axial Viewport',
|
||||
text: 'RectangleROI Threshold tool should be used on PT Axial Viewport',
|
||||
type: 'info',
|
||||
},
|
||||
},
|
||||
@@ -338,6 +345,7 @@ const toolbarButtons = [
|
||||
tooltip: 'PET Image Colormap',
|
||||
},
|
||||
isAction: true, // ?
|
||||
renderer: WindowLevelMenuItem,
|
||||
items: [
|
||||
_createColormap('HSV', 'hsv'),
|
||||
_createColormap('Hot Iron', 'hot_iron'),
|
||||
|
||||
@@ -149,6 +149,7 @@
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
"@cornerstonejs/core": "^1.1.0",
|
||||
"**/@babel/runtime": "^7.20.13",
|
||||
"commander": "8.3.0",
|
||||
"nth-check": "^2.1.1",
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
describe('OHIF Context Menu', function() {
|
||||
beforeEach(function() {
|
||||
describe('OHIF Context Menu', function () {
|
||||
beforeEach(function () {
|
||||
cy.checkStudyRouteInViewer(
|
||||
'1.2.840.113619.2.5.1762583153.215519.978957063.78'
|
||||
);
|
||||
@@ -10,10 +10,10 @@ describe('OHIF Context Menu', function() {
|
||||
cy.resetViewport().wait(50);
|
||||
});
|
||||
|
||||
it('checks context menu customization', function() {
|
||||
it('checks context menu customization', function () {
|
||||
// Add length measurement
|
||||
cy.addLengthMeasurement();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
||||
cy.get('[data-cy="measurement-item"]').click();
|
||||
|
||||
const [x1, y1] = [150, 100];
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ describe('OHIF Cornerstone Toolbar', () => {
|
||||
cy.addLengthMeasurement();
|
||||
cy.get('[data-cy="viewport-notification"]').should('exist');
|
||||
cy.get('[data-cy="viewport-notification"]').should('be.visible');
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
||||
|
||||
//Verify the measurement exists in the table
|
||||
cy.get('@measurementsPanel').should('be.visible');
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('OHIF Measurement Panel', function() {
|
||||
cy.addLengthMeasurement();
|
||||
cy.get('[data-cy="viewport-notification"]').should('exist');
|
||||
cy.get('[data-cy="viewport-notification"]').should('be.visible');
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
||||
cy.get('[data-cy="measurement-item"]').click();
|
||||
|
||||
cy.get('[data-cy="measurement-item"]')
|
||||
@@ -46,7 +46,7 @@ describe('OHIF Measurement Panel', function() {
|
||||
it('checks if image would jump when clicked on a measurement item', function() {
|
||||
// Add length measurement
|
||||
cy.addLengthMeasurement();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').click();
|
||||
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
||||
|
||||
cy.scrollToIndex(13);
|
||||
|
||||
|
||||
@@ -43,5 +43,3 @@
|
||||
# COMMENT: For sharedArrayBuffer, see https://developer.chrome.com/blog/enabling-shared-array-buffer/
|
||||
Cross-Origin-Embedder-Policy = "require-corp"
|
||||
Cross-Origin-Opener-Policy = "same-origin"
|
||||
# set CORP to cross-origin for anyone who wants to use the viewer in an iframe
|
||||
Cross-Origin-Resource-Policy = "cross-origin"
|
||||
+18
-18
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/app",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"productVersion": "3.4.0",
|
||||
"description": "OHIF Viewer",
|
||||
"author": "OHIF Contributors",
|
||||
@@ -51,23 +51,23 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^1.4.1",
|
||||
"@ohif/core": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.7.0-beta.27",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.27",
|
||||
"@ohif/extension-default": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-microscopy": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-pdf": "3.7.0-beta.27",
|
||||
"@ohif/extension-dicom-video": "3.7.0-beta.27",
|
||||
"@ohif/extension-test": "3.7.0-beta.27",
|
||||
"@ohif/i18n": "3.7.0-beta.27",
|
||||
"@ohif/mode-basic-dev-mode": "3.7.0-beta.27",
|
||||
"@ohif/mode-longitudinal": "3.7.0-beta.27",
|
||||
"@ohif/mode-microscopy": "3.7.0-beta.27",
|
||||
"@ohif/mode-test": "3.7.0-beta.27",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@cornerstonejs/dicom-image-loader": "^0.6.8",
|
||||
"@ohif/core": "3.6.0",
|
||||
"@ohif/extension-cornerstone": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-rt": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-seg": "3.6.0",
|
||||
"@ohif/extension-cornerstone-dicom-sr": "3.6.0",
|
||||
"@ohif/extension-default": "3.6.0",
|
||||
"@ohif/extension-dicom-microscopy": "3.6.0",
|
||||
"@ohif/extension-dicom-pdf": "3.6.0",
|
||||
"@ohif/extension-dicom-video": "3.6.0",
|
||||
"@ohif/extension-test": "3.6.0",
|
||||
"@ohif/i18n": "3.6.0",
|
||||
"@ohif/mode-basic-dev-mode": "3.6.0",
|
||||
"@ohif/mode-longitudinal": "3.6.0",
|
||||
"@ohif/mode-microscopy": "3.6.0",
|
||||
"@ohif/mode-test": "3.6.0",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"@types/react": "^17.0.38",
|
||||
"classnames": "^2.3.2",
|
||||
"core-js": "^3.16.1",
|
||||
|
||||
@@ -4,7 +4,7 @@ window.config = {
|
||||
modes: [],
|
||||
showStudyList: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -30,7 +30,6 @@ window.config = {
|
||||
supportsFuzzyMatching: false,
|
||||
supportsWildcard: false,
|
||||
staticWado: true,
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@ window.config = {
|
||||
// some windows systems have issues with more than 3 web workers
|
||||
maxNumberOfWebWorkers: 3,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -50,6 +51,7 @@ window.config = {
|
||||
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
|
||||
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
|
||||
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
|
||||
|
||||
qidoSupportsIncludeField: false,
|
||||
supportsReject: false,
|
||||
imageRendering: 'wadors',
|
||||
@@ -66,7 +68,6 @@ window.config = {
|
||||
enabled: true,
|
||||
relativeResolution: 'studies',
|
||||
},
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ window.config = {
|
||||
extensions: [],
|
||||
showStudyList: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
strictZSpacingForVolumeViewport: true,
|
||||
showCPUFallbackMessage: true,
|
||||
@@ -24,7 +25,6 @@ window.config = {
|
||||
bulkDataURI: {
|
||||
enabled: false,
|
||||
},
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,6 +4,7 @@ window.config = {
|
||||
modes: [],
|
||||
showStudyList: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -27,7 +28,6 @@ window.config = {
|
||||
enableStudyLazyLoad: true,
|
||||
supportsFuzzyMatching: false,
|
||||
supportsWildcard: false,
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ window.config = {
|
||||
showStudyList: true,
|
||||
maxNumberOfWebWorkers: 3,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -30,7 +31,6 @@ window.config = {
|
||||
supportsWildcard: true,
|
||||
staticWado: true,
|
||||
singlepart: 'bulkdata,video,pdf',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ window.config = {
|
||||
extensions: [],
|
||||
modes: [],
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -22,7 +23,6 @@ window.config = {
|
||||
qidoSupportsIncludeField: false,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ window.config = {
|
||||
routerBasename: '/',
|
||||
showStudyList: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -17,7 +18,6 @@ window.config = {
|
||||
qidoSupportsIncludeField: false,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
// REQUIRED TAG:
|
||||
// TODO: Remove tag after https://github.com/OHIF/ohif-core/pull/19 is merged and we bump version
|
||||
// requestOptions: {
|
||||
|
||||
@@ -4,7 +4,7 @@ window.config = {
|
||||
extensions: [],
|
||||
modes: [],
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -23,7 +23,6 @@ window.config = {
|
||||
qidoSupportsIncludeField: false,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ window.config = {
|
||||
modes: ['@ohif/mode-test'],
|
||||
showStudyList: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
maxNumberOfWebWorkers: 3,
|
||||
showWarningMessageForCrossOrigin: false,
|
||||
showCPUFallbackMessage: false,
|
||||
@@ -30,7 +31,6 @@ window.config = {
|
||||
supportsFuzzyMatching: false,
|
||||
supportsWildcard: true,
|
||||
singlepart: 'video,thumbnail,pdf',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ window.config = {
|
||||
},
|
||||
enableGoogleCloudAdapter: false,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -54,7 +55,6 @@ window.config = {
|
||||
supportsFuzzyMatching: true,
|
||||
supportsWildcard: false,
|
||||
dicomUploadEnabled: true,
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ window.config = {
|
||||
routerBasename: '/',
|
||||
enableGoogleCloudAdapter: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
|
||||
@@ -8,6 +8,7 @@ window.config = {
|
||||
extensions: [],
|
||||
modes: [],
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -38,7 +39,6 @@ window.config = {
|
||||
bulkDataURI: {
|
||||
enabled: true,
|
||||
},
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ window.config = {
|
||||
showStudyList: true,
|
||||
maxNumberOfWebWorkers: 4,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -32,7 +33,6 @@ window.config = {
|
||||
supportsWildcard: true,
|
||||
staticWado: true,
|
||||
singlepart: 'bulkdata,video,pdf',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ window.config = {
|
||||
showStudyList: true,
|
||||
maxNumberOfWebWorkers: 4,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -41,7 +42,6 @@ window.config = {
|
||||
supportsWildcard: true,
|
||||
staticWado: true,
|
||||
singlepart: 'bulkdata,video,pdf',
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ window.config = {
|
||||
modes: [],
|
||||
showStudyList: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -37,7 +38,6 @@ window.config = {
|
||||
enabled: true,
|
||||
relativeResolution: 'studies',
|
||||
},
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ window.config = {
|
||||
routerBasename: '/',
|
||||
showStudyList: true,
|
||||
// below flag is for performance reasons, but it might not work for all servers
|
||||
omitQuotationForMultipartRequest: true,
|
||||
showWarningMessageForCrossOrigin: true,
|
||||
showCPUFallbackMessage: true,
|
||||
showLoadingIndicator: true,
|
||||
@@ -17,7 +18,6 @@ window.config = {
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
supportsFuzzyMatching: true,
|
||||
omitQuotationForMultipartRequest: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -15,7 +15,7 @@ import { utils, hotkeys, ServicesManager } from '@ohif/core';
|
||||
import {
|
||||
Icon,
|
||||
StudyListExpandedRow,
|
||||
LegacyButton,
|
||||
Button,
|
||||
EmptyStudies,
|
||||
StudyListTable,
|
||||
StudyListPagination,
|
||||
@@ -363,17 +363,16 @@ function WorkList({
|
||||
''}?${query.toString()}`}
|
||||
// to={`${mode.routeName}/dicomweb?StudyInstanceUIDs=${studyInstanceUid}`}
|
||||
>
|
||||
{/* TODO revisit the completely rounded style of buttons used for launching a mode from the worklist later - for now use LegacyButton*/}
|
||||
<LegacyButton
|
||||
<Button
|
||||
rounded="full"
|
||||
variant={isValidMode ? 'contained' : 'disabled'}
|
||||
disabled={!isValidMode}
|
||||
endIcon={<Icon name="launch-arrow" />} // launch-arrow | launch-info
|
||||
className={classnames({ 'ml-2': !isFirst })}
|
||||
className={classnames('font-medium ', { 'ml-2': !isFirst })}
|
||||
onClick={() => {}}
|
||||
>
|
||||
{t(`Modes:${mode.displayName}`)}
|
||||
</LegacyButton>
|
||||
</Button>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -74,16 +74,9 @@ module.exports = {
|
||||
},
|
||||
|
||||
customblue: {
|
||||
10: '#0A163F',
|
||||
20: '#0B1F54',
|
||||
30: '#09286e',
|
||||
40: '#0E307F',
|
||||
50: '#0F3A94',
|
||||
80: '#1454D4',
|
||||
100: '#c4fdff',
|
||||
200: '#38daff',
|
||||
300: '#1D204D',
|
||||
400: '#90A0C1',
|
||||
},
|
||||
|
||||
customgray: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/cli",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "A CLI to bootstrap new OHIF extension or mode",
|
||||
"type": "module",
|
||||
"main": "src/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/core",
|
||||
"version": "3.7.0-beta.27",
|
||||
"version": "3.6.0",
|
||||
"description": "Generic business logic for web-based medical imaging applications",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -35,8 +35,8 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^1.4.1",
|
||||
"@ohif/ui": "3.7.0-beta.27",
|
||||
"@cornerstonejs/dicom-image-loader": "^0.6.8",
|
||||
"@ohif/ui": "3.6.0",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"dicom-parser": "^1.8.21"
|
||||
},
|
||||
|
||||
@@ -173,31 +173,30 @@ const bindings = [
|
||||
label: 'W/L Preset 5',
|
||||
keys: ['5'],
|
||||
},
|
||||
// These don't exist, so don't try applying them....
|
||||
// {
|
||||
// commandName: 'setWindowLevel',
|
||||
// commandOptions: windowLevelPresets[6],
|
||||
// label: 'W/L Preset 6',
|
||||
// keys: ['6'],
|
||||
// },
|
||||
// {
|
||||
// commandName: 'setWindowLevel',
|
||||
// commandOptions: windowLevelPresets[7],
|
||||
// label: 'W/L Preset 7',
|
||||
// keys: ['7'],
|
||||
// },
|
||||
// {
|
||||
// commandName: 'setWindowLevel',
|
||||
// commandOptions: windowLevelPresets[8],
|
||||
// label: 'W/L Preset 8',
|
||||
// keys: ['8'],
|
||||
// },
|
||||
// {
|
||||
// commandName: 'setWindowLevel',
|
||||
// commandOptions: windowLevelPresets[9],
|
||||
// label: 'W/L Preset 9',
|
||||
// keys: ['9'],
|
||||
// },
|
||||
{
|
||||
commandName: 'setWindowLevel',
|
||||
commandOptions: windowLevelPresets[6],
|
||||
label: 'W/L Preset 6',
|
||||
keys: ['6'],
|
||||
},
|
||||
{
|
||||
commandName: 'setWindowLevel',
|
||||
commandOptions: windowLevelPresets[7],
|
||||
label: 'W/L Preset 7',
|
||||
keys: ['7'],
|
||||
},
|
||||
{
|
||||
commandName: 'setWindowLevel',
|
||||
commandOptions: windowLevelPresets[8],
|
||||
label: 'W/L Preset 8',
|
||||
keys: ['8'],
|
||||
},
|
||||
{
|
||||
commandName: 'setWindowLevel',
|
||||
commandOptions: windowLevelPresets[9],
|
||||
label: 'W/L Preset 9',
|
||||
keys: ['9'],
|
||||
},
|
||||
];
|
||||
|
||||
export default bindings;
|
||||
@@ -695,18 +695,15 @@ export default class HangingProtocolService extends PubSubService {
|
||||
) {
|
||||
viewport.displaySets.forEach(displaySet => {
|
||||
const { id } = displaySet;
|
||||
const displaySetMatchDetail = displaySetMatchDetails.get(id);
|
||||
const {
|
||||
displaySetInstanceUID: oldDisplaySetInstanceUID,
|
||||
} = displaySetMatchDetails.get(id);
|
||||
|
||||
const { displaySetInstanceUID: oldDisplaySetInstanceUID } = displaySetMatchDetail;
|
||||
|
||||
const displaySetInstanceUID =
|
||||
displaySetInstanceUIDs.push(
|
||||
displaySet.id === displaySetSelectorId
|
||||
? newDisplaySetInstanceUID
|
||||
: oldDisplaySetInstanceUID;
|
||||
|
||||
displaySetMatchDetail.displaySetInstanceUID = displaySetInstanceUID;
|
||||
|
||||
displaySetInstanceUIDs.push(displaySetInstanceUID);
|
||||
: oldDisplaySetInstanceUID
|
||||
);
|
||||
displaySetOptions.push(displaySet);
|
||||
});
|
||||
}
|
||||
@@ -1392,20 +1389,17 @@ export default class HangingProtocolService extends PubSubService {
|
||||
this.studies.forEach(study => {
|
||||
// Skip non-active if active only
|
||||
if (matchActiveOnly && this.activeStudy !== study) return;
|
||||
|
||||
const studyDisplaySets = this.displaySets.filter(
|
||||
it => it.StudyInstanceUID === study.StudyInstanceUID
|
||||
it => it.StudyInstanceUID === study.StudyInstanceUID
|
||||
);
|
||||
|
||||
const studyMatchDetails = this.protocolEngine.findMatch(
|
||||
study,
|
||||
studyMatchingRules,
|
||||
{
|
||||
studies: this.studies,
|
||||
displaySets: studyDisplaySets,
|
||||
allDisplaySets: this.displaySets,
|
||||
displaySetMatchDetails: this.displaySetMatchDetails,
|
||||
}
|
||||
study,
|
||||
studyMatchingRules,
|
||||
{
|
||||
studies: this.studies,
|
||||
displaySets: studyDisplaySets,
|
||||
displaySetMatchDetails: this.displaySetMatchDetails,
|
||||
}
|
||||
);
|
||||
|
||||
// Prevent bestMatch from being updated if the matchDetails' required attribute check has failed
|
||||
@@ -1414,10 +1408,10 @@ export default class HangingProtocolService extends PubSubService {
|
||||
}
|
||||
|
||||
this.debug(
|
||||
'study',
|
||||
study.StudyInstanceUID,
|
||||
'display sets #',
|
||||
studyDisplaySets.length
|
||||
'study',
|
||||
study.StudyInstanceUID,
|
||||
'display sets #',
|
||||
studyDisplaySets.length
|
||||
);
|
||||
studyDisplaySets.forEach(displaySet => {
|
||||
const {
|
||||
@@ -1426,15 +1420,15 @@ export default class HangingProtocolService extends PubSubService {
|
||||
displaySetInstanceUID,
|
||||
} = displaySet;
|
||||
const seriesMatchDetails = this.protocolEngine.findMatch(
|
||||
displaySet,
|
||||
seriesMatchingRules,
|
||||
// Todo: why we have images here since the matching type does not have it
|
||||
{
|
||||
studies: this.studies,
|
||||
instance: displaySet.images?.[0],
|
||||
displaySetMatchDetails: this.displaySetMatchDetails,
|
||||
displaySets: studyDisplaySets,
|
||||
}
|
||||
displaySet,
|
||||
seriesMatchingRules,
|
||||
// Todo: why we have images here since the matching type does not have it
|
||||
{
|
||||
studies: this.studies,
|
||||
instance: displaySet.images?.[0],
|
||||
displaySetMatchDetails: this.displaySetMatchDetails,
|
||||
displaySets: studyDisplaySets,
|
||||
}
|
||||
);
|
||||
|
||||
// Prevent bestMatch from being updated if the matchDetails' required attribute check has failed
|
||||
|
||||
@@ -1,240 +1,69 @@
|
||||
import validate from 'validate.js';
|
||||
/**
|
||||
* check if the value is strictly equal to options
|
||||
*
|
||||
* @example
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'abc' (Fail)
|
||||
* = ['abc'] (Fail)
|
||||
* = ['abc', 'def', 'GHI'] (Valid)
|
||||
* = ['abc', 'GHI', 'def'] (Fail)
|
||||
* = ['abc', 'def'] (Fail)
|
||||
*
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = 'Attenuation Corrected' (Valid)
|
||||
* testValue = 'Attenuation' (Fail)
|
||||
*
|
||||
* value = ['Attenuation Corrected']
|
||||
* testValue = ['Attenuation Corrected'] (Valid)
|
||||
* = 'Attenuation Corrected' (Valid)
|
||||
* = 'Attenuation' (Fail)
|
||||
*
|
||||
* */
|
||||
validate.validators.equals = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
const dicomArrayValue = dicomTagToArray(value);
|
||||
|
||||
// If options is an array, then we need to validate each element in the array
|
||||
if (Array.isArray(testValue)) {
|
||||
// If the array has only one element, then we need to compare the value to that element
|
||||
if (testValue.length !== dicomArrayValue.length) {
|
||||
return `${key} must be an array of length ${testValue.length}`;
|
||||
} else {
|
||||
for (let i = 0; i < testValue.length; i++) {
|
||||
if (testValue[i] !== dicomArrayValue[i]) {
|
||||
return `${key} ${testValue[i]} must equal ${dicomArrayValue[i]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (testValue !== dicomArrayValue[0]) {
|
||||
return `${key} must equal ${testValue}`;
|
||||
validate.validators.equals = function(value, options, key, attributes) {
|
||||
const testValue = options?.value ?? options;
|
||||
if (value !== testValue) {
|
||||
return key + 'must equal ' + testValue;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* check if the value is not equal to options
|
||||
*
|
||||
* @example
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'abc' (Valid)
|
||||
* = ['abc'] (Valid)
|
||||
* = ['abc', 'def', 'GHI'] (Fail)
|
||||
* = ['abc', 'GHI', 'def'] (Valid)
|
||||
* = ['abc', 'def'] (Valid)
|
||||
*
|
||||
* value = 'Attenuation Corrected'
|
||||
* = 'Attenuation Corrected' (Fail)
|
||||
* = 'Attenuation' (Valid)
|
||||
*
|
||||
* value = ['Attenuation Corrected']
|
||||
* testValue = ['Attenuation Corrected'] (Fail)
|
||||
* = 'Attenuation Corrected' (Fail)
|
||||
* = 'Attenuation' (Fail)
|
||||
* */
|
||||
|
||||
validate.validators.doesNotEqual = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
const dicomArrayValue = dicomTagToArray(value);
|
||||
|
||||
if (Array.isArray(testValue)) {
|
||||
if (testValue.length === dicomArrayValue.length) {
|
||||
let score = 0;
|
||||
testValue.forEach((x, i) => {
|
||||
if (x === dicomArrayValue[i]) {
|
||||
score++;
|
||||
}
|
||||
});
|
||||
if (score === testValue.length) {
|
||||
return `${key} must not equal to ${testValue}`;
|
||||
}
|
||||
}
|
||||
} else if (testValue === dicomArrayValue[0]) {
|
||||
console.debug(dicomArrayValue, testValue);
|
||||
return `${key} must not equal to ${testValue}`;
|
||||
const testValue = options?.value ?? options;
|
||||
if (value === testValue) {
|
||||
return key + 'cannot equal ' + testValue;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a value includes one or more specified options.
|
||||
*
|
||||
* @example
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = ‘abc’ (Fail)
|
||||
* = ‘dog’ (Fail)
|
||||
* = [‘abc’] (Valid)
|
||||
* = [‘att’, ‘abc’] (Valid)
|
||||
* = ['abc', 'def', 'dog'] (Valid)
|
||||
* = ['cat', 'dog'] (Fail)
|
||||
*
|
||||
* value = ['Attenuation Corrected']
|
||||
* testValue = 'Attenuation Corrected' (Fail)
|
||||
* = ['Attenuation Corrected', 'Corrected'] (Valid)
|
||||
* = ['Attenuation', 'Corrected'] (Fail)
|
||||
*
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ['Attenuation Corrected', 'Corrected'] (Valid)
|
||||
* = ['Attenuation', 'Corrected'] (Fail)
|
||||
* */
|
||||
validate.validators.includes = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
const dicomArrayValue = dicomTagToArray(value);
|
||||
|
||||
if (Array.isArray(testValue)) {
|
||||
const includedValues = testValue.filter(el => dicomArrayValue.includes(el));
|
||||
if (includedValues.length === 0) {
|
||||
return `${key} must include at least one of the following values: ${testValue.join(
|
||||
', '
|
||||
)}`;
|
||||
}
|
||||
} else return `${key} ${testValue} must be an array`;
|
||||
// else if (!value.includes(testValue)) {
|
||||
// return `${key} ${value} must include ${testValue}`;
|
||||
// }
|
||||
};
|
||||
/**
|
||||
* Check if a value does not include one or more specified options.
|
||||
*
|
||||
* @example
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = ['Corr'] (Valid)
|
||||
* = 'abc' (Fail)
|
||||
* = ['abc'] (Fail)
|
||||
* = [‘att’, ‘cor’] (Valid)
|
||||
* = ['abc', 'def', 'dog'] (Fail)
|
||||
*
|
||||
* value = ['Attenuation Corrected']
|
||||
* testValue = 'Attenuation Corrected' (Fail)
|
||||
* = ['Attenuation Corrected', 'Corrected'] (Fail)
|
||||
* = ['Attenuation', 'Corrected'] (Valid)
|
||||
*
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ['Attenuation Corrected', 'Corrected'] (Fail)
|
||||
* = ['Attenuation', 'Corrected'] (Valid)
|
||||
* */
|
||||
validate.validators.doesNotInclude = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
const dicomArrayValue = dicomTagToArray(value);
|
||||
|
||||
// if (!Array.isArray(value) || value.length === 1) {
|
||||
// return `${key} is not allowed as a single value`;
|
||||
// }
|
||||
if (Array.isArray(testValue)) {
|
||||
const includedValues = testValue.filter(el => dicomArrayValue.includes(el));
|
||||
if (includedValues.length > 0) {
|
||||
return `${key} must not include the following value: ${includedValues}`;
|
||||
}
|
||||
} else return `${key} ${testValue} must be an array`;
|
||||
};
|
||||
// Ignore case contains.
|
||||
// options testValue MUST be in lower case already, otherwise it won't match
|
||||
/**
|
||||
* @example
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ‘Corr’ (Valid)
|
||||
* = ‘corr’ (Valid)
|
||||
* = [‘att’, ‘cor’] (Valid)
|
||||
* = [‘Att’, ‘Wall’] (Valid)
|
||||
* = [‘cat’, ‘dog’] (Fail)
|
||||
*
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'def' (Valid)
|
||||
* = 'dog' (Fail)
|
||||
* = ['gh', 'de'] (Valid)
|
||||
* = ['cat', 'dog'] (Fail)
|
||||
*
|
||||
* */
|
||||
validate.validators.containsI = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
validate.validators.containsI = function (value, options, key) {
|
||||
const testValue = options?.value ?? options;
|
||||
if (Array.isArray(value)) {
|
||||
if (
|
||||
value.some(
|
||||
item => !validate.validators.containsI(item.toLowerCase(), options, key)
|
||||
)
|
||||
value.some(
|
||||
item => !validate.validators.containsI(item.toLowerCase(), options, key)
|
||||
)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return `No item of ${value.join(',')} contains ${JSON.stringify(
|
||||
testValue
|
||||
testValue
|
||||
)}`;
|
||||
}
|
||||
if (Array.isArray(testValue)) {
|
||||
if (
|
||||
testValue.some(
|
||||
subTest =>
|
||||
!validate.validators.containsI(value, subTest.toLowerCase(), key)
|
||||
)
|
||||
testValue.some(
|
||||
subTest => !validate.validators.containsI(value, subTest, key)
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return `${key} must contain at least one of ${testValue.join(',')}`;
|
||||
}
|
||||
if (
|
||||
testValue &&
|
||||
value.indexOf &&
|
||||
value.toLowerCase().indexOf(testValue.toLowerCase()) === -1
|
||||
testValue &&
|
||||
value.indexOf &&
|
||||
value.toLowerCase().indexOf(testValue) === -1
|
||||
) {
|
||||
return key + 'must contain any case of' + testValue;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @example
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ‘Corr’ (Valid)
|
||||
* = ‘corr’ (Fail)
|
||||
* = [‘att’, ‘cor’] (Fail)
|
||||
* = [‘Att’, ‘Wall’] (Valid)
|
||||
* = [‘cat’, ‘dog’] (Fail)
|
||||
*
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'def' (Valid)
|
||||
* = 'dog' (Fail)
|
||||
* = ['cat', 'de'] (Valid)
|
||||
* = ['cat', 'dog'] (Fail)
|
||||
*
|
||||
* */
|
||||
|
||||
validate.validators.contains = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
const testValue = options?.value ?? options;
|
||||
if (Array.isArray(value)) {
|
||||
if (value.some(item => !validate.validators.contains(item, options, key))) {
|
||||
return undefined;
|
||||
}
|
||||
return `No item of ${value.join(',')} contains ${JSON.stringify(
|
||||
testValue
|
||||
testValue
|
||||
)}`;
|
||||
}
|
||||
if (Array.isArray(testValue)) {
|
||||
if (
|
||||
testValue.some(
|
||||
subTest => !validate.validators.contains(value, subTest, key)
|
||||
)
|
||||
testValue.some(
|
||||
subTest => !validate.validators.contains(value, subTest, key)
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -244,235 +73,50 @@ validate.validators.contains = function(value, options, key) {
|
||||
return key + 'must contain ' + testValue;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @example
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ‘Corr’ (Fail)
|
||||
* = ‘corr’ (Valid)
|
||||
* = [‘att’, ‘cor’] (Valid)
|
||||
* = [‘Att’, ‘Wall’] (Fail)
|
||||
* = [‘cat’, ‘dog’] (Valid)
|
||||
*
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'def' (Fail)
|
||||
* = 'dog' (Valid)
|
||||
* = ['cat', 'de'] (Fail)
|
||||
* = ['cat', 'dog'] (Valid)
|
||||
*
|
||||
* */
|
||||
|
||||
validate.validators.doesNotContain = function(value, options, key) {
|
||||
const containsResult = validate.validators.contains(value, options, key);
|
||||
if (!containsResult) {
|
||||
return `No item of ${value} should contain ${getTestValue(options)}`;
|
||||
if (options && value.indexOf && value.indexOf(options.value) !== -1) {
|
||||
return key + 'cannot contain ' + options.value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @example
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ‘Corr’ (Fail)
|
||||
* = ‘corr’ (Fail)
|
||||
* = [‘att’, ‘cor’] (Fail)
|
||||
* = [‘Att’, ‘Wall’] (Fail)
|
||||
* = [‘cat’, ‘dog’] (Valid)
|
||||
*
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'DEF' (Fail)
|
||||
* = 'dog' (Valid)
|
||||
* = ['cat', 'gh'] (Fail)
|
||||
* = ['cat', 'dog'] (Valid)
|
||||
*
|
||||
* */
|
||||
validate.validators.doesNotContainI = function(value, options, key) {
|
||||
const containsResult = validate.validators.containsI(value, options, key);
|
||||
if (!containsResult) {
|
||||
return `No item of ${value} should not contain ${getTestValue(options)}`;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @example
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ‘Corr’ (Fail)
|
||||
* = ‘Att’ (Fail)
|
||||
* = ['cat', 'dog', 'Att'] (Valid)
|
||||
* = [‘cat’, ‘dog’] (Fail)
|
||||
*
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'deg' (Valid)
|
||||
* = ['cat', 'GH'] (Valid)
|
||||
* = ['cat', 'gh'] (Fail)
|
||||
* = ['cat', 'dog'] (Fail)
|
||||
*
|
||||
* */
|
||||
validate.validators.startsWith = function(value, options, key) {
|
||||
let testValues = getTestValue(options);
|
||||
|
||||
if (typeof testValues === 'string') {
|
||||
testValues = [testValues];
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (!testValues.some(testValue => value.startsWith(testValue))) {
|
||||
return key + ' must start with any of these values: ' + testValues;
|
||||
}
|
||||
} else if (Array.isArray(value)) {
|
||||
let valid = false;
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
for (let j = 0; j < testValues.length; j++) {
|
||||
if (value[i].startsWith(testValues[j])) {
|
||||
valid = true; // set valid flag to true if a match is found
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
return undefined; // break out of loop if a match is found
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
return key + ' must start with any of these values: ' + testValues; // return undefined if no match is found
|
||||
}
|
||||
} else {
|
||||
return 'Value must be a string or an array';
|
||||
if (options && value.startsWith && !value.startsWith(options.value)) {
|
||||
return key + 'must start with ' + options.value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @example
|
||||
* value = 'Attenuation Corrected'
|
||||
* testValue = ‘TED’ (Fail)
|
||||
* = ‘ted’ (Valid)
|
||||
* = ['cat', 'dog', 'ted'] (Valid)
|
||||
* = [‘cat’, ‘dog’] (Fail)
|
||||
*
|
||||
* value = ['abc', 'def', 'GHI']
|
||||
* testValue = 'deg' (Valid)
|
||||
* = ['cat', 'HI'] (Valid)
|
||||
* = ['cat', 'hi'] (Fail)
|
||||
* = ['cat', 'dog'] (Fail)
|
||||
*
|
||||
* */
|
||||
validate.validators.endsWith = function(value, options, key) {
|
||||
let testValues = getTestValue(options);
|
||||
|
||||
if (typeof testValues === 'string') {
|
||||
testValues = [testValues];
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (!testValues.some(testValue => value.endsWith(testValue))) {
|
||||
return key + ' must end with any of these values: ' + testValues;
|
||||
}
|
||||
} else if (Array.isArray(value)) {
|
||||
let valid = false;
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
for (let j = 0; j < testValues.length; j++) {
|
||||
if (value[i].endsWith(testValues[j])) {
|
||||
valid = true; // set valid flag to true if a match is found
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
return undefined; // break out of loop if a match is found
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
return key + ' must end with any of these values: ' + testValues; // return undefined if no match is found
|
||||
}
|
||||
} else {
|
||||
return key + ' must be a string or an array';
|
||||
if (options && value.endsWith && !value.endsWith(options.value)) {
|
||||
return key + 'must end with ' + options.value;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @example
|
||||
* value = 30
|
||||
* testValue = 20 (Valid)
|
||||
* = 40 (Fail)
|
||||
*
|
||||
* */
|
||||
|
||||
const getTestValue = options => options?.value ?? options;
|
||||
|
||||
validate.validators.greaterThan = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
if (Array.isArray(value) || typeof value === 'string') {
|
||||
return `${key} is not allowed as an array or string`;
|
||||
}
|
||||
if (Array.isArray(testValue)) {
|
||||
if (testValue.length === 1) {
|
||||
if (!(value >= testValue[0])) {
|
||||
return `${key} must be greater than or equal to ${testValue[0]}, but was ${value}`;
|
||||
}
|
||||
} else if (testValue.length > 1) {
|
||||
return key + ' must be an array of length 1';
|
||||
}
|
||||
} else {
|
||||
if (!(value >= testValue)) {
|
||||
return key + ' must be greater than ' + testValue;
|
||||
}
|
||||
if (value === undefined || value === null || value <= testValue) {
|
||||
return key + 'with value ' + value + ' must be greater than ' + testValue;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @example
|
||||
* value = 30
|
||||
* testValue = 40 (Valid)
|
||||
* = 20 (Fail)
|
||||
*
|
||||
* */
|
||||
validate.validators.lessThan = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
if (Array.isArray(testValue)) {
|
||||
if (testValue.length === 1) {
|
||||
if (!(value <= testValue[0])) {
|
||||
return `${key} must be less than or equal to ${testValue[0]}, but was ${value}`;
|
||||
}
|
||||
} else if (testValue.length > 1) {
|
||||
return key + ' must be an array of length 1';
|
||||
}
|
||||
} else {
|
||||
if (!(value <= testValue)) {
|
||||
return key + ' must be less than ' + testValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @example
|
||||
|
||||
*
|
||||
* value = 50
|
||||
* testValue = [10,60] (Valid)
|
||||
* = [60, 10] (Valid)
|
||||
* = [0, 10] (Fail)
|
||||
* = [70, 80] (Fail)
|
||||
* = 45 (Fail)
|
||||
* = [45] (Fail)
|
||||
*
|
||||
* */
|
||||
validate.validators.range = function(value, options, key) {
|
||||
const testValue = getTestValue(options);
|
||||
if (Array.isArray(testValue) && testValue.length === 2) {
|
||||
const min = Math.min(testValue[0], testValue[1]);
|
||||
const max = Math.max(testValue[0], testValue[1]);
|
||||
if (value === undefined || value < min || value > max) {
|
||||
return `${key} with value ${value} must be between ${min} and ${max}`;
|
||||
}
|
||||
} else return `${key} must be an array of length 2`;
|
||||
if (value === undefined || value < testValue[0] || value > testValue[1]) {
|
||||
return (
|
||||
key +
|
||||
'with value ' +
|
||||
value +
|
||||
' must be between ' +
|
||||
testValue[0] +
|
||||
' and ' +
|
||||
testValue[1]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
validate.validators.notNull = value =>
|
||||
value === null || value === undefined ? 'Value is null' : undefined;
|
||||
const getTestValue = options => {
|
||||
if (Array.isArray(options)) {
|
||||
return options.map(option => option?.value ?? option);
|
||||
} else {
|
||||
return options?.value ?? options;
|
||||
}
|
||||
};
|
||||
const dicomTagToArray = value => {
|
||||
let dicomArrayValue;
|
||||
if (!Array.isArray(value)) {
|
||||
dicomArrayValue = [value];
|
||||
} else {
|
||||
dicomArrayValue = [...value];
|
||||
}
|
||||
return dicomArrayValue;
|
||||
};
|
||||
value === null || value === undefined ? 'Value is null' : undefined;
|
||||
|
||||
export default validate;
|
||||
@@ -1,570 +1,139 @@
|
||||
import validate from './validator.js';
|
||||
|
||||
describe('validator', () => {
|
||||
const attributeMap = {
|
||||
str: 'Attenuation Corrected',
|
||||
upper: 'UPPER',
|
||||
num: 3,
|
||||
nullValue: null,
|
||||
list: ['abc', 'def', 'GHI'],
|
||||
listStr: ['Attenuation Corrected'],
|
||||
};
|
||||
const attributeMap = {
|
||||
str: 'string',
|
||||
upper: 'UPPER',
|
||||
num: 3,
|
||||
nullValue: null,
|
||||
list: ['abc', 'def', 'GHI'],
|
||||
};
|
||||
|
||||
const options = {
|
||||
format: 'grouped',
|
||||
};
|
||||
const options = {
|
||||
format: 'grouped',
|
||||
};
|
||||
|
||||
describe('equals', () => {
|
||||
it('returned undefined on strictly equals', () => {
|
||||
expect(
|
||||
validate(attributeMap, { listStr: { equals: ['Attenuation'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { listStr: { equals: 'Attenuation' } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { equals: 'Attenuation Corrected' } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { equals: ['Attenuation Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { equals: 'Attenuation Corrected' } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
describe('contains', () => {
|
||||
it('returns match any list contains', () => {
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: 'a' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { contains: 'i' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { contains: ['i'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: ['a'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: ['z', 'd'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: ['z'] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ str: { equals: { value: 'Attenuation Corrected' } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { equals: ['Attenuation Corrected'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { equals: ['Attenuation'] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { equals: ['abc', 'def', 'GHI'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { equals: ['abc', 'GHI', 'def'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ list: { equals: { value: ['abc', 'def', 'GHI'] } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
});
|
||||
describe('containsI', () => {
|
||||
it('returns match any list contains case insensitive', () => {
|
||||
expect(
|
||||
validate(attributeMap, { upper: { containsI: ['bye', 'pre'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: 'hi' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: ['hi', 'bye'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: ['bye', 'hi'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: ['ig', 'hi'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { upper: { containsI: ['bye', 'per'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
});
|
||||
describe('doesNotEqual', () => {
|
||||
it('returns undefined if value does not equal ', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { doesNotEqual: 'Attenuation Corrected' } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { doesNotEqual: ['Attenuation Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { listStr: { doesNotEqual: 'Attenuation' } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotEqual: 'Attenuation' } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ str: { doesNotEqual: { value: 'Attenuation' } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotEqual: ['Attenuation'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotEqual: ['abc', 'def'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ list: { doesNotEqual: ['abc', 'GHI', 'def'] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ list: { doesNotEqual: ['abc', 'def', 'GHI'] } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('includes', () => {
|
||||
it('returns match any list includes', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { includes: 'Attenuation Corrected' } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { includes: ['Attenuation Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { includes: ['Attenuation Corrected', 'Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { includes: ['Attenuation', 'Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ str: { includes: ['Attenuation Corrected', 'Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ str: { includes: ['Attenuation', 'Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { includes: ['abc'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { includes: ['GHI', 'HI'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { includes: ['HI', 'bye'] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('doesNotInclude', () => {
|
||||
it('returns undefined if list does not includes', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { doesNotInclude: 'Attenuation Corrected' } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{
|
||||
listStr: { doesNotInclude: ['Attenuation Corrected', 'Corrected'] },
|
||||
},
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ listStr: { doesNotInclude: ['Attenuation', 'Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ str: { doesNotInclude: ['Attenuation Corrected', 'Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ str: { doesNotInclude: ['Attenuation', 'Corrected'] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { doesNotInclude: ['Corr'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { doesNotInclude: 'abc' } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ list: { doesNotInclude: { value: ['abc'] } } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ list: { doesNotInclude: { value: ['att', 'cor'] } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ list: { doesNotInclude: { value: ['abc', 'def', 'dog'] } } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('containsI', () => {
|
||||
it('returns match any list contains case insensitive', () => {
|
||||
expect(
|
||||
validate(attributeMap, { upper: { containsI: ['hi', 'pre'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: 'hi' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: ['ghi', 'bye'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: ['bye', 'hi'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { containsI: ['ig', 'hi'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { upper: { containsI: ['bye', 'per'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('contains', () => {
|
||||
it('returns match any list contains', () => {
|
||||
expect(
|
||||
validate(attributeMap, { str: { contains: 'Corr' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { contains: { value: 'Corr' } } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { contains: ['Corr'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { contains: ['corr'] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { contains: ['Att', 'Wall'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: 'GH' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: ['ab'] } }, [options])
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: ['z', 'bc'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { contains: ['z'] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
describe('equals', () => {
|
||||
it('returned undefined on equals', () => {
|
||||
expect(
|
||||
validate(attributeMap, { str: { equals: attributeMap.str } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { equals: { value: attributeMap.num } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('doesNotContain', () => {
|
||||
it('returns undefined if string does not contain specified value', () => {
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContain: ['att', 'wall'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContain: 'Corr' } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContain: 'corr' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContain: { value: 'corr' } } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContain: ['att', 'cor'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContain: ['Att', 'cor'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContain: ['bye', 'hi'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { doesNotContain: ['GHI', 'hi'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { doesNotContain: ['hi'] } }, [options])
|
||||
).toBeUndefined();
|
||||
});
|
||||
it('returns error on not equals', () => {
|
||||
expect(
|
||||
validate(attributeMap, { str: { equals: 'abc' } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { equals: { value: 1 + attributeMap.num } } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
describe('doesNotContainI', () => {
|
||||
it('returns undefined if string does not contain specified value', () => {
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContainI: 'corr' } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContainI: 'Corr' } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContainI: ['att', 'cor'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContainI: ['Att', 'wall'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { doesNotContainI: ['bye', 'hi'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { doesNotContainI: ['bye', 'ABC'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { doesNotContainI: 'bye' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { doesNotContainI: ['bye', 'ABC'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('startsWith', () => {
|
||||
it('returns undefined if string starts with specified value', () => {
|
||||
expect(
|
||||
validate(attributeMap, { str: { startsWith: { value: 'Atte' } } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { startsWith: 'Att' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { startsWith: ['cat', 'dog', 'Att'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { startsWith: ['cat', 'dog'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { startsWith: ['GH'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { startsWith: ['de', 'bye'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { startsWith: ['hi', 'bye'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('endsWith', () => {
|
||||
it('returns undefined if string ends with specified value', () => {
|
||||
expect(
|
||||
validate(attributeMap, { str: { endsWith: 'ted' } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { endsWith: { value: 'ted' } } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { endsWith: ['ted'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { endsWith: ['Att'] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { str: { endsWith: ['cat', 'dog', 'ted'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { endsWith: ['HI'] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { endsWith: ['bc', 'dog', 'ted'] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { list: { endsWith: ['bye', 'dog'] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('greaterThan', () => {
|
||||
it('returns undefined on greaterThan', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { greaterThan: { value: attributeMap.num - 1 } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { greaterThan: attributeMap.num - 1 } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('greaterThan', () => {
|
||||
it('returns undefined on greaterThan', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { greaterThan: { value: attributeMap.num - 1 } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { greaterThan: attributeMap.num - 1 } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { greaterThan: [attributeMap.num - 1] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { greaterThan: [attributeMap.num + 1] } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
it('returns error on not greater than', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { greaterThan: { value: attributeMap.num } } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { greaterThan: attributeMap.num } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
describe('lessThan', () => {
|
||||
it('returns undefined on lessThan', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { lessThan: { value: attributeMap.num + 1 } } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { lessThan: attributeMap.num + 1 } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { lessThan: [attributeMap.num + 1] } }, [
|
||||
options,
|
||||
])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { lessThan: [attributeMap.num - 1] } }, [
|
||||
options,
|
||||
])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
describe('range', () => {
|
||||
it('returns undefined if the value is between', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ num: { range: [attributeMap.num + 1, attributeMap.num - 1] } },
|
||||
[options]
|
||||
)
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { range: [1, 4] } }, [options])
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { range: [1, 2] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { range: [4, 5] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { range: [5] } }, [options])
|
||||
).not.toBeUndefined();
|
||||
expect(
|
||||
validate(attributeMap, { num: { range: 5 } }, [options])
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns error on undefined value', () => {
|
||||
expect(
|
||||
validate(
|
||||
attributeMap,
|
||||
{ numUndefined: { greaterThan: { value: 3 } } },
|
||||
[options]
|
||||
)
|
||||
).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -14,23 +14,23 @@ import {
|
||||
* The interface for the services object
|
||||
*/
|
||||
export default interface Services {
|
||||
userAuthenticationService?: Record<string, unknown>;
|
||||
hangingProtocolService?: HangingProtocolService;
|
||||
customizationService?: CustomizationService;
|
||||
measurementService?: MeasurementService;
|
||||
displaySetService?: DisplaySetService;
|
||||
cineService?: Record<string, unknown>;
|
||||
toolbarService?: ToolbarService;
|
||||
viewportGridService?: ViewportGridService;
|
||||
uiModalService?: UIModalService;
|
||||
cornerstoneViewportService?: Record<string, unknown>;
|
||||
uiDialogService?: Record<string, unknown>;
|
||||
toolGroupService?: Record<string, unknown>;
|
||||
uiNotificationService?: UINotificationService;
|
||||
uiModalService?: UIModalService;
|
||||
uiViewportDialogService?: Record<string, unknown>;
|
||||
viewportGridService?: ViewportGridService;
|
||||
syncGroupService?: Record<string, unknown>;
|
||||
cornerstoneCacheService?: Record<string, unknown>;
|
||||
segmentationService?: Record<string, unknown>;
|
||||
stateSyncService?: StateSyncService;
|
||||
cineService?: unknown;
|
||||
userAuthenticationService?: unknown;
|
||||
cornerstoneViewportService?: unknown;
|
||||
uiDialogService?: unknown;
|
||||
toolGroupService?: unknown;
|
||||
uiViewportDialogService?: unknown;
|
||||
syncGroupService?: unknown;
|
||||
cornerstoneCacheService?: unknown;
|
||||
segmentationService?: unknown;
|
||||
panelService?: unknown;
|
||||
panelService?: Record<string, unknown>;
|
||||
}
|
||||
Loaded 100 of 574 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user