Merge branch 'v3-stable' into customizable-TS

This commit is contained in:
Salim Kanoun authored and GitHub committed 2023-05-29 23:26:36 +02:00
commit 56633a67d9
59 files changed
+1039 -409

No files matched your search

+1 -1
View File
@@ -32,7 +32,7 @@
},
"peerDependencies": {
"cornerstone-math": "0.1.9",
"@cornerstonejs/dicom-image-loader": "^0.6.6",
"@cornerstonejs/dicom-image-loader": "^0.6.8",
"@cornerstonejs/codec-charls": "^1.2.3",
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
+18 -12
View File
@@ -76,18 +76,24 @@ const bindings = [
keys: ['left'],
isEditable: true,
},
// {
// commandName: 'nextViewportDisplaySet',
// label: 'Next Series',
// keys: ['pageup'],
// isEditable: true,
// },
// {
// commandName: 'previousViewportDisplaySet',
// label: 'Previous Series',
// keys: ['pagedown'],
// isEditable: true,
// },
{
commandName: 'updateViewportDisplaySet',
commandOptions: {
direction: -1,
},
label: 'Previous Series',
keys: ['pageup'],
isEditable: true,
},
{
commandName: 'updateViewportDisplaySet',
commandOptions: {
direction: 1,
},
label: 'Next Series',
keys: ['pagedown'],
isEditable: true,
},
{
commandName: 'nextStage',
context: 'DEFAULT',
@@ -1033,6 +1033,23 @@ export default class HangingProtocolService extends PubSubService {
return this._matchViewport(useViewport, options);
}
/**
* Gets a sort function that is consistent with the display set sorting performed
* to match display sets to viewports.
* @returns a display set sort function
*/
public getDisplaySetSortFunction(): (
displaySetA: IDisplaySet,
displaySetB: IDisplaySet
) => number {
return (displaySetA, displaySetB) => {
const seriesA = this._getSeriesSortInfoForDisplaySetSort(displaySetA);
const seriesB = this._getSeriesSortInfoForDisplaySetSort(displaySetB);
return sortBy(this._getSeriesFieldForDisplaySetSort())(seriesA, seriesB);
};
}
/**
* Updates the viewports with the selected protocol stage.
*/
@@ -1461,7 +1478,7 @@ export default class HangingProtocolService extends PubSubService {
sortingInfo: {
score: totalMatchScore,
study: study.StudyInstanceUID,
series: parseInt(displaySet.SeriesNumber),
...this._getSeriesSortInfoForDisplaySetSort(displaySet),
},
};
@@ -1484,9 +1501,7 @@ export default class HangingProtocolService extends PubSubService {
name: 'study',
reverse: true,
},
{
name: 'series',
}
this._getSeriesFieldForDisplaySetSort()
);
matchingScores.sort((a, b) =>
sortingFunction(a.sortingInfo, b.sortingInfo)
@@ -1506,6 +1521,19 @@ export default class HangingProtocolService extends PubSubService {
};
}
private _getSeriesSortInfoForDisplaySetSort(displaySet) {
return {
[this._getSeriesFieldForDisplaySetSort().name]:
displaySet.SeriesNumber != null
? parseInt(displaySet.SeriesNumber)
: parseInt(displaySet.seriesNumber),
};
}
private _getSeriesFieldForDisplaySetSort() {
return { name: 'series' };
}
/**
* Check if the next stage is available
* @return {Boolean} True if next stage is available or false otherwise
@@ -179,6 +179,24 @@ See the [`singlepart`](#singlepart) data source configuration option.
### DICOM Video
See the [`singlepart`](#singlepart) data source configuration option.
### BulkDataURI
The `bulkDataURI` configuration option allows the datasource to use the
bulkdata end points for retrieving metadata if originally was not included in the
response from the server. This is useful for the metadata information that
are big and can/should be retrieved in a separate request. In case the bulkData URI
is relative (instead of absolute) the `relativeResolution` option can be used to
specify the resolution of the relative URI. The possible values are `studies`, `series` and `instances`.
Certainly the knowledge of how the server is configured is required to use this option.
```js
bulkDataURI: {
enabled: true,
relativeResolution: 'series',
},
```
### Running DCM4CHEE
dcm4che is a collection of open source applications for healthcare enterprise
+7
View File
@@ -209,6 +209,13 @@ see [custom routes](./platform/services/ui/customization-service.md#customroutes
</details>
## DICOM Endpoints
In OHIF v3 there is a new end point that your DICOM server should be able to respond to
`WADO-RS GET studies/{studyInstanceUid}/series`
This is used in the viewer for fetching the series list for a study to use for the hanging protocol.
## LifeCycle Hooks
OHIF v2 had `preRegistration` hook for extensions for initialization. In OHIF v3 you have
@@ -490,7 +490,7 @@ are specific to the context used for where the menu is displayed.
The default cornerstone context menu can be customized by setting the
`cornerstoneContextMenu`. For a full example, see `findingsContextMenu`.
## Customizeable Cornerstone Viewport Click Behaviour
## Customizable Cornerstone Viewport Click Behaviour
The behaviour on clicking on the cornerstone viewport can be customized
by setting the `cornerstoneViewportClickCommands`. This is intended to
+1
View File
@@ -47,6 +47,7 @@
"react-outside-click-handler": "^1.3.0",
"react-select": "3.0.8",
"react-with-direction": "^1.3.1",
"react-window": "^1.8.9",
"swiper": "^8.4.2",
"webpack": "^5.81.0"
},
@@ -0,0 +1,8 @@
<svg width="19" height="19" viewBox="0 0 19 19" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<circle fill="#0944B3" cx="9.5" cy="9.5" r="9.5"/>
<g stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="m5.188 5.187 8.625 8.625M13.813 5.187l-8.625 8.625"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 377 B

@@ -0,0 +1,9 @@
<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h18v18H0z"/>
<g transform="translate(1 1)" stroke="#348CFD" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5">
<circle cx="5.565" cy="5.565" r="5.565"/>
<path d="M9.5 9.5 16 16"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 402 B

@@ -53,12 +53,14 @@ import checkboxUnchecked from './../../assets/icons/checkbox-unchecked.svg';
import iconAlertOutline from './../../assets/icons/icons-alert-outline.svg';
import iconAlertSmall from './../../assets/icons/icon-alert-small.svg';
import iconClose from './../../assets/icons/icon-close.svg';
import iconClearField from './../../assets/icons/icon-clear-field.svg';
import iconNextInactive from './../../assets/icons/icon-next-inactive.svg';
import iconNext from './../../assets/icons/icon-next.svg';
import iconPlay from './../../assets/icons/icon-play.svg';
import iconPause from './../../assets/icons/icon-pause.svg';
import iconPrevInactive from './../../assets/icons/icon-prev-inactive.svg';
import iconPrev from './../../assets/icons/icon-prev.svg';
import iconSearch from './../../assets/icons/icon-search.svg';
import iconStatusAlert from './../../assets/icons/icon-status-alert.svg';
import iconTransferring from './../../assets/icons/icon-transferring.svg';
import iconUpload from './../../assets/icons/icon-upload.svg';
@@ -151,9 +153,11 @@ const ICONS = {
info: info,
'icon-alert-outline': iconAlertOutline,
'icon-alert-small': iconAlertSmall,
'icon-clear-field': iconClearField,
'icon-close': iconClose,
'icon-play': iconPlay,
'icon-pause': iconPause,
'icon-search': iconSearch,
'icon-status-alert': iconStatusAlert,
'icon-transferring': iconTransferring,
'info-action': infoAction,
@@ -5,8 +5,8 @@ input[type='range'] {
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
height: 10px;
width: 10px;
height: 13px;
width: 13px;
border-radius: 50%;
background: #5acce6;
}
@@ -14,8 +14,8 @@ input[type='range']::-webkit-slider-thumb {
input[type='range']::-moz-range-thumb {
-webkit-appearance: none;
border: none;
height: 10px;
width: 10px;
height: 13px;
width: 13px;
border-radius: 50%;
background: #5acce6;
}
@@ -23,7 +23,9 @@ const InputRange: React.FC<{
inputClassName?: string;
labelClassName?: string;
labelVariant?: string;
showLabel: boolean;
showLabel?: boolean;
labelPosition?: string;
trackColor?: string;
}> = ({
value,
onChange,
@@ -36,6 +38,8 @@ const InputRange: React.FC<{
labelClassName,
labelVariant,
showLabel = true,
labelPosition = '',
trackColor,
}) => {
const [rangeValue, setRangeValue] = useState(value);
@@ -63,6 +67,16 @@ const InputRange: React.FC<{
containerClassName ? containerClassName : ''
}`}
>
{showLabel && labelPosition === 'left' && (
<Typography
variant={labelVariant ?? 'subtitle'}
component="p"
className={classNames('w-8', labelClassName ?? 'text-white')}
>
{rangeValueForStr}
{unit}
</Typography>
)}
<input
type="range"
min={minValue}
@@ -72,14 +86,16 @@ const InputRange: React.FC<{
inputClassName ? inputClassName : ''
}`}
style={{
background: `linear-gradient(to right, #5acce6 0%, #5acce6 ${rangeValuePercentage -
10}%, #3a3f99 ${rangeValuePercentage + 10}%, #3a3f99 100%)`,
background:
trackColor ||
`linear-gradient(to right, #5acce6 0%, #5acce6 ${rangeValuePercentage -
10}%, #3a3f99 ${rangeValuePercentage + 10}%, #3a3f99 100%)`,
}}
onChange={handleChange}
id="myRange"
step={step}
/>
{showLabel && (
{showLabel && (!labelPosition || labelPosition === 'right') && (
<Typography
variant={labelVariant ?? 'subtitle'}
component="p"
@@ -19,7 +19,7 @@ function LoadingIndicatorProgress({ className, textBlock, progress }) {
>
<Icon name="loading-ohif-mark" className="text-white w-12 h-12" />
<div className="w-48">
<ProgressLoadingBar></ProgressLoadingBar>
<ProgressLoadingBar progress={progress} />
</div>
{textBlock}
</div>
@@ -63,6 +63,7 @@ const Thumbnail = ({
src={imageSrc}
alt={imageAltText}
className="object-none min-h-32"
crossOrigin="anonymous"
/>
) : (
<div>{imageAltText}</div>
@@ -12,7 +12,10 @@ const ThumbnailList = ({
activeDisplaySetInstanceUIDs = [],
}) => {
return (
<div className="py-3 bg-black overflow-y-hidden ohif-scrollbar study-min-height">
<div
id="ohif-thumbnail-list"
className="py-3 bg-black overflow-y-hidden ohif-scrollbar study-min-height"
>
{thumbnails.map(
({
displaySetInstanceUID,
+1 -1
View File
@@ -39,7 +39,7 @@ module.exports = {
main: '#3a3f99',
disabled: '#2b166b',
focus: '#5acce6',
placeholder: '#39383f'
placeholder: '#39383f',
},
secondary: {
+1 -2
View File
@@ -65,10 +65,9 @@
"@ohif/ui": "^2.0.0",
"@types/react": "^17.0.38",
"classnames": "^2.3.2",
"config-point": "^0.4.8",
"core-js": "^3.16.1",
"cornerstone-math": "^0.1.9",
"@cornerstonejs/dicom-image-loader": "^0.6.6",
"@cornerstonejs/dicom-image-loader": "^0.6.8",
"@cornerstonejs/codec-charls": "^1.2.3",
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
+11 -6
View File
@@ -48,9 +48,9 @@ window.config = {
// wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
// new server
wadoUriRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
qidoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
@@ -60,9 +60,14 @@ window.config = {
supportsFuzzyMatching: false,
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,video,pdf',
useBulkDataURI: false,
//requestTransferSyntaxUID: '1.2.840.10008.1.2.4.80'
singlepart: 'bulkdata,video',
// whether the data source should use retrieveBulkData to grab metadata,
// and in case of relative path, what would it be relative to, options
// are in the series level or study level (some servers like series some study)
bulkDataURI: {
enabled: true,
relativeResolution: 'studies',
},
},
},
{
+6 -4
View File
@@ -16,13 +16,15 @@ window.config = {
sourceName: 'dicomweb',
configuration: {
name: 'DCM4CHEE',
wadoUriRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
qidoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoSupportsIncludeField: true,
imageRendering: 'wadors',
enableStudyLazyLoad: true,
useBulkDataURI: false,
bulkDataURI: {
enabled: false,
},
},
},
],
+3 -3
View File
@@ -64,9 +64,9 @@ window.config = {
// qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
// wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
// new server
wadoUriRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
qidoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
@@ -33,6 +33,12 @@ window.config = {
},
dicomUploadEnabled: true,
singlepart: 'pdf,video',
// whether the data source should use retrieveBulkData to grab metadata,
// and in case of relative path, what would it be relative to, options
// are in the series level or study level (some servers like series some study)
bulkDataURI: {
enabled: true,
},
},
},
{
@@ -29,10 +29,12 @@ window.config = {
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
useBulkDataURI: false,
supportsFuzzyMatching: true,
supportsWildcard: true,
dicomUploadEnabled: true,
bulkDataURI: {
enabled: false,
},
},
},
{
+3 -3
View File
@@ -55,9 +55,9 @@ window.config = {
// qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
// wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
// new server
wadoUriRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
qidoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
+12 -4
View File
@@ -18,9 +18,10 @@ window.config = {
sourceName: 'dicomweb',
configuration: {
name: 'aws',
wadoUriRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
qidoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
@@ -29,7 +30,14 @@ window.config = {
supportsFuzzyMatching: false,
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,video,pdf',
singlepart: 'bulkdata,video',
// whether the data source should use retrieveBulkData to grab metadata,
// and in case of relative path, what would it be relative to, options
// are in the series level or study level (some servers like series some study)
bulkDataURI: {
enabled: true,
relativeResolution: 'studies',
},
},
},
{
@@ -11,9 +11,9 @@ window.config = {
dicomWeb: [
{
name: 'aws',
wadoUriRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
qidoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
wadoUriRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
wadoRoot: 'https://d33do7qe4w26qo.cloudfront.net/dicomweb',
qidoSupportsIncludeField: true,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
@@ -343,6 +343,7 @@ function WorkList({
const isValidMode = mode.isValidMode({
modalities: modalitiesToCheck,
study,
});
// TODO: Modes need a default/target route? We mostly support a single one for now.
// We should also be using the route path, but currently are not
+1 -1
View File
@@ -50,7 +50,7 @@ module.exports = {
main: '#3a3f99',
disabled: '#2b166b',
focus: '#5acce6',
placeholder: '#39383f'
placeholder: '#39383f',
},
secondary: {