Merge branch 'feat/v2-main' into feat/OHIF-177
This commit is contained in:
commit
0264e5998d
@ -33,7 +33,7 @@
|
|||||||
"@ohif/ui": "^0.50.0",
|
"@ohif/ui": "^0.50.0",
|
||||||
"cornerstone-core": "^2.3.0",
|
"cornerstone-core": "^2.3.0",
|
||||||
"cornerstone-math": "^0.1.8",
|
"cornerstone-math": "^0.1.8",
|
||||||
"cornerstone-tools": "4.15.1",
|
"cornerstone-tools": "4.16.0",
|
||||||
"dcmjs": "0.14.0",
|
"dcmjs": "0.14.0",
|
||||||
"cornerstone-wado-image-loader": "^3.1.2",
|
"cornerstone-wado-image-loader": "^3.1.2",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
|
|||||||
@ -2,33 +2,32 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { ToolbarButton } from '@ohif/ui';
|
import { ToolbarButton } from '@ohif/ui';
|
||||||
|
|
||||||
function NestedMenu({ children }) {
|
function NestedMenu({ children, label, icon, isActive }) {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
const toggleNestedMenu = () => setIsOpen(!isOpen);
|
||||||
function closeNestedMenu() {
|
|
||||||
if (isOpen) {
|
const closeNestedMenu = () => {
|
||||||
setIsOpen(false);
|
if (isOpen) {
|
||||||
}
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
window.addEventListener('click', closeNestedMenu);
|
window.addEventListener('click', closeNestedMenu);
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('click', closeNestedMenu);
|
window.removeEventListener('click', closeNestedMenu);
|
||||||
};
|
};
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
const dropdownContent = isOpen ? children : undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
id="More"
|
id="NestedMenu"
|
||||||
label="More"
|
label={label}
|
||||||
icon="tool-more-menu"
|
icon={icon}
|
||||||
onClick={() => {
|
onClick={toggleNestedMenu}
|
||||||
setIsOpen(!isOpen);
|
dropdownContent={isOpen && children}
|
||||||
}}
|
isActive={isActive || isOpen}
|
||||||
dropdownContent={dropdownContent}
|
|
||||||
isActive={isOpen}
|
|
||||||
type="primary"
|
type="primary"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -36,6 +35,13 @@ function NestedMenu({ children }) {
|
|||||||
|
|
||||||
NestedMenu.propTypes = {
|
NestedMenu.propTypes = {
|
||||||
children: PropTypes.any.isRequired,
|
children: PropTypes.any.isRequired,
|
||||||
|
icon: PropTypes.string,
|
||||||
|
label: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
NestedMenu.defaultProps = {
|
||||||
|
icon: "tool-more-menu",
|
||||||
|
label: "More",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NestedMenu;
|
export default NestedMenu;
|
||||||
|
|||||||
@ -55,7 +55,20 @@ function ViewerLayout({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultTool = { icon: 'tool-more-menu', label: 'More', isActive: false };
|
||||||
const [toolbars, setToolbars] = useState({ primary: [], secondary: [] });
|
const [toolbars, setToolbars] = useState({ primary: [], secondary: [] });
|
||||||
|
const [activeTool, setActiveTool] = useState(defaultTool);
|
||||||
|
|
||||||
|
const setActiveToolHandler = (tool, isNested) => {
|
||||||
|
setActiveTool(isNested ? tool : defaultTool);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPrimaryClickHandler = (evt, btn) => {
|
||||||
|
if (btn.props && btn.props.commands && evt.value && btn.props.commands[evt.value]) {
|
||||||
|
const { commandName, commandOptions } = btn.props.commands[evt.value];
|
||||||
|
commandsManager.runCommand(commandName, commandOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { unsubscribe } = ToolBarService.subscribe(
|
const { unsubscribe } = ToolBarService.subscribe(
|
||||||
@ -63,8 +76,8 @@ function ViewerLayout({
|
|||||||
() => {
|
() => {
|
||||||
console.warn('~~~ TOOL BAR MODIFIED EVENT CAUGHT');
|
console.warn('~~~ TOOL BAR MODIFIED EVENT CAUGHT');
|
||||||
const updatedToolbars = {
|
const updatedToolbars = {
|
||||||
primary: ToolBarService.getButtonSection('primary'),
|
primary: ToolBarService.getButtonSection('primary', { onClick: onPrimaryClickHandler, setActiveTool: setActiveToolHandler }),
|
||||||
secondary: ToolBarService.getButtonSection('secondary'),
|
secondary: ToolBarService.getButtonSection('secondary', { setActiveTool: setActiveToolHandler }),
|
||||||
};
|
};
|
||||||
setToolbars(updatedToolbars);
|
setToolbars(updatedToolbars);
|
||||||
}
|
}
|
||||||
@ -86,11 +99,10 @@ function ViewerLayout({
|
|||||||
|
|
||||||
if (!isNested) {
|
if (!isNested) {
|
||||||
const { id, Component, componentProps } = toolDef;
|
const { id, Component, componentProps } = toolDef;
|
||||||
|
|
||||||
return <Component key={id} id={id} {...componentProps} />;
|
return <Component key={id} id={id} {...componentProps} />;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<NestedMenu>
|
<NestedMenu isActive={activeTool.isActive} icon={activeTool.icon} label={activeTool.label}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{toolDef.map(x => {
|
{toolDef.map(x => {
|
||||||
const { id, Component, componentProps } = x;
|
const { id, Component, componentProps } = x;
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
{
|
{
|
||||||
name: 'ohif.divider',
|
name: 'ohif.divider',
|
||||||
defaultComponent: ToolbarDivider,
|
defaultComponent: ToolbarDivider,
|
||||||
clickHandler: () => {},
|
clickHandler: () => { },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'ohif.action',
|
name: 'ohif.action',
|
||||||
@ -30,7 +30,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
optionalConfig: [],
|
optionalConfig: [],
|
||||||
requiredProps: [],
|
requiredProps: [],
|
||||||
optionalProps: [],
|
optionalProps: [],
|
||||||
clickHandler: (evt, clickedBtn, btnSectionName) => {
|
clickHandler: (evt, clickedBtn, btnSectionName, metadata, viewerProps) => {
|
||||||
const { props } = clickedBtn;
|
const { props } = clickedBtn;
|
||||||
const allButtons = toolbarService.getButtons();
|
const allButtons = toolbarService.getButtons();
|
||||||
|
|
||||||
@ -47,6 +47,10 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
clickedBtn.config.groupName === btn.config.groupName
|
clickedBtn.config.groupName === btn.config.groupName
|
||||||
) {
|
) {
|
||||||
btn.props.isActive = false;
|
btn.props.isActive = false;
|
||||||
|
|
||||||
|
if (viewerProps.setActiveTool) {
|
||||||
|
viewerProps.setActiveTool(props, metadata.isNested);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -63,7 +67,7 @@ export default function getToolbarModule({ commandsManager, servicesManager }) {
|
|||||||
{
|
{
|
||||||
name: 'ohif.layoutSelector',
|
name: 'ohif.layoutSelector',
|
||||||
defaultComponent: ToolbarLayoutSelector,
|
defaultComponent: ToolbarLayoutSelector,
|
||||||
clickHandler: (evt, clickedBtn, btnSectionName) => {},
|
clickHandler: (evt, clickedBtn, btnSectionName) => { },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'ohif.toggle',
|
name: 'ohif.toggle',
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ohif/core": "^0.50.0",
|
"@ohif/core": "^0.50.0",
|
||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-tools": "4.15.1",
|
"cornerstone-tools": "4.16.0",
|
||||||
"dcmjs": "0.14.0",
|
"dcmjs": "0.14.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
"@ohif/ui": "^0.50.0",
|
"@ohif/ui": "^0.50.0",
|
||||||
"cornerstone-core": "^2.3.0",
|
"cornerstone-core": "^2.3.0",
|
||||||
"cornerstone-math": "^0.1.8",
|
"cornerstone-math": "^0.1.8",
|
||||||
"cornerstone-tools": "4.15.1",
|
"cornerstone-tools": "4.16.0",
|
||||||
"dcmjs": "0.14.0",
|
"dcmjs": "0.14.0",
|
||||||
"cornerstone-wado-image-loader": "^3.1.2",
|
"cornerstone-wado-image-loader": "^3.1.2",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import cornerstone from 'cornerstone-core';
|
import cornerstone from 'cornerstone-core';
|
||||||
|
import cornerstoneTools from 'cornerstone-tools';
|
||||||
import CornerstoneViewport from 'react-cornerstone-viewport';
|
import CornerstoneViewport from 'react-cornerstone-viewport';
|
||||||
import OHIF, { DicomMetadataStore } from '@ohif/core';
|
import OHIF, { DicomMetadataStore } from '@ohif/core';
|
||||||
import {
|
import {
|
||||||
@ -13,6 +14,18 @@ import debounce from 'lodash.debounce';
|
|||||||
import throttle from 'lodash.throttle';
|
import throttle from 'lodash.throttle';
|
||||||
import { useTrackedMeasurements } from './../getContextModule';
|
import { useTrackedMeasurements } from './../getContextModule';
|
||||||
|
|
||||||
|
// TODO -> Get this list from the list of tracked measurements.
|
||||||
|
const {
|
||||||
|
ArrowAnnotateTool,
|
||||||
|
BidirectionalTool,
|
||||||
|
EllipticalRoiTool,
|
||||||
|
LengthTool,
|
||||||
|
} = cornerstoneTools;
|
||||||
|
|
||||||
|
const BaseAnnotationTool = cornerstoneTools.importInternal(
|
||||||
|
'base/BaseAnnotationTool'
|
||||||
|
);
|
||||||
|
|
||||||
// const cine = viewportSpecificData.cine;
|
// const cine = viewportSpecificData.cine;
|
||||||
|
|
||||||
// isPlaying = cine.isPlaying === true;
|
// isPlaying = cine.isPlaying === true;
|
||||||
@ -27,6 +40,7 @@ function TrackedCornerstoneViewport({
|
|||||||
viewportIndex,
|
viewportIndex,
|
||||||
}) {
|
}) {
|
||||||
const [trackedMeasurements] = useTrackedMeasurements();
|
const [trackedMeasurements] = useTrackedMeasurements();
|
||||||
|
|
||||||
const [
|
const [
|
||||||
{ activeViewportIndex, viewports },
|
{ activeViewportIndex, viewports },
|
||||||
dispatchViewportGrid,
|
dispatchViewportGrid,
|
||||||
@ -34,6 +48,8 @@ function TrackedCornerstoneViewport({
|
|||||||
// viewportIndex, onSubmit
|
// viewportIndex, onSubmit
|
||||||
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
|
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
|
||||||
const [viewportData, setViewportData] = useState(null);
|
const [viewportData, setViewportData] = useState(null);
|
||||||
|
const [element, setElement] = useState(null);
|
||||||
|
const [isTracked, setIsTracked] = useState(false);
|
||||||
// TODO: Still needed? Better way than import `OHIF` and destructure?
|
// TODO: Still needed? Better way than import `OHIF` and destructure?
|
||||||
// Why is this managed by `core`?
|
// Why is this managed by `core`?
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -42,6 +58,75 @@ function TrackedCornerstoneViewport({
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const allTools = cornerstoneTools.store.state.tools;
|
||||||
|
const toolsForElement = allTools.filter(tool => tool.element === element);
|
||||||
|
|
||||||
|
toolsForElement.forEach(tool => {
|
||||||
|
if (
|
||||||
|
tool instanceof ArrowAnnotateTool ||
|
||||||
|
tool instanceof BidirectionalTool ||
|
||||||
|
tool instanceof EllipticalRoiTool ||
|
||||||
|
tool instanceof LengthTool
|
||||||
|
) {
|
||||||
|
const configuration = tool.configuration;
|
||||||
|
|
||||||
|
configuration.renderDashed = !isTracked;
|
||||||
|
|
||||||
|
tool.configuration = configuration;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const enabledElement = cornerstone.getEnabledElement(element);
|
||||||
|
|
||||||
|
if (enabledElement.image) {
|
||||||
|
cornerstone.updateImage(element);
|
||||||
|
}
|
||||||
|
}, [isTracked]);
|
||||||
|
|
||||||
|
const onElementEnabled = evt => {
|
||||||
|
const eventData = evt.detail;
|
||||||
|
const targetElement = eventData.element;
|
||||||
|
|
||||||
|
const allTools = cornerstoneTools.store.state.tools;
|
||||||
|
|
||||||
|
const toolsForElement = allTools.filter(
|
||||||
|
tool => tool.element === targetElement
|
||||||
|
);
|
||||||
|
|
||||||
|
toolsForElement.forEach(tool => {
|
||||||
|
if (
|
||||||
|
tool instanceof ArrowAnnotateTool ||
|
||||||
|
tool instanceof BidirectionalTool ||
|
||||||
|
tool instanceof EllipticalRoiTool ||
|
||||||
|
tool instanceof LengthTool
|
||||||
|
) {
|
||||||
|
const configuration = tool.configuration;
|
||||||
|
|
||||||
|
configuration.renderDashed = !isTracked;
|
||||||
|
|
||||||
|
tool.configuration = configuration;
|
||||||
|
} else if (tool instanceof BaseAnnotationTool) {
|
||||||
|
const configuration = tool.configuration;
|
||||||
|
|
||||||
|
configuration.renderDashed = true;
|
||||||
|
|
||||||
|
tool.configuration = configuration;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const enabledElement = cornerstone.getEnabledElement(targetElement);
|
||||||
|
|
||||||
|
if (enabledElement.image) {
|
||||||
|
cornerstone.updateImage(targetElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
setElement(targetElement);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const {
|
const {
|
||||||
StudyInstanceUID,
|
StudyInstanceUID,
|
||||||
@ -116,6 +201,7 @@ function TrackedCornerstoneViewport({
|
|||||||
vp => vp.displaySetInstanceUID === displaySet.displaySetInstanceUID
|
vp => vp.displaySetInstanceUID === displaySet.displaySetInstanceUID
|
||||||
);
|
);
|
||||||
const { trackedSeries } = trackedMeasurements.context;
|
const { trackedSeries } = trackedMeasurements.context;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Modality,
|
Modality,
|
||||||
SeriesDate,
|
SeriesDate,
|
||||||
@ -131,6 +217,11 @@ function TrackedCornerstoneViewport({
|
|||||||
SliceThickness,
|
SliceThickness,
|
||||||
} = displaySet.images[0];
|
} = displaySet.images[0];
|
||||||
|
|
||||||
|
|
||||||
|
if (trackedSeries.includes(SeriesInstanceUID) !== isTracked) {
|
||||||
|
setIsTracked(!isTracked);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewportActionBar
|
<ViewportActionBar
|
||||||
@ -159,6 +250,7 @@ function TrackedCornerstoneViewport({
|
|||||||
{/* TODO: Viewport interface to accept stack or layers of content like this? */}
|
{/* TODO: Viewport interface to accept stack or layers of content like this? */}
|
||||||
<div className="relative flex flex-row w-full h-full">
|
<div className="relative flex flex-row w-full h-full">
|
||||||
<CornerstoneViewport
|
<CornerstoneViewport
|
||||||
|
onElementEnabled={onElementEnabled}
|
||||||
viewportIndex={viewportIndex}
|
viewportIndex={viewportIndex}
|
||||||
imageIds={imageIds}
|
imageIds={imageIds}
|
||||||
imageIdIndex={currentImageIdIndex}
|
imageIdIndex={currentImageIdIndex}
|
||||||
|
|||||||
@ -55,7 +55,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ohif/core": "^2.9.6",
|
"@ohif/core": "^2.9.6",
|
||||||
"cornerstone-tools": "4.15.1",
|
"cornerstone-tools": "4.16.0",
|
||||||
"@ohif/ui": "^2.0.0",
|
"@ohif/ui": "^2.0.0",
|
||||||
"cornerstone-core": "^2.3.0",
|
"cornerstone-core": "^2.3.0",
|
||||||
"cornerstone-wado-image-loader": "^3.1.2",
|
"cornerstone-wado-image-loader": "^3.1.2",
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
// TODO: torn, can either bake this here; or have to create a whole new button type
|
// TODO: torn, can either bake this here; or have to create a whole new button type
|
||||||
// Only ways that you can pass in a custom React component for render :l
|
// Only ways that you can pass in a custom React component for render :l
|
||||||
|
import { ExpandableToolbarButton, ListMenu } from '@ohif/ui';
|
||||||
|
import React from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
// Divider
|
// Divider
|
||||||
@ -29,13 +32,58 @@ export default [
|
|||||||
config: {
|
config: {
|
||||||
groupName: 'primaryTool',
|
groupName: 'primaryTool',
|
||||||
},
|
},
|
||||||
|
component: ExpandableToolbarButton,
|
||||||
props: {
|
props: {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
icon: 'tool-window-level',
|
icon: 'tool-window-level',
|
||||||
label: 'Levels',
|
|
||||||
commandName: 'setToolActive',
|
commandName: 'setToolActive',
|
||||||
commandOptions: { toolName: 'Wwwc' },
|
commandOptions: { toolName: 'Wwwc' },
|
||||||
|
commands: {
|
||||||
|
'windowLevelPreset1': {
|
||||||
|
commandName: 'windowLevelPreset1',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
'windowLevelPreset2': {
|
||||||
|
commandName: 'windowLevelPreset2',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
'windowLevelPreset3': {
|
||||||
|
commandName: 'windowLevelPreset3',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
'windowLevelPreset4': {
|
||||||
|
commandName: 'windowLevelPreset4',
|
||||||
|
commandOptions: {},
|
||||||
|
},
|
||||||
|
'windowLevelPreset5': {
|
||||||
|
commandName: 'windowLevelPreset5',
|
||||||
|
commandOptions: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
|
content: ListMenu,
|
||||||
|
contentProps: {
|
||||||
|
options: [
|
||||||
|
{ value: 'windowLevelPreset1', title: 'Soft tissue', subtitle: '400 / 40' },
|
||||||
|
{ value: 'windowLevelPreset2', title: 'Lung', subtitle: '1500 / -600' },
|
||||||
|
{ value: 'windowLevelPreset3', title: 'Liver', subtitle: '150 / 90' },
|
||||||
|
{ value: 'windowLevelPreset4', title: 'Bone', subtitle: '80 / 40' },
|
||||||
|
{ value: 'windowLevelPreset5', title: 'Brain', subtitle: '2500 / 480' },
|
||||||
|
],
|
||||||
|
renderer: ({ title, subtitle, isActive, index }) => (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-white", "mr-2 text-base")}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-aqua-pale", "font-thin text-sm")}>
|
||||||
|
{subtitle}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-primary-active", "text-sm")}>{index + 1}</span>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"cornerstone-core": "^2.3.0",
|
"cornerstone-core": "^2.3.0",
|
||||||
"cornerstone-tools": "^4.12.0",
|
"cornerstone-tools": "4.16.0",
|
||||||
"cornerstone-wado-image-loader": "^3.1.2",
|
"cornerstone-wado-image-loader": "^3.1.2",
|
||||||
"dicom-parser": "^1.8.3"
|
"dicom-parser": "^1.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -62,7 +62,7 @@ export default class ToolBarService {
|
|||||||
this._broadcastChange(this.EVENTS.TOOL_BAR_MODIFIED, {});
|
this._broadcastChange(this.EVENTS.TOOL_BAR_MODIFIED, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
getButtonSection(key) {
|
getButtonSection(key, props) {
|
||||||
const buttonSectionIds = this.buttonSections[key];
|
const buttonSectionIds = this.buttonSections[key];
|
||||||
const buttonsInSection = [];
|
const buttonsInSection = [];
|
||||||
|
|
||||||
@ -79,7 +79,8 @@ export default class ToolBarService {
|
|||||||
|
|
||||||
btnIds.forEach(nestedBtnId => {
|
btnIds.forEach(nestedBtnId => {
|
||||||
const nestedBtn = this.buttons[nestedBtnId];
|
const nestedBtn = this.buttons[nestedBtnId];
|
||||||
const mappedNestedBtn = this._mapButtonToDisplay(nestedBtn, key);
|
const metadata = { isNested: true };
|
||||||
|
const mappedNestedBtn = this._mapButtonToDisplay(nestedBtn, key, metadata, props);
|
||||||
|
|
||||||
nestedButtons.push(mappedNestedBtn);
|
nestedButtons.push(mappedNestedBtn);
|
||||||
});
|
});
|
||||||
@ -90,7 +91,8 @@ export default class ToolBarService {
|
|||||||
} else {
|
} else {
|
||||||
const btnId = btnIdOrArray;
|
const btnId = btnIdOrArray;
|
||||||
const btn = this.buttons[btnId];
|
const btn = this.buttons[btnId];
|
||||||
const mappedBtn = this._mapButtonToDisplay(btn, key);
|
const metadata = { isNested: false };
|
||||||
|
const mappedBtn = this._mapButtonToDisplay(btn, key, metadata, props);
|
||||||
|
|
||||||
buttonsInSection.push(mappedBtn);
|
buttonsInSection.push(mappedBtn);
|
||||||
}
|
}
|
||||||
@ -136,8 +138,8 @@ export default class ToolBarService {
|
|||||||
* @param {*} btn
|
* @param {*} btn
|
||||||
* @param {*} btnSection
|
* @param {*} btnSection
|
||||||
*/
|
*/
|
||||||
_mapButtonToDisplay(btn, btnSection) {
|
_mapButtonToDisplay(btn, btnSection, metadata, props) {
|
||||||
const { id, type, component, props } = btn;
|
const { id, type, component } = btn;
|
||||||
const buttonType = this._buttonTypes()[type];
|
const buttonType = this._buttonTypes()[type];
|
||||||
|
|
||||||
if (!buttonType) {
|
if (!buttonType) {
|
||||||
@ -146,7 +148,7 @@ export default class ToolBarService {
|
|||||||
|
|
||||||
const onClick = evt => {
|
const onClick = evt => {
|
||||||
if (buttonType.clickHandler) {
|
if (buttonType.clickHandler) {
|
||||||
buttonType.clickHandler(evt, btn, btnSection);
|
buttonType.clickHandler(evt, btn, btnSection, metadata, props);
|
||||||
}
|
}
|
||||||
if (btn.props.onClick) {
|
if (btn.props.onClick) {
|
||||||
btn.onClick(evt, btn, btnSection);
|
btn.onClick(evt, btn, btnSection);
|
||||||
@ -154,12 +156,15 @@ export default class ToolBarService {
|
|||||||
if (btn.props.clickHandler) {
|
if (btn.props.clickHandler) {
|
||||||
btn.clickHandler(evt, btn, btnSection);
|
btn.clickHandler(evt, btn, btnSection);
|
||||||
}
|
}
|
||||||
|
if (props && props.onClick) {
|
||||||
|
props.onClick(evt, btn, btnSection, props);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
Component: component || buttonType.defaultComponent,
|
Component: component || buttonType.defaultComponent,
|
||||||
componentProps: Object.assign({}, props, { onClick }), //
|
componentProps: Object.assign({}, btn.props, { onClick }), //
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,8 @@ export {
|
|||||||
DateRange,
|
DateRange,
|
||||||
Dialog,
|
Dialog,
|
||||||
EmptyStudies,
|
EmptyStudies,
|
||||||
|
ExpandableToolbarButton,
|
||||||
|
ListMenu,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
Input,
|
Input,
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
.ExpandableToolbarButton:hover .ExpandableToolbarButton__arrow:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10px;
|
||||||
|
border-width: 10px 10px 0;
|
||||||
|
border-style: solid;
|
||||||
|
border-color:#5acce6 transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ExpandableToolbarButton .ExpandableToolbarButton__content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ExpandableToolbarButton:hover .ExpandableToolbarButton__content {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
import { IconButton, Icon } from '@ohif/ui';
|
||||||
|
|
||||||
|
import './ExpandableToolbarButton.css';
|
||||||
|
|
||||||
|
const ExpandableToolbarButton = ({
|
||||||
|
type,
|
||||||
|
id,
|
||||||
|
isActive,
|
||||||
|
onClick,
|
||||||
|
icon,
|
||||||
|
className,
|
||||||
|
content: Content,
|
||||||
|
contentProps
|
||||||
|
}) => {
|
||||||
|
const classes = {
|
||||||
|
type: {
|
||||||
|
primary: isActive
|
||||||
|
? 'text-black'
|
||||||
|
: 'text-common-bright hover:bg-primary-dark hover:text-primary-light',
|
||||||
|
secondary: isActive
|
||||||
|
? 'text-black'
|
||||||
|
: 'text-white hover:bg-secondary-dark focus:bg-secondary-dark',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChildClickHandler = (...args) => {
|
||||||
|
onClick(...args);
|
||||||
|
|
||||||
|
if (contentProps.onClick) {
|
||||||
|
contentProps.onClick(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClickHandler = (...args) => {
|
||||||
|
onClick(...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={id} className="ExpandableToolbarButton">
|
||||||
|
<IconButton
|
||||||
|
variant={isActive ? 'contained' : 'text'}
|
||||||
|
className={classnames(
|
||||||
|
'mx-1',
|
||||||
|
classes.type[type],
|
||||||
|
isActive && 'ExpandableToolbarButton__arrow'
|
||||||
|
)}
|
||||||
|
onClick={onClickHandler}
|
||||||
|
key={id}
|
||||||
|
>
|
||||||
|
<Icon name={icon} />
|
||||||
|
</IconButton>
|
||||||
|
<div className="absolute z-10 pt-4">
|
||||||
|
<div className={classnames("ExpandableToolbarButton__content w-48", className)}>
|
||||||
|
<Content {...contentProps} onClick={onChildClickHandler} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const noop = () => { };
|
||||||
|
|
||||||
|
ExpandableToolbarButton.defaultProps = {
|
||||||
|
isActive: false,
|
||||||
|
type: 'primary',
|
||||||
|
content: null,
|
||||||
|
onClick: noop,
|
||||||
|
};
|
||||||
|
|
||||||
|
ExpandableToolbarButton.propTypes = {
|
||||||
|
/* Influences background/hover styling */
|
||||||
|
type: PropTypes.oneOf(['primary', 'secondary']),
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
isActive: PropTypes.bool,
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
icon: PropTypes.string.isRequired,
|
||||||
|
/** Expandable toolbar button content can be replaced for a customized content by passing a node to this value. */
|
||||||
|
content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
||||||
|
contentProps: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExpandableToolbarButton;
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
name: Expandable Toolbar Button
|
||||||
|
menu: General
|
||||||
|
route: components/expandableToolbarButton
|
||||||
|
---
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Playground, Props } from 'docz';
|
||||||
|
import { ExpandableToolbarButton, ListMenu } from '@ohif/ui';
|
||||||
|
|
||||||
|
# Toolbar Button
|
||||||
|
|
||||||
|
Expandable Toolbar Buttons are used to populate the Toolbar.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { ExpandableToolbarButton, ListMenu } from '@ohif/ui';
|
||||||
|
```
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
{() => {
|
||||||
|
const props = {
|
||||||
|
content: ListMenu,
|
||||||
|
contentProps: {
|
||||||
|
options: [
|
||||||
|
{ value: 'windowLevelPreset1', title: 'Soft tissue', subtitle: '400 / 40' },
|
||||||
|
{ value: 'windowLevelPreset2', title: 'Lung', subtitle: '1500 / -600' },
|
||||||
|
{ value: 'windowLevelPreset3', title: 'Liver', subtitle: '150 / 90' },
|
||||||
|
{ value: 'windowLevelPreset4', title: 'Bone', subtitle: '80 / 40' },
|
||||||
|
{ value: 'windowLevelPreset5', title: 'Brain', subtitle: '2500 / 480' },
|
||||||
|
],
|
||||||
|
renderer: ({ title, subtitle, isActive, index }) => (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-white", "mr-2 text-base")}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-aqua-pale", "font-thin text-sm")}>
|
||||||
|
{subtitle}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-primary-active", "text-sm")}>{index + 1}</span>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="py-10 flex justify-center">
|
||||||
|
<ExpandableToolbarButton {...props} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<Props of={ToolbarButton} />
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
import ExpandableToolbarButton from './ExpandableToolbarButton';
|
||||||
|
export default ExpandableToolbarButton;
|
||||||
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
const baseClasses =
|
const baseClasses =
|
||||||
'text-center items-center justify-center outline-none transition duration-300 ease-in-out font-bold focus:outline-none';
|
'text-center items-center justify-center outline-none font-bold focus:outline-none';
|
||||||
|
|
||||||
const roundedClasses = {
|
const roundedClasses = {
|
||||||
none: '',
|
none: '',
|
||||||
@ -113,7 +113,7 @@ const IconButton = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
IconButton.defaultProps = {
|
IconButton.defaultProps = {
|
||||||
onClick: () => {},
|
onClick: () => { },
|
||||||
color: 'default',
|
color: 'default',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
fullWidth: false,
|
fullWidth: false,
|
||||||
|
|||||||
65
platform/ui/src/components/ListMenu/ListMenu.jsx
Normal file
65
platform/ui/src/components/ListMenu/ListMenu.jsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const ListMenu = ({ options = [], renderer, onClick }) => {
|
||||||
|
const [selectedIndex, setSelectedIndex] = useState(null);
|
||||||
|
|
||||||
|
const ListItem = (props) => {
|
||||||
|
const flex = 'flex flex-row justify-between items-center';
|
||||||
|
const theme = 'bg-indigo-dark';
|
||||||
|
const hover = 'hover:bg-primary-dark';
|
||||||
|
const spacing = 'p-3 h-8';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
flex,
|
||||||
|
theme,
|
||||||
|
spacing,
|
||||||
|
'cursor-pointer',
|
||||||
|
!props.isActive && hover,
|
||||||
|
props.isActive && 'bg-primary-light',
|
||||||
|
)}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
|
{renderer && renderer(props)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col rounded-md bg-secondary-dark pt-2 pb-2">
|
||||||
|
{options.map((option, index) => {
|
||||||
|
const onClickHandler = () => {
|
||||||
|
setSelectedIndex(index);
|
||||||
|
onClick({ ...option, index });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem
|
||||||
|
key={`ListItem${index}`}
|
||||||
|
{...option}
|
||||||
|
index={index}
|
||||||
|
isActive={selectedIndex === index}
|
||||||
|
onClick={onClickHandler}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const noop = () => { };
|
||||||
|
|
||||||
|
ListMenu.propTypes = {
|
||||||
|
options: PropTypes.array.isRequired,
|
||||||
|
renderer: PropTypes.func.isRequired,
|
||||||
|
onClick: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
ListMenu.defaultProps = {
|
||||||
|
onClick: noop
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListMenu;
|
||||||
52
platform/ui/src/components/ListMenu/ListMenu.mdx
Normal file
52
platform/ui/src/components/ListMenu/ListMenu.mdx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
name: List Menu
|
||||||
|
menu: General
|
||||||
|
route: components/listMenu
|
||||||
|
---
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Playground, Props } from 'docz';
|
||||||
|
import { ListMenu } from '@ohif/ui';
|
||||||
|
|
||||||
|
# List Menu
|
||||||
|
|
||||||
|
List Menus are used to populate expandable Toolbar.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { ListMenu } from '@ohif/ui';
|
||||||
|
```
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
{() => {
|
||||||
|
return (
|
||||||
|
<ToolbarButton options={[
|
||||||
|
{ value: 'windowLevelPreset1', title: 'Soft tissue', subtitle: '400 / 40' },
|
||||||
|
{ value: 'windowLevelPreset2', title: 'Lung', subtitle: '1500 / -600' },
|
||||||
|
{ value: 'windowLevelPreset3', title: 'Liver', subtitle: '150 / 90' },
|
||||||
|
{ value: 'windowLevelPreset4', title: 'Bone', subtitle: '80 / 40' },
|
||||||
|
{ value: 'windowLevelPreset5', title: 'Brain', subtitle: '2500 / 480' },
|
||||||
|
]}
|
||||||
|
renderer={
|
||||||
|
({ title, subtitle, isActive, index }) => (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-white", "mr-2 text-base")}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-aqua-pale", "font-thin text-sm")}>
|
||||||
|
{subtitle}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span className={classnames(isActive ? "text-black" : "text-primary-active", "text-sm")}>{index + 1}</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<Props of={ToolbarButton} />
|
||||||
2
platform/ui/src/components/ListMenu/index.js
Normal file
2
platform/ui/src/components/ListMenu/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import ListMenu from './ListMenu';
|
||||||
|
export default ListMenu;
|
||||||
@ -76,7 +76,7 @@ const Select = ({
|
|||||||
options={options}
|
options={options}
|
||||||
value={selectedOptions}
|
value={selectedOptions}
|
||||||
onChange={(selectedOptions, { action }) => {
|
onChange={(selectedOptions, { action }) => {
|
||||||
const newSelection = selectedOptions.reduce(
|
const newSelection = !selectedOptions.length ? selectedOptions : selectedOptions.reduce(
|
||||||
(acc, curr) => acc.concat([curr.value]),
|
(acc, curr) => acc.concat([curr.value]),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,6 +25,7 @@ const ToolbarButton = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const shouldShowDropdown = !!isActive && !!dropdownContent;
|
const shouldShowDropdown = !!isActive && !!dropdownContent;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={id}>
|
<div key={id}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const arrowPositionStyle = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const Tooltip = ({ content, isSticky, position, tight, children }) => {
|
const Tooltip = ({ content, isSticky, position, tight, children, isDisabled }) => {
|
||||||
const [isActive, setIsActive] = useState(false);
|
const [isActive, setIsActive] = useState(false);
|
||||||
|
|
||||||
const handleMouseOver = () => {
|
const handleMouseOver = () => {
|
||||||
@ -39,7 +39,7 @@ const Tooltip = ({ content, isSticky, position, tight, children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isOpen = isSticky || isActive;
|
const isOpen = (isSticky || isActive) && !isDisabled;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -84,10 +84,12 @@ Tooltip.defaultProps = {
|
|||||||
tight: false,
|
tight: false,
|
||||||
isSticky: false,
|
isSticky: false,
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
|
isDisabled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
Tooltip.propTypes = {
|
Tooltip.propTypes = {
|
||||||
// Allow null
|
/** prevents tooltip from rendering despite hover/active/sticky */
|
||||||
|
isDisabled: PropTypes.bool,
|
||||||
content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
||||||
position: PropTypes.oneOf([
|
position: PropTypes.oneOf([
|
||||||
'bottom',
|
'bottom',
|
||||||
|
|||||||
@ -39,6 +39,8 @@ import ThumbnailNoImage from './ThumbnailNoImage';
|
|||||||
import ThumbnailTracked from './ThumbnailTracked';
|
import ThumbnailTracked from './ThumbnailTracked';
|
||||||
import ThumbnailList from './ThumbnailList';
|
import ThumbnailList from './ThumbnailList';
|
||||||
import ToolbarButton from './ToolbarButton';
|
import ToolbarButton from './ToolbarButton';
|
||||||
|
import ExpandableToolbarButton from './ExpandableToolbarButton';
|
||||||
|
import ListMenu from './ListMenu';
|
||||||
import Tooltip from './Tooltip';
|
import Tooltip from './Tooltip';
|
||||||
import Typography from './Typography';
|
import Typography from './Typography';
|
||||||
import Viewport from './Viewport';
|
import Viewport from './Viewport';
|
||||||
@ -52,6 +54,8 @@ export {
|
|||||||
DateRange,
|
DateRange,
|
||||||
Dialog,
|
Dialog,
|
||||||
EmptyStudies,
|
EmptyStudies,
|
||||||
|
ExpandableToolbarButton,
|
||||||
|
ListMenu,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
Input,
|
Input,
|
||||||
|
|||||||
@ -16,6 +16,13 @@ module.exports = {
|
|||||||
initial: 'initial',
|
initial: 'initial',
|
||||||
inherit: 'inherit',
|
inherit: 'inherit',
|
||||||
|
|
||||||
|
indigo: {
|
||||||
|
dark: '#0b1a42'
|
||||||
|
},
|
||||||
|
aqua: {
|
||||||
|
pale: '#7bb2ce'
|
||||||
|
},
|
||||||
|
|
||||||
primary: {
|
primary: {
|
||||||
light: '#5acce6',
|
light: '#5acce6',
|
||||||
main: '#0944b3',
|
main: '#0944b3',
|
||||||
|
|||||||
@ -67,7 +67,7 @@
|
|||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"core-js": "^3.2.1",
|
"core-js": "^3.2.1",
|
||||||
"cornerstone-math": "^0.1.8",
|
"cornerstone-math": "^0.1.8",
|
||||||
"cornerstone-tools": "4.15.1",
|
"cornerstone-tools": "4.16.0",
|
||||||
"cornerstone-wado-image-loader": "^3.1.2",
|
"cornerstone-wado-image-loader": "^3.1.2",
|
||||||
"dcmjs": "0.14.0",
|
"dcmjs": "0.14.0",
|
||||||
"dicom-parser": "^1.8.3",
|
"dicom-parser": "^1.8.3",
|
||||||
|
|||||||
@ -19,7 +19,9 @@ window.config = {
|
|||||||
imageRendering: 'wadors',
|
imageRendering: 'wadors',
|
||||||
thumbnailRendering: 'wadors',
|
thumbnailRendering: 'wadors',
|
||||||
enableStudyLazyLoad: true,
|
enableStudyLazyLoad: true,
|
||||||
|
supportsFuzzyMatching: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
defaultDataSourceName: 'dicomweb',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6755,10 +6755,10 @@ cornerstone-math@^0.1.8:
|
|||||||
resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5"
|
resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5"
|
||||||
integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw==
|
integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw==
|
||||||
|
|
||||||
cornerstone-tools@4.15.1:
|
cornerstone-tools@4.16.0:
|
||||||
version "4.15.1"
|
version "4.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-4.15.1.tgz#f0b1026da9c7758defc088bb2f1e78426a23d91e"
|
resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-4.16.0.tgz#af3d32d13722b97bec258492642e622312280196"
|
||||||
integrity sha512-fJuTUJW/NDSD520jPB++tX//Kq80jPDngChHZrhx2xjj/9dCnexD9kmTX30Z0WUq0a2JEHZ6FlcOX38kSmw1hQ==
|
integrity sha512-kUhuSb2Ixpd2hgbdem+740rnN4hmoxzcOBNaUcsizFRWjMAsgc0yUxBFwLl0mIs811mefq79JOL+juwRA8T3Tg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "7.1.2"
|
"@babel/runtime" "7.1.2"
|
||||||
cornerstone-math "0.1.7"
|
cornerstone-math "0.1.7"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user