Merge pull request #504 from dannyrb/master-semicolon-fix

semicolon fix
This commit is contained in:
Danny Brown 2019-05-29 10:37:36 -04:00 committed by GitHub
commit a3405e7a9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 1129 additions and 1117 deletions

View File

@ -3,7 +3,7 @@
"printWidth": 80, "printWidth": 80,
"proseWrap": "always", "proseWrap": "always",
"tabWidth": 2, "tabWidth": 2,
"semi": false, "semi": true,
"singleQuote": true, "singleQuote": true,
"endOfLine": "lf" "endOfLine": "lf"
} }

View File

@ -1,47 +1,47 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import { BrowserRouter as Router } from 'react-router-dom' import { BrowserRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux' import { Provider } from 'react-redux';
import { createStore, combineReducers } from 'redux' import { createStore, combineReducers } from 'redux';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
import './config' import './config';
import ui from './redux/ui.js' import ui from './redux/ui.js';
import OHIFStandaloneViewer from './OHIFStandaloneViewer' import OHIFStandaloneViewer from './OHIFStandaloneViewer';
import WhiteLabellingContext from './WhiteLabellingContext' import WhiteLabellingContext from './WhiteLabellingContext';
import OHIFCornerstoneExtension from 'ohif-cornerstone-extension' import OHIFCornerstoneExtension from 'ohif-cornerstone-extension';
import OHIFVTKExtension from 'ohif-vtk-extension' import OHIFVTKExtension from 'ohif-vtk-extension';
import OHIFDicomPDFExtension from 'ohif-dicom-pdf-extension' import OHIFDicomPDFExtension from 'ohif-dicom-pdf-extension';
import OHIFDicomHtmlExtension from 'ohif-dicom-html-extension' import OHIFDicomHtmlExtension from 'ohif-dicom-html-extension';
import OHIFDicomMicroscopyExtension from 'ohif-dicom-microscopy-extension' import OHIFDicomMicroscopyExtension from 'ohif-dicom-microscopy-extension';
import { OidcProvider, reducer as oidcReducer } from 'redux-oidc' import { OidcProvider, reducer as oidcReducer } from 'redux-oidc';
import { import {
getDefaultToolbarButtons, getDefaultToolbarButtons,
getUserManagerForOpenIdConnectClient, getUserManagerForOpenIdConnectClient,
initWebWorkers, initWebWorkers,
} from './utils/index.js' } from './utils/index.js';
import setupTools from './setupTools' import setupTools from './setupTools';
import ConnectedToolContextMenu from './connectedComponents/ConnectedToolContextMenu' import ConnectedToolContextMenu from './connectedComponents/ConnectedToolContextMenu';
const { ExtensionManager } = OHIF.extensions const { ExtensionManager } = OHIF.extensions;
const { reducers, localStorage } = OHIF.redux const { reducers, localStorage } = OHIF.redux;
reducers.ui = ui reducers.ui = ui;
reducers.oidc = oidcReducer reducers.oidc = oidcReducer;
const combined = combineReducers(reducers) const combined = combineReducers(reducers);
const store = createStore(combined, localStorage.loadState()) const store = createStore(combined, localStorage.loadState());
store.subscribe(() => { store.subscribe(() => {
localStorage.saveState({ localStorage.saveState({
preferences: store.getState().preferences, preferences: store.getState().preferences,
}) });
}) });
setupTools(store) setupTools(store);
const children = { const children = {
viewport: [<ConnectedToolContextMenu />], viewport: [<ConnectedToolContextMenu />],
} };
/** TODO: extensions should be passed in as prop as soon as we have the extensions as separate packages and then registered by ExtensionsManager */ /** TODO: extensions should be passed in as prop as soon as we have the extensions as separate packages and then registered by ExtensionsManager */
const extensions = [ const extensions = [
@ -50,15 +50,15 @@ const extensions = [
new OHIFDicomPDFExtension(), new OHIFDicomPDFExtension(),
new OHIFDicomHtmlExtension(), new OHIFDicomHtmlExtension(),
new OHIFDicomMicroscopyExtension(), new OHIFDicomMicroscopyExtension(),
] ];
ExtensionManager.registerExtensions(store, extensions) ExtensionManager.registerExtensions(store, extensions);
// TODO[react] Use a provider when the whole tree is React // TODO[react] Use a provider when the whole tree is React
window.store = store window.store = store;
function handleServers(servers) { function handleServers(servers) {
if (servers) { if (servers) {
OHIF.utils.addServers(servers, store) OHIF.utils.addServers(servers, store);
} }
} }
@ -69,39 +69,41 @@ class App extends Component {
servers: PropTypes.object.isRequired, servers: PropTypes.object.isRequired,
oidc: PropTypes.array, oidc: PropTypes.array,
whiteLabelling: PropTypes.object, whiteLabelling: PropTypes.object,
} };
static defaultProps = { static defaultProps = {
whiteLabelling: {}, whiteLabelling: {},
oidc: [], oidc: [],
} };
constructor(props) { constructor(props) {
super(props) super(props);
// //
const defaultButtons = getDefaultToolbarButtons(this.props.routerBasename) const defaultButtons = getDefaultToolbarButtons(this.props.routerBasename);
const buttonsAction = OHIF.redux.actions.setAvailableButtons(defaultButtons) const buttonsAction = OHIF.redux.actions.setAvailableButtons(
defaultButtons
);
store.dispatch(buttonsAction) store.dispatch(buttonsAction);
if (this.props.oidc.length) { if (this.props.oidc.length) {
const firstOpenIdClient = this.props.oidc[0] const firstOpenIdClient = this.props.oidc[0];
this.userManager = getUserManagerForOpenIdConnectClient( this.userManager = getUserManagerForOpenIdConnectClient(
store, store,
firstOpenIdClient firstOpenIdClient
) );
} }
handleServers(this.props.servers) handleServers(this.props.servers);
initWebWorkers( initWebWorkers(
this.props.routerBasename, this.props.routerBasename,
this.props.relativeWebWorkerScriptsPath this.props.relativeWebWorkerScriptsPath
) );
} }
render() { render() {
const userManager = this.userManager const userManager = this.userManager;
if (userManager) { if (userManager) {
return ( return (
@ -114,7 +116,7 @@ class App extends Component {
</Router> </Router>
</OidcProvider> </OidcProvider>
</Provider> </Provider>
) );
} }
return ( return (
@ -125,8 +127,8 @@ class App extends Component {
</WhiteLabellingContext.Provider> </WhiteLabellingContext.Provider>
</Router> </Router>
</Provider> </Provider>
) );
} }
} }
export default App export default App;

View File

@ -6,7 +6,7 @@ import { CallbackComponent } from 'redux-oidc';
class CallbackPage extends Component { class CallbackPage extends Component {
static propTypes = { static propTypes = {
userManager: PropTypes.object.isRequired, userManager: PropTypes.object.isRequired,
history: PropTypes.object.isRequired history: PropTypes.object.isRequired,
}; };
render() { render() {

View File

@ -1,19 +1,19 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
// import asyncComponent from './components/AsyncComponent.js' // import asyncComponent from './components/AsyncComponent.js'
import IHEInvokeImageDisplay from './routes/IHEInvokeImageDisplay.js' import IHEInvokeImageDisplay from './routes/IHEInvokeImageDisplay.js';
import ViewerRouting from './routes/ViewerRouting.js' import ViewerRouting from './routes/ViewerRouting.js';
import StudyListRouting from './studylist/StudyListRouting.js' import StudyListRouting from './studylist/StudyListRouting.js';
import StandaloneRouting from './routes/StandaloneRouting.js' import StandaloneRouting from './routes/StandaloneRouting.js';
import CallbackPage from './CallbackPage.js' import CallbackPage from './CallbackPage.js';
import { withRouter } from 'react-router' import { withRouter } from 'react-router';
import { Route, Switch } from 'react-router-dom' import { Route, Switch } from 'react-router-dom';
import { connect } from 'react-redux' import { connect } from 'react-redux';
import { ViewerbaseDragDropContext } from 'react-viewerbase' import { ViewerbaseDragDropContext } from 'react-viewerbase';
import './OHIFStandaloneViewer.css' import './OHIFStandaloneViewer.css';
import './variables.css' import './variables.css';
import './theme-tide.css' import './theme-tide.css';
// Dynamic Import Routes (CodeSplitting) // Dynamic Import Routes (CodeSplitting)
// const IHEInvokeImageDisplay = asyncComponent(() => // const IHEInvokeImageDisplay = asyncComponent(() =>
@ -29,35 +29,35 @@ import './theme-tide.css'
// const CallbackPage = asyncComponent(() => import('./CallbackPage.js')) // const CallbackPage = asyncComponent(() => import('./CallbackPage.js'))
// //
const reload = () => window.location.reload() const reload = () => window.location.reload();
class OHIFStandaloneViewer extends Component { class OHIFStandaloneViewer extends Component {
static propTypes = { static propTypes = {
history: PropTypes.object.isRequired, history: PropTypes.object.isRequired,
user: PropTypes.object, user: PropTypes.object,
} };
componentDidMount() { componentDidMount() {
this.unlisten = this.props.history.listen((location, action) => { this.unlisten = this.props.history.listen((location, action) => {
if (this.props.setContext) { if (this.props.setContext) {
this.props.setContext(window.location.pathname) this.props.setContext(window.location.pathname);
} }
}) });
} }
componentWillUnmount() { componentWillUnmount() {
this.unlisten() this.unlisten();
} }
render() { render() {
const { user, userManager } = this.props const { user, userManager } = this.props;
const userNotLoggedIn = userManager && (!user || user.expired) const userNotLoggedIn = userManager && (!user || user.expired);
if (userNotLoggedIn) { if (userNotLoggedIn) {
const pathname = this.props.location.pathname const pathname = this.props.location.pathname;
if (pathname !== '/callback') { if (pathname !== '/callback') {
sessionStorage.setItem('ohif-redirect-to', pathname) sessionStorage.setItem('ohif-redirect-to', pathname);
} }
return ( return (
@ -70,13 +70,13 @@ class OHIFStandaloneViewer extends Component {
/> />
<Route <Route
component={() => { component={() => {
userManager.signinRedirect() userManager.signinRedirect();
return null return null;
}} }}
/> />
</Switch> </Switch>
) );
} }
return ( return (
@ -97,21 +97,21 @@ class OHIFStandaloneViewer extends Component {
/> />
<Route render={() => <div> Sorry, this page does not exist. </div>} /> <Route render={() => <div> Sorry, this page does not exist. </div>} />
</Switch> </Switch>
) );
} }
} }
const mapStateToProps = state => { const mapStateToProps = state => {
return { return {
user: state.oidc.user, user: state.oidc.user,
} };
} };
const ConnectedOHIFStandaloneViewer = connect( const ConnectedOHIFStandaloneViewer = connect(
mapStateToProps, mapStateToProps,
null null
)(OHIFStandaloneViewer) )(OHIFStandaloneViewer);
export default ViewerbaseDragDropContext( export default ViewerbaseDragDropContext(
withRouter(ConnectedOHIFStandaloneViewer) withRouter(ConnectedOHIFStandaloneViewer)
) );

View File

@ -2,7 +2,7 @@ import OHIFLogo from './components/OHIFLogo/OHIFLogo.js';
import React from 'react'; import React from 'react';
const defaultContextValues = { const defaultContextValues = {
logoComponent: OHIFLogo() logoComponent: OHIFLogo(),
}; };
const WhiteLabellingContext = React.createContext(defaultContextValues); const WhiteLabellingContext = React.createContext(defaultContextValues);

View File

@ -2,4 +2,4 @@ export default {
webWorkerManager: { webWorkerManager: {
initialize: jest.fn(), initialize: jest.fn(),
}, },
} };

View File

@ -1,3 +1,3 @@
// https://jestjs.io/docs/en/webpack#handling-static-assets // https://jestjs.io/docs/en/webpack#handling-static-assets
module.exports = 'test-file-stub' module.exports = 'test-file-stub';

View File

@ -1,4 +1,4 @@
const createUserManager = () => jest.fn().mockReturnValue({}) const createUserManager = () => jest.fn().mockReturnValue({});
const loadUser = () => jest.fn() const loadUser = () => jest.fn();
export { createUserManager, loadUser } export { createUserManager, loadUser };

View File

@ -1,9 +1,9 @@
const _ = require('lodash') const _ = require('lodash');
const originalConsoleError = console.error const originalConsoleError = console.error;
// JSDom's CSS Parser has limited support for certain features // JSDom's CSS Parser has limited support for certain features
// This supresses error warnings caused by it // This supresses error warnings caused by it
console.error = function(msg) { console.error = function(msg) {
if (_.startsWith(msg, 'Error: Could not parse CSS stylesheet')) return if (_.startsWith(msg, 'Error: Could not parse CSS stylesheet')) return;
originalConsoleError(msg) originalConsoleError(msg);
} };

View File

@ -4,34 +4,34 @@
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html * Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
*/ */
import React, { Component } from 'react' import React, { Component } from 'react';
export default function asyncComponent(importComponent) { export default function asyncComponent(importComponent) {
class AsyncComponent extends Component { class AsyncComponent extends Component {
constructor(props) { constructor(props) {
super(props) super(props);
this.state = { this.state = {
component: null, component: null,
} };
} }
async componentDidMount() { async componentDidMount() {
// Add dynamically loaded component to state // Add dynamically loaded component to state
const { default: component } = await importComponent() const { default: component } = await importComponent();
this.setState({ this.setState({
component: component, component: component,
}) });
} }
render() { render() {
const C = this.state.component const C = this.state.component;
// Render the loaded component, or null // Render the loaded component, or null
return C ? <C {...this.props} /> : null return C ? <C {...this.props} /> : null;
} }
} }
return AsyncComponent return AsyncComponent;
} }

View File

@ -1,18 +1,18 @@
import { Component } from 'react' import { Component } from 'react';
import React from 'react' import React from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import SimpleDialog from '../SimpleDialog/SimpleDialog.js' import SimpleDialog from '../SimpleDialog/SimpleDialog.js';
import bounding from '../../lib/utils/bounding.js' import bounding from '../../lib/utils/bounding.js';
import { getDialogStyle } from './../Labelling/labellingPositionUtils.js' import { getDialogStyle } from './../Labelling/labellingPositionUtils.js';
import './EditDescriptionDialog.css' import './EditDescriptionDialog.css';
export default class EditDescriptionDialog extends Component { export default class EditDescriptionDialog extends Component {
static defaultProps = { static defaultProps = {
componentRef: React.createRef(), componentRef: React.createRef(),
componentStyle: {}, componentStyle: {},
} };
static propTypes = { static propTypes = {
measurementData: PropTypes.object.isRequired, measurementData: PropTypes.object.isRequired,
@ -20,32 +20,32 @@ export default class EditDescriptionDialog extends Component {
componentRef: PropTypes.object, componentRef: PropTypes.object,
componentStyle: PropTypes.object, componentStyle: PropTypes.object,
onUpdate: PropTypes.func.isRequired, onUpdate: PropTypes.func.isRequired,
} };
constructor(props) { constructor(props) {
super(props) super(props);
this.state = { this.state = {
description: props.measurementData.description || '', description: props.measurementData.description || '',
} };
this.mainElement = React.createRef() this.mainElement = React.createRef();
} }
componentDidMount = () => { componentDidMount = () => {
bounding(this.mainElement) bounding(this.mainElement);
} };
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
if (this.props.description !== prevProps.description) { if (this.props.description !== prevProps.description) {
this.setState({ this.setState({
description: this.props.description, description: this.props.description,
}) });
} }
} }
render() { render() {
const style = getDialogStyle(this.props.componentStyle) const style = getDialogStyle(this.props.componentStyle);
return ( return (
<SimpleDialog <SimpleDialog
@ -65,18 +65,18 @@ export default class EditDescriptionDialog extends Component {
onChange={this.handleChange} onChange={this.handleChange}
/> />
</SimpleDialog> </SimpleDialog>
) );
} }
onClose = () => { onClose = () => {
this.props.onCancel() this.props.onCancel();
} };
onConfirm = () => { onConfirm = () => {
this.props.onUpdate(this.state.description) this.props.onUpdate(this.state.description);
} };
handleChange = event => { handleChange = event => {
this.setState({ description: event.target.value }) this.setState({ description: event.target.value });
} };
} }

View File

@ -11,32 +11,32 @@ class Header extends Component {
home: PropTypes.bool.isRequired, home: PropTypes.bool.isRequired,
location: PropTypes.object.isRequired, location: PropTypes.object.isRequired,
openUserPreferencesModal: PropTypes.func, openUserPreferencesModal: PropTypes.func,
children: PropTypes.node children: PropTypes.node,
}; };
static defaultProps = { static defaultProps = {
home: true, home: true,
children: OHIFLogo() children: OHIFLogo(),
}; };
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
userPreferencesOpen: false userPreferencesOpen: false,
}; };
this.options = [ this.options = [
{ {
title: 'Preferences ', title: 'Preferences ',
icon: 'fa fa-user', icon: 'fa fa-user',
onClick: this.props.openUserPreferencesModal onClick: this.props.openUserPreferencesModal,
}, },
{ {
title: 'About', title: 'About',
icon: 'fa fa-info', icon: 'fa fa-info',
link: 'http://ohif.org' link: 'http://ohif.org',
} },
]; ];
} }
@ -60,7 +60,7 @@ class Header extends Component {
className="header-btn header-studyListLinkSection" className="header-btn header-studyListLinkSection"
to={{ to={{
pathname: '/', pathname: '/',
state: { studyLink: this.props.location.pathname } state: { studyLink: this.props.location.pathname },
}} }}
> >
Study list Study list

View File

@ -1,3 +1,3 @@
import Header from './Header' import Header from './Header';
export default Header export default Header;

View File

@ -1,14 +1,14 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import cloneDeep from 'lodash.clonedeep' import cloneDeep from 'lodash.clonedeep';
import bounding from '../../lib/utils/bounding.js' import bounding from '../../lib/utils/bounding.js';
import LabellingTransition from './LabellingTransition.js' import LabellingTransition from './LabellingTransition.js';
import { SelectTree } from 'react-viewerbase' import { SelectTree } from 'react-viewerbase';
import { getAddLabelButtonStyle } from './labellingPositionUtils.js' import { getAddLabelButtonStyle } from './labellingPositionUtils.js';
import OHIFLabellingData from './OHIFLabellingData.js' import OHIFLabellingData from './OHIFLabellingData.js';
export default class LabellingFlow extends Component { export default class LabellingFlow extends Component {
static propTypes = { static propTypes = {
@ -21,16 +21,16 @@ export default class LabellingFlow extends Component {
skipAddLabelButton: PropTypes.bool, skipAddLabelButton: PropTypes.bool,
editLocation: PropTypes.bool, editLocation: PropTypes.bool,
editDescription: PropTypes.bool, editDescription: PropTypes.bool,
} };
constructor(props) { constructor(props) {
super(props) super(props);
const { location, locationLabel, description } = props.measurementData const { location, locationLabel, description } = props.measurementData;
let style = props.componentStyle let style = props.componentStyle;
if (!props.skipAddLabelButton) { if (!props.skipAddLabelButton) {
style = getAddLabelButtonStyle(props.measurementData, props.eventData) style = getAddLabelButtonStyle(props.measurementData, props.eventData);
} }
this.state = { this.state = {
@ -43,28 +43,28 @@ export default class LabellingFlow extends Component {
componentStyle: style, componentStyle: style,
confirmationState: false, confirmationState: false,
displayComponent: true, displayComponent: true,
} };
this.mainElement = React.createRef() this.mainElement = React.createRef();
this.descriptionInput = React.createRef() this.descriptionInput = React.createRef();
this.initialItems = OHIFLabellingData this.initialItems = OHIFLabellingData;
this.currentItems = cloneDeep(this.initialItems) this.currentItems = cloneDeep(this.initialItems);
} }
componentDidUpdate = () => { componentDidUpdate = () => {
this.repositionComponent() this.repositionComponent();
} };
render() { render() {
let mainElementClassName = 'labellingComponent' let mainElementClassName = 'labellingComponent';
if (this.state.editDescription) { if (this.state.editDescription) {
mainElementClassName += ' editDescription' mainElementClassName += ' editDescription';
} }
const style = Object.assign({}, this.state.componentStyle) const style = Object.assign({}, this.state.componentStyle);
if (this.state.skipAddLabelButton) { if (this.state.skipAddLabelButton) {
style.left -= 160 style.left -= 160;
} }
return ( return (
@ -82,7 +82,7 @@ export default class LabellingFlow extends Component {
{this.labellingStateFragment()} {this.labellingStateFragment()}
</div> </div>
</LabellingTransition> </LabellingTransition>
) );
} }
labellingStateFragment = () => { labellingStateFragment = () => {
@ -91,9 +91,12 @@ export default class LabellingFlow extends Component {
editLocation, editLocation,
description, description,
locationLabel, locationLabel,
} = this.state } = this.state;
const Icons = `${window.config.routerBasename}/icons.svg`.replace('//', '/') const Icons = `${window.config.routerBasename}/icons.svg`.replace(
'//',
'/'
);
if (!skipAddLabelButton) { if (!skipAddLabelButton) {
return ( return (
@ -106,7 +109,7 @@ export default class LabellingFlow extends Component {
{this.state.location ? 'Edit' : 'Add'} Label {this.state.location ? 'Edit' : 'Add'} Label
</button> </button>
</> </>
) );
} else { } else {
if (editLocation) { if (editLocation) {
return ( return (
@ -117,7 +120,7 @@ export default class LabellingFlow extends Component {
selectTreeFirstTitle="Assign Label" selectTreeFirstTitle="Assign Label"
onComponentChange={this.repositionComponent} onComponentChange={this.repositionComponent}
/> />
) );
} else { } else {
return ( return (
<> <>
@ -174,53 +177,53 @@ export default class LabellingFlow extends Component {
</button> </button>
</div> </div>
</> </>
) );
} }
} }
} };
relabel = () => { relabel = () => {
this.setState({ this.setState({
editLocation: true, editLocation: true,
}) });
} };
setDescriptionUpdateMode = () => { setDescriptionUpdateMode = () => {
this.descriptionInput.current.focus() this.descriptionInput.current.focus();
this.setState({ this.setState({
editDescription: true, editDescription: true,
}) });
} };
descriptionCancel = () => { descriptionCancel = () => {
const { description = '' } = cloneDeep(this.state) const { description = '' } = cloneDeep(this.state);
this.descriptionInput.current.value = description this.descriptionInput.current.value = description;
this.setState({ this.setState({
editDescription: false, editDescription: false,
}) });
} };
descriptionSave = () => { descriptionSave = () => {
const description = this.descriptionInput.current.value const description = this.descriptionInput.current.value;
this.props.updateLabelling({ description }) this.props.updateLabelling({ description });
this.setState({ this.setState({
description, description,
editDescription: false, editDescription: false,
}) });
} };
selectTreeSelectCalback = (event, itemSelected) => { selectTreeSelectCalback = (event, itemSelected) => {
const location = itemSelected.value const location = itemSelected.value;
this.props.updateLabelling({ location }) this.props.updateLabelling({ location });
const viewportTopPosition = this.mainElement.current.offsetParent.offsetTop const viewportTopPosition = this.mainElement.current.offsetParent.offsetTop;
const componentStyle = { const componentStyle = {
top: event.nativeEvent.y - viewportTopPosition - 25, top: event.nativeEvent.y - viewportTopPosition - 25,
left: this.state.componentStyle.left, left: this.state.componentStyle.left,
} };
this.setState({ this.setState({
editLocation: false, editLocation: false,
@ -228,51 +231,51 @@ export default class LabellingFlow extends Component {
location: itemSelected.value, location: itemSelected.value,
locationLabel: itemSelected.label, locationLabel: itemSelected.label,
componentStyle, componentStyle,
}) });
if (this.isTouchScreen) { if (this.isTouchScreen) {
this.setTimeout = setTimeout(() => { this.setTimeout = setTimeout(() => {
this.setState({ this.setState({
displayComponent: false, displayComponent: false,
}) });
}, 2000) }, 2000);
} }
} };
showLabelling = () => { showLabelling = () => {
this.setState({ this.setState({
skipAddLabelButton: true, skipAddLabelButton: true,
editLocation: false, editLocation: false,
}) });
} };
fadeOutAndLeave = () => { fadeOutAndLeave = () => {
// Wait for 1 sec to dismiss the labelling component // Wait for 1 sec to dismiss the labelling component
this.fadeOutTimer = setTimeout(() => { this.fadeOutTimer = setTimeout(() => {
this.setState({ this.setState({
displayComponent: false, displayComponent: false,
}) });
}, 1000) }, 1000);
} };
fadeOutAndLeaveFast = () => { fadeOutAndLeaveFast = () => {
this.setState({ this.setState({
displayComponent: false, displayComponent: false,
}) });
} };
clearFadeOutTimer = () => { clearFadeOutTimer = () => {
if (!this.fadeOutTimer) { if (!this.fadeOutTimer) {
return return;
} }
clearTimeout(this.fadeOutTimer) clearTimeout(this.fadeOutTimer);
} };
repositionComponent = () => { repositionComponent = () => {
// SetTimeout for the css animation to end. // SetTimeout for the css animation to end.
setTimeout(() => { setTimeout(() => {
bounding(this.mainElement) bounding(this.mainElement);
}, 200) }, 200);
} };
} }

View File

@ -1,12 +1,12 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import cloneDeep from 'lodash.clonedeep' import cloneDeep from 'lodash.clonedeep';
import EditDescriptionDialog from './../EditDescriptionDialog/EditDescriptionDialog.js' import EditDescriptionDialog from './../EditDescriptionDialog/EditDescriptionDialog.js';
import LabellingFlow from './LabellingFlow.js' import LabellingFlow from './LabellingFlow.js';
import './LabellingManager.css' import './LabellingManager.css';
export default class LabellingManager extends Component { export default class LabellingManager extends Component {
static propTypes = { static propTypes = {
@ -20,24 +20,24 @@ export default class LabellingManager extends Component {
editLocation: PropTypes.bool, editLocation: PropTypes.bool,
editDescription: PropTypes.bool, editDescription: PropTypes.bool,
editDescriptionOnDialog: PropTypes.bool, editDescriptionOnDialog: PropTypes.bool,
} };
static defaultProps = { static defaultProps = {
skipAddLabelButton: false, skipAddLabelButton: false,
editLocation: false, editLocation: false,
editDescription: false, editDescription: false,
editDescriptionOnDialog: false, editDescriptionOnDialog: false,
} };
constructor(props) { constructor(props) {
super(props) super(props);
const measurementData = cloneDeep(props.measurementData) const measurementData = cloneDeep(props.measurementData);
this.treatMeasurementData(measurementData) this.treatMeasurementData(measurementData);
let editLocation = props.editLocation let editLocation = props.editLocation;
if (!props.editDescription && !props.editLocation) { if (!props.editDescription && !props.editLocation) {
editLocation = true editLocation = true;
} }
this.state = { this.state = {
@ -47,19 +47,19 @@ export default class LabellingManager extends Component {
editDescription: props.editDescription, editDescription: props.editDescription,
editDescriptionOnDialog: props.editDescriptionOnDialog, editDescriptionOnDialog: props.editDescriptionOnDialog,
measurementData: measurementData, measurementData: measurementData,
} };
} }
componentDidMount = () => { componentDidMount = () => {
document.addEventListener('touchstart', this.onTouchStart) document.addEventListener('touchstart', this.onTouchStart);
} };
componentWillUnmount = () => { componentWillUnmount = () => {
document.removeEventListener('touchstart', this.onTouchStart) document.removeEventListener('touchstart', this.onTouchStart);
} };
render() { render() {
return this.getRenderComponent() return this.getRenderComponent();
} }
getRenderComponent = () => { getRenderComponent = () => {
@ -68,7 +68,7 @@ export default class LabellingManager extends Component {
editDescription, editDescription,
editDescriptionOnDialog, editDescriptionOnDialog,
measurementData, measurementData,
} = this.state } = this.state;
if (editDescriptionOnDialog) { if (editDescriptionOnDialog) {
return ( return (
@ -79,7 +79,7 @@ export default class LabellingManager extends Component {
componentStyle={this.state.componentStyle} componentStyle={this.state.componentStyle}
measurementData={measurementData} measurementData={measurementData}
/> />
) );
} }
if (editLocation || editDescription) { if (editLocation || editDescription) {
@ -88,43 +88,43 @@ export default class LabellingManager extends Component {
{...this.props} {...this.props}
componentStyle={this.state.componentStyle} componentStyle={this.state.componentStyle}
/> />
) );
} }
} };
treatMeasurementData = measurementData => { treatMeasurementData = measurementData => {
const { editDescription, editLocation } = this.props const { editDescription, editLocation } = this.props;
if (editDescription) { if (editDescription) {
measurementData.description = undefined measurementData.description = undefined;
} }
if (editLocation) { if (editLocation) {
measurementData.location = undefined measurementData.location = undefined;
} }
} };
responseDialogUpdate = response => { responseDialogUpdate = response => {
this.props.updateLabelling({ this.props.updateLabelling({
response, response,
}) });
this.props.labellingDoneCallback() this.props.labellingDoneCallback();
} };
descriptionDialogUpdate = description => { descriptionDialogUpdate = description => {
this.props.updateLabelling({ this.props.updateLabelling({
description, description,
}) });
this.props.labellingDoneCallback() this.props.labellingDoneCallback();
} };
} }
function getComponentPosition(eventData) { function getComponentPosition(eventData) {
const { const {
event: { clientX: left, clientY: top }, event: { clientX: left, clientY: top },
} = eventData } = eventData;
return { return {
left, left,
top, top,
} };
} }

View File

@ -1,20 +1,20 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import { CSSTransition } from 'react-transition-group' import { CSSTransition } from 'react-transition-group';
import './LabellingTransition.css' import './LabellingTransition.css';
// If these variables changes, CSS must be updated // If these variables changes, CSS must be updated
const transitionDuration = 500 const transitionDuration = 500;
const transitionClassName = 'labelling' const transitionClassName = 'labelling';
const transitionOnAppear = true const transitionOnAppear = true;
export default class LabellingTransition extends Component { export default class LabellingTransition extends Component {
static propTypes = { static propTypes = {
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
displayComponent: PropTypes.bool.isRequired, displayComponent: PropTypes.bool.isRequired,
onTransitionExit: PropTypes.func.isRequired, onTransitionExit: PropTypes.func.isRequired,
} };
render() { render() {
return ( return (
<CSSTransition <CSSTransition
@ -26,6 +26,6 @@ export default class LabellingTransition extends Component {
> >
{this.props.children} {this.props.children}
</CSSTransition> </CSSTransition>
) );
} }
} }

View File

@ -27,13 +27,13 @@ const items = [
'Spleen', 'Spleen',
'Stomach', 'Stomach',
'Subcutaneous', 'Subcutaneous',
] ];
const OHIFLabellingData = items.map(item => { const OHIFLabellingData = items.map(item => {
return { return {
label: item, label: item,
value: item, value: item,
} };
}) });
export default OHIFLabellingData export default OHIFLabellingData;

View File

@ -1,53 +1,53 @@
import cornerstone from 'cornerstone-core' import cornerstone from 'cornerstone-core';
const buttonSize = { const buttonSize = {
width: 96, width: 96,
height: 28, height: 28,
} };
export function getAddLabelButtonStyle(measurementData, eventData) { export function getAddLabelButtonStyle(measurementData, eventData) {
const { start, end } = measurementData.handles const { start, end } = measurementData.handles;
const { client } = eventData.currentPoints const { client } = eventData.currentPoints;
const clientStart = cornerstone.pixelToCanvas(eventData.element, start) const clientStart = cornerstone.pixelToCanvas(eventData.element, start);
const clientEnd = cornerstone.pixelToCanvas(eventData.element, end) const clientEnd = cornerstone.pixelToCanvas(eventData.element, end);
const canvasOffSetLeft = client.x - clientStart.x const canvasOffSetLeft = client.x - clientStart.x;
const canvasOffSetTop = client.y - clientStart.y const canvasOffSetTop = client.y - clientStart.y;
const position = { const position = {
left: clientEnd.x + canvasOffSetLeft, left: clientEnd.x + canvasOffSetLeft,
top: clientEnd.y + canvasOffSetTop, top: clientEnd.y + canvasOffSetTop,
} };
if (start.y > end.y) { if (start.y > end.y) {
position.top -= buttonSize.height position.top -= buttonSize.height;
} }
if (start.x > end.x) { if (start.x > end.x) {
position.left -= buttonSize.width position.left -= buttonSize.width;
} }
return position return position;
} }
export function getDialogStyle(componentStyle) { export function getDialogStyle(componentStyle) {
const style = Object.assign({}, componentStyle) const style = Object.assign({}, componentStyle);
const dialogProps = { const dialogProps = {
width: 320, width: 320,
height: 230, height: 230,
} };
// Get max values to avoid position out of the screen // Get max values to avoid position out of the screen
const maxLeft = window.innerWidth - dialogProps.width const maxLeft = window.innerWidth - dialogProps.width;
const maxTop = window.innerHeight - dialogProps.height const maxTop = window.innerHeight - dialogProps.height;
// Positioning the dialog with its center on the click event // Positioning the dialog with its center on the click event
style.left -= dialogProps.width / 2 style.left -= dialogProps.width / 2;
style.top -= dialogProps.height / 2 style.top -= dialogProps.height / 2;
if (style.left > maxLeft) { if (style.left > maxLeft) {
style.left = maxLeft style.left = maxLeft;
} }
if (style.top > maxTop) { if (style.top > maxTop) {
style.top = maxTop style.top = maxTop;
} }
return style return style;
} }

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react';
import './OHIFLogo.css' import './OHIFLogo.css';
const Icons = `${window.config.routerBasename}/icons.svg`.replace('//', '/') const Icons = `${window.config.routerBasename}/icons.svg`.replace('//', '/');
function OHIFLogo() { function OHIFLogo() {
return ( return (
@ -16,7 +16,7 @@ function OHIFLogo() {
</svg> </svg>
<div className="header-logo-text">Open Health Imaging Foundation</div> <div className="header-logo-text">Open Health Imaging Foundation</div>
</a> </a>
) );
} }
export default OHIFLogo export default OHIFLogo;

View File

@ -1,14 +1,14 @@
import { Component } from 'react' import { Component } from 'react';
import React from 'react' import React from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import './SimpleDialog.css' import './SimpleDialog.css';
class SimpleDialog extends Component { class SimpleDialog extends Component {
static defaultProps = { static defaultProps = {
componentStyle: {}, componentStyle: {},
rootClass: '', rootClass: '',
} };
render() { render() {
return ( return (
@ -43,7 +43,7 @@ class SimpleDialog extends Component {
</div> </div>
</form> </form>
</div> </div>
) );
} }
} }
@ -51,6 +51,6 @@ SimpleDialog.propTypes = {
headerTitle: PropTypes.string.isRequired, headerTitle: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onConfirm: PropTypes.func.isRequired, onConfirm: PropTypes.func.isRequired,
} };
export default SimpleDialog export default SimpleDialog;

View File

@ -1,43 +1,42 @@
import { Component } from "react"; import { Component } from 'react';
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import OHIF from 'ohif-core'; import OHIF from 'ohif-core';
class StudyLoadingMonitor extends Component { class StudyLoadingMonitor extends Component {
static propTypes = { static propTypes = {
studies: PropTypes.array.isRequired, studies: PropTypes.array.isRequired,
setStudyLoadingProgress: PropTypes.func.isRequired, setStudyLoadingProgress: PropTypes.func.isRequired,
clearStudyLoadingProgress: PropTypes.func.isRequired, clearStudyLoadingProgress: PropTypes.func.isRequired,
};
componentDidMount() {
// TODO: This is pretty ugly. The thing is that the StudyLoadingListener
// needs to update the Redux store, but shouldn't know that it exists.
// I am therefore passing in some functions to update the store instead,
// but this should definitely be cleaned up somehow.
const options = {
_setProgressData: (progressId, progressData) => {
this.props.setStudyLoadingProgress(progressId, progressData);
},
_clearProgressById: progressId => {
this.props.clearStudyLoadingProgress(progressId);
},
}; };
componentDidMount() { const { StudyLoadingListener } = OHIF.classes;
// TODO: This is pretty ugly. The thing is that the StudyLoadingListener this.studyLoadingListener = StudyLoadingListener.getInstance(options);
// needs to update the Redux store, but shouldn't know that it exists. this.studyLoadingListener.clear();
// I am therefore passing in some functions to update the store instead, this.studyLoadingListener.addStudies(this.props.studies);
// but this should definitely be cleaned up somehow. }
const options = {
_setProgressData: (progressId, progressData) => {
this.props.setStudyLoadingProgress(progressId, progressData)
},
_clearProgressById: (progressId) => {
this.props.clearStudyLoadingProgress(progressId)
}
}
const { StudyLoadingListener } = OHIF.classes; render() {
this.studyLoadingListener = StudyLoadingListener.getInstance(options); return null;
this.studyLoadingListener.clear(); }
this.studyLoadingListener.addStudies(this.props.studies);
}
render() { componentWillUnmount() {
return null; // Destroy stack loading listeners when we close the viewer
} this.studyLoadingListener.clear();
}
componentWillUnmount() {
// Destroy stack loading listeners when we close the viewer
this.studyLoadingListener.clear();
}
} }
export default StudyLoadingMonitor; export default StudyLoadingMonitor;

View File

@ -1,30 +1,29 @@
import { Component } from "react"; import { Component } from 'react';
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import OHIF from 'ohif-core'; import OHIF from 'ohif-core';
const { StudyPrefetcher } = OHIF.classes; const { StudyPrefetcher } = OHIF.classes;
class StudyPrefetcherComponent extends Component { class StudyPrefetcherComponent extends Component {
static propTypes = { static propTypes = {
studies: PropTypes.array, studies: PropTypes.array,
}; };
componentDidMount() { componentDidMount() {
const { studies } = this.props; const { studies } = this.props;
this.studyPrefetcher = StudyPrefetcher.getInstance(); this.studyPrefetcher = StudyPrefetcher.getInstance();
this.studyPrefetcher.setStudies(studies); this.studyPrefetcher.setStudies(studies);
} }
render() { render() {
return null; return null;
} }
componentWillUnmount() { componentWillUnmount() {
// Stop prefetching when we close the viewer // Stop prefetching when we close the viewer
this.studyPrefetcher.destroy(); this.studyPrefetcher.destroy();
} }
} }
export default StudyPrefetcherComponent; export default StudyPrefetcherComponent;

View File

@ -1,37 +1,37 @@
import dicomParser from 'dicom-parser' import dicomParser from 'dicom-parser';
import cornerstone from 'cornerstone-core' import cornerstone from 'cornerstone-core';
import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
import version from './version.js' import version from './version.js';
window.info = { window.info = {
version, version,
homepage: `${process.env.PUBLIC_URL}`, homepage: `${process.env.PUBLIC_URL}`,
} };
// For debugging // For debugging
window.cornerstone = cornerstone window.cornerstone = cornerstone;
window.cornerstoneWADOImageLoader = cornerstoneWADOImageLoader window.cornerstoneWADOImageLoader = cornerstoneWADOImageLoader;
cornerstoneWADOImageLoader.external.cornerstone = cornerstone cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
cornerstoneWADOImageLoader.external.dicomParser = dicomParser cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
OHIF.user.getAccessToken = () => { OHIF.user.getAccessToken = () => {
// TODO: Get the Redux store from somewhere else // TODO: Get the Redux store from somewhere else
const state = window.store.getState() const state = window.store.getState();
if (!state.oidc || !state.oidc.user) { if (!state.oidc || !state.oidc.user) {
return return;
} }
return state.oidc.user.access_token return state.oidc.user.access_token;
} };
cornerstoneWADOImageLoader.configure({ cornerstoneWADOImageLoader.configure({
beforeSend: function(xhr) { beforeSend: function(xhr) {
const headers = OHIF.DICOMWeb.getAuthorizationHeader() const headers = OHIF.DICOMWeb.getAuthorizationHeader();
if (headers.Authorization) { if (headers.Authorization) {
xhr.setRequestHeader('Authorization', headers.Authorization) xhr.setRequestHeader('Authorization', headers.Authorization);
} }
}, },
}) });

View File

@ -2,15 +2,15 @@ import { connect } from 'react-redux';
import FlexboxLayout from './FlexboxLayout'; import FlexboxLayout from './FlexboxLayout';
const mapStateToProps = state => { const mapStateToProps = state => {
return { return {
leftSidebarOpen: state.ui.leftSidebarOpen, leftSidebarOpen: state.ui.leftSidebarOpen,
rightSidebarOpen: state.ui.rightSidebarOpen, rightSidebarOpen: state.ui.rightSidebarOpen,
}; };
}; };
const ConnectedFlexboxLayout = connect( const ConnectedFlexboxLayout = connect(
mapStateToProps, mapStateToProps,
null null
)(FlexboxLayout); )(FlexboxLayout);
export default ConnectedFlexboxLayout; export default ConnectedFlexboxLayout;

View File

@ -4,7 +4,7 @@ import { setUserPreferencesModalOpen } from '../redux/actions.js';
const mapStateToProps = state => { const mapStateToProps = state => {
return { return {
isOpen: state.ui.userPreferencesModalOpen isOpen: state.ui.userPreferencesModalOpen,
}; };
}; };
@ -12,7 +12,7 @@ const mapDispatchToProps = dispatch => {
return { return {
openUserPreferencesModal: () => { openUserPreferencesModal: () => {
dispatch(setUserPreferencesModalOpen(true)); dispatch(setUserPreferencesModalOpen(true));
} },
}; };
}; };

View File

@ -1,24 +1,24 @@
import { connect } from 'react-redux' import { connect } from 'react-redux';
import LabellingOverlay from './LabellingOverlay' import LabellingOverlay from './LabellingOverlay';
const mapStateToProps = state => { const mapStateToProps = state => {
if (!state.ui || !state.ui.labelling) { if (!state.ui || !state.ui.labelling) {
return { return {
visible: false, visible: false,
} };
} }
const labellingFlowData = state.ui.labelling const labellingFlowData = state.ui.labelling;
return { return {
visible: false, visible: false,
...labellingFlowData, ...labellingFlowData,
} };
} };
const ConnectedLabellingOverlay = connect( const ConnectedLabellingOverlay = connect(
mapStateToProps, mapStateToProps,
null null
)(LabellingOverlay) )(LabellingOverlay);
export default ConnectedLabellingOverlay export default ConnectedLabellingOverlay;

View File

@ -1,41 +1,41 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { LayoutButton } from 'react-viewerbase'; import { LayoutButton } from 'react-viewerbase';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
const { setLayout } = OHIF.redux.actions; const { setLayout } = OHIF.redux.actions;
const mapStateToProps = state => { const mapStateToProps = state => {
return { return {
currentLayout: state.viewports.layout, currentLayout: state.viewports.layout,
}; };
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
// TODO: Change if layout switched becomes more complex // TODO: Change if layout switched becomes more complex
onChange: selectedCell => { onChange: selectedCell => {
let viewports = []; let viewports = [];
const rows = selectedCell.row + 1; const rows = selectedCell.row + 1;
const columns = selectedCell.col + 1; const columns = selectedCell.col + 1;
const numViewports = rows * columns; const numViewports = rows * columns;
for (let i = 0; i < numViewports; i++) { for (let i = 0; i < numViewports; i++) {
viewports.push({ viewports.push({
height: `${100 / rows}%`, height: `${100 / rows}%`,
width: `${100 / columns}%` width: `${100 / columns}%`,
}); });
} }
const layout = { const layout = {
viewports viewports,
}; };
dispatch(setLayout(layout)) dispatch(setLayout(layout));
} },
}; };
}; };
const ConnectedLayoutButton = connect( const ConnectedLayoutButton = connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(LayoutButton); )(LayoutButton);
export default ConnectedLayoutButton; export default ConnectedLayoutButton;

View File

@ -27,7 +27,7 @@ const mapStateToProps = state => {
layout: state.viewports.layout, layout: state.viewports.layout,
activeViewportIndex: state.viewports.activeViewportIndex, activeViewportIndex: state.viewports.activeViewportIndex,
availablePlugins, availablePlugins,
defaultPlugin defaultPlugin,
}; };
}; };

View File

@ -1,41 +1,41 @@
import { connect } from 'react-redux' import { connect } from 'react-redux';
import { MeasurementTable } from 'react-viewerbase' import { MeasurementTable } from 'react-viewerbase';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
import moment from 'moment' import moment from 'moment';
import cornerstone from 'cornerstone-core' import cornerstone from 'cornerstone-core';
import jumpToRowItem from '../lib/jumpToRowItem.js' import jumpToRowItem from '../lib/jumpToRowItem.js';
import getMeasurementLocationCallback from '../lib/getMeasurementLocationCallback' import getMeasurementLocationCallback from '../lib/getMeasurementLocationCallback';
const { setViewportSpecificData } = OHIF.redux.actions const { setViewportSpecificData } = OHIF.redux.actions;
const { MeasurementApi } = OHIF.measurements const { MeasurementApi } = OHIF.measurements;
function groupBy(list, props) { function groupBy(list, props) {
return list.reduce((a, b) => { return list.reduce((a, b) => {
;(a[b[props]] = a[b[props]] || []).push(b) (a[b[props]] = a[b[props]] || []).push(b);
return a return a;
}, {}) }, {});
} }
function getAllTools() { function getAllTools() {
const config = OHIF.measurements.MeasurementApi.getConfiguration() const config = OHIF.measurements.MeasurementApi.getConfiguration();
let tools = [] let tools = [];
config.measurementTools.forEach( config.measurementTools.forEach(
toolGroup => (tools = tools.concat(toolGroup.childTools)) toolGroup => (tools = tools.concat(toolGroup.childTools))
) );
return tools return tools;
} }
function getMeasurementText(measurementData) { function getMeasurementText(measurementData) {
const { location, description } = measurementData const { location, description } = measurementData;
let text = '...' let text = '...';
if (location) { if (location) {
text = location text = location;
if (description) { if (description) {
text += `(${description})` text += `(${description})`;
} }
} }
return text return text;
} }
function getDataForEachMeasurementNumber( function getDataForEachMeasurementNumber(
@ -43,54 +43,54 @@ function getDataForEachMeasurementNumber(
timepoints, timepoints,
displayFunction displayFunction
) { ) {
const data = [] const data = [];
// on each measurement number we should get each measurement data by available timepoint // on each measurement number we should get each measurement data by available timepoint
measurementNumberList.forEach(measurement => { measurementNumberList.forEach(measurement => {
timepoints.forEach(timepoint => { timepoints.forEach(timepoint => {
const eachData = { const eachData = {
displayText: '...', displayText: '...',
} };
if (measurement.timepointId === timepoint.timepointId) { if (measurement.timepointId === timepoint.timepointId) {
eachData.displayText = displayFunction(measurement) eachData.displayText = displayFunction(measurement);
} }
data.push(eachData) data.push(eachData);
}) });
}) });
return data return data;
} }
function convertMeasurementsToTableData(toolCollections, timepoints) { function convertMeasurementsToTableData(toolCollections, timepoints) {
const config = OHIF.measurements.MeasurementApi.getConfiguration() const config = OHIF.measurements.MeasurementApi.getConfiguration();
const toolGroups = config.measurementTools const toolGroups = config.measurementTools;
const tools = getAllTools() const tools = getAllTools();
const tableMeasurements = toolGroups.map(toolGroup => { const tableMeasurements = toolGroups.map(toolGroup => {
return { return {
groupName: toolGroup.name, groupName: toolGroup.name,
groupId: toolGroup.id, groupId: toolGroup.id,
measurements: [], measurements: [],
} };
}) });
Object.keys(toolCollections).forEach(toolId => { Object.keys(toolCollections).forEach(toolId => {
const toolMeasurements = toolCollections[toolId] const toolMeasurements = toolCollections[toolId];
const tool = tools.find(tool => tool.id === toolId) const tool = tools.find(tool => tool.id === toolId);
const { displayFunction } = tool.options.measurementTable const { displayFunction } = tool.options.measurementTable;
// Group by measurementNumber so we can display then all in the same line // Group by measurementNumber so we can display then all in the same line
const groupedMeasurements = groupBy(toolMeasurements, 'measurementNumber') const groupedMeasurements = groupBy(toolMeasurements, 'measurementNumber');
Object.keys(groupedMeasurements).forEach(groupedMeasurementsIndex => { Object.keys(groupedMeasurements).forEach(groupedMeasurementsIndex => {
const measurementNumberList = const measurementNumberList =
groupedMeasurements[groupedMeasurementsIndex] groupedMeasurements[groupedMeasurementsIndex];
const measurementData = measurementNumberList[0] const measurementData = measurementNumberList[0];
const { const {
measurementNumber, measurementNumber,
lesionNamingNumber, lesionNamingNumber,
toolType, toolType,
} = measurementData } = measurementData;
const measurementId = measurementData._id const measurementId = measurementData._id;
//check if all measurements with same measurementNumber will have same LABEL //check if all measurements with same measurementNumber will have same LABEL
const tableMeasurement = { const tableMeasurement = {
@ -109,30 +109,30 @@ function convertMeasurementsToTableData(toolCollections, timepoints) {
timepoints, timepoints,
displayFunction displayFunction
), ),
} };
// find the group object for the tool // find the group object for the tool
const toolGroupMeasurements = tableMeasurements.find(group => { const toolGroupMeasurements = tableMeasurements.find(group => {
return group.groupId === tool.toolGroup return group.groupId === tool.toolGroup;
}) });
// inject the new measurement for this measurementNumer // inject the new measurement for this measurementNumer
toolGroupMeasurements.measurements.push(tableMeasurement) toolGroupMeasurements.measurements.push(tableMeasurement);
}) });
}) });
// Sort measurements by lesion naming number // Sort measurements by lesion naming number
tableMeasurements.forEach(tm => { tableMeasurements.forEach(tm => {
tm.measurements.sort((m1, m2) => tm.measurements.sort((m1, m2) =>
m1.lesionNamingNumber > m2.lesionNamingNumber ? 1 : -1 m1.lesionNamingNumber > m2.lesionNamingNumber ? 1 : -1
) );
}) });
return tableMeasurements return tableMeasurements;
} }
function convertTimepointsToTableData(timepoints) { function convertTimepointsToTableData(timepoints) {
if (!timepoints || !timepoints.length) { if (!timepoints || !timepoints.length) {
return [] return [];
} }
return [ return [
@ -140,11 +140,11 @@ function convertTimepointsToTableData(timepoints) {
label: 'Study date:', label: 'Study date:',
date: moment(timepoints[0].latestDate).format('DD-MMM-YY'), date: moment(timepoints[0].latestDate).format('DD-MMM-YY'),
}, },
] ];
} }
const mapStateToProps = state => { const mapStateToProps = state => {
const { timepoints, measurements } = state.timepointManager const { timepoints, measurements } = state.timepointManager;
return { return {
timepoints: convertTimepointsToTableData(timepoints), timepoints: convertTimepointsToTableData(timepoints),
measurementCollection: convertMeasurementsToTableData( measurementCollection: convertMeasurementsToTableData(
@ -153,22 +153,22 @@ const mapStateToProps = state => {
), ),
timepointManager: state.timepointManager, timepointManager: state.timepointManager,
viewports: state.viewports, viewports: state.viewports,
} };
} };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
dispatchRelabel: (event, measurementData, viewportsState) => { dispatchRelabel: (event, measurementData, viewportsState) => {
const activeViewportIndex = const activeViewportIndex =
(viewportsState && viewportsState.activeViewportIndex) || 0 (viewportsState && viewportsState.activeViewportIndex) || 0;
const enabledElements = cornerstone.getEnabledElements() const enabledElements = cornerstone.getEnabledElements();
if (!enabledElements || enabledElements.length <= activeViewportIndex) { if (!enabledElements || enabledElements.length <= activeViewportIndex) {
OHIF.log.error('Failed to find the enabled element') OHIF.log.error('Failed to find the enabled element');
return return;
} }
const { element } = enabledElements[activeViewportIndex] const { element } = enabledElements[activeViewportIndex];
const eventData = { const eventData = {
event: { event: {
@ -176,33 +176,33 @@ const mapDispatchToProps = dispatch => {
clientY: event.clientY, clientY: event.clientY,
}, },
element, element,
} };
const { toolType, measurementId } = measurementData const { toolType, measurementId } = measurementData;
const tool = MeasurementApi.Instance.tools[toolType].find(measurement => { const tool = MeasurementApi.Instance.tools[toolType].find(measurement => {
return measurement._id === measurementId return measurement._id === measurementId;
}) });
const options = { const options = {
skipAddLabelButton: true, skipAddLabelButton: true,
editLocation: true, editLocation: true,
} };
// Clone the tool not to set empty location initially // Clone the tool not to set empty location initially
const toolForLocation = Object.assign({}, tool, { location: null }) const toolForLocation = Object.assign({}, tool, { location: null });
getMeasurementLocationCallback(eventData, toolForLocation, options) getMeasurementLocationCallback(eventData, toolForLocation, options);
}, },
dispatchEditDescription: (event, measurementData, viewportsState) => { dispatchEditDescription: (event, measurementData, viewportsState) => {
const activeViewportIndex = const activeViewportIndex =
(viewportsState && viewportsState.activeViewportIndex) || 0 (viewportsState && viewportsState.activeViewportIndex) || 0;
const enabledElements = cornerstone.getEnabledElements() const enabledElements = cornerstone.getEnabledElements();
if (!enabledElements || enabledElements.length <= activeViewportIndex) { if (!enabledElements || enabledElements.length <= activeViewportIndex) {
OHIF.log.error('Failed to find the enabled element') OHIF.log.error('Failed to find the enabled element');
return return;
} }
const { element } = enabledElements[activeViewportIndex] const { element } = enabledElements[activeViewportIndex];
const eventData = { const eventData = {
event: { event: {
@ -210,18 +210,18 @@ const mapDispatchToProps = dispatch => {
clientY: event.clientY, clientY: event.clientY,
}, },
element, element,
} };
const { toolType, measurementId } = measurementData const { toolType, measurementId } = measurementData;
const tool = MeasurementApi.Instance.tools[toolType].find(measurement => { const tool = MeasurementApi.Instance.tools[toolType].find(measurement => {
return measurement._id === measurementId return measurement._id === measurementId;
}) });
const options = { const options = {
editDescriptionOnDialog: true, editDescriptionOnDialog: true,
} };
getMeasurementLocationCallback(eventData, tool, options) getMeasurementLocationCallback(eventData, tool, options);
}, },
dispatchJumpToRowItem: ( dispatchJumpToRowItem: (
measurementData, measurementData,
@ -235,40 +235,40 @@ const mapDispatchToProps = dispatch => {
timepointManagerState, timepointManagerState,
dispatch, dispatch,
options options
) );
actionData.viewportSpecificData.forEach(viewportSpecificData => { actionData.viewportSpecificData.forEach(viewportSpecificData => {
const { viewportIndex, displaySet } = viewportSpecificData const { viewportIndex, displaySet } = viewportSpecificData;
dispatch(setViewportSpecificData(viewportIndex, displaySet)) dispatch(setViewportSpecificData(viewportIndex, displaySet));
}) });
const { toolType, measurementNumber } = measurementData const { toolType, measurementNumber } = measurementData;
const measurementApi = MeasurementApi.Instance const measurementApi = MeasurementApi.Instance;
Object.keys(measurementApi.tools).forEach(toolType => { Object.keys(measurementApi.tools).forEach(toolType => {
const measurements = measurementApi.tools[toolType] const measurements = measurementApi.tools[toolType];
measurements.forEach(measurement => { measurements.forEach(measurement => {
measurement.active = false measurement.active = false;
}) });
}) });
const measurementsToActive = measurementApi.tools[toolType].filter( const measurementsToActive = measurementApi.tools[toolType].filter(
measurement => { measurement => {
return measurement.measurementNumber === measurementNumber return measurement.measurementNumber === measurementNumber;
} }
) );
measurementsToActive.forEach(measurementToActive => { measurementsToActive.forEach(measurementToActive => {
measurementToActive.active = true measurementToActive.active = true;
}) });
measurementApi.syncMeasurementsAndToolData() measurementApi.syncMeasurementsAndToolData();
cornerstone.getEnabledElements().forEach(enabledElement => { cornerstone.getEnabledElements().forEach(enabledElement => {
cornerstone.updateImage(enabledElement.element) cornerstone.updateImage(enabledElement.element);
}) });
// Needs to update viewports.layout state to set layout // Needs to update viewports.layout state to set layout
//const layout = actionData.layout; //const layout = actionData.layout;
@ -284,8 +284,8 @@ const mapDispatchToProps = dispatch => {
// (later): Needs to set some property on state.extensions.cornerstone to synchronize viewport scrolling // (later): Needs to set some property on state.extensions.cornerstone to synchronize viewport scrolling
}, },
} };
} };
const mergeProps = (propsFromState, propsFromDispatch, ownProps) => { const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
return { return {
@ -298,37 +298,37 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
// TODO: Tooltype should be on the level below? This should // TODO: Tooltype should be on the level below? This should
// provide the entire row item? // provide the entire row item?
const viewportsState = propsFromState.viewports const viewportsState = propsFromState.viewports;
const timepointManagerState = propsFromState.timepointManager const timepointManagerState = propsFromState.timepointManager;
// TODO: invertViewportTimepointsOrder should be stored in / read from user preferences // TODO: invertViewportTimepointsOrder should be stored in / read from user preferences
// TODO: childToolKey should come from the measurement table when it supports child tools // TODO: childToolKey should come from the measurement table when it supports child tools
const options = { const options = {
invertViewportTimepointsOrder: false, invertViewportTimepointsOrder: false,
childToolKey: null, childToolKey: null,
} };
propsFromDispatch.dispatchJumpToRowItem( propsFromDispatch.dispatchJumpToRowItem(
measurementData, measurementData,
viewportsState, viewportsState,
timepointManagerState, timepointManagerState,
options options
) );
}, },
onRelabelClick: (event, measurementData) => { onRelabelClick: (event, measurementData) => {
const viewportsState = propsFromState.viewports const viewportsState = propsFromState.viewports;
propsFromDispatch.dispatchRelabel(event, measurementData, viewportsState) propsFromDispatch.dispatchRelabel(event, measurementData, viewportsState);
}, },
onEditDescriptionClick: (event, measurementData) => { onEditDescriptionClick: (event, measurementData) => {
const viewportsState = propsFromState.viewports const viewportsState = propsFromState.viewports;
propsFromDispatch.dispatchEditDescription( propsFromDispatch.dispatchEditDescription(
event, event,
measurementData, measurementData,
viewportsState viewportsState
) );
}, },
onDeleteClick: (event, measurementData) => { onDeleteClick: (event, measurementData) => {
const { MeasurementHandlers } = OHIF.measurements const { MeasurementHandlers } = OHIF.measurements;
MeasurementHandlers.onRemoved({ MeasurementHandlers.onRemoved({
detail: { detail: {
@ -339,15 +339,15 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
measurementNumber: measurementData.measurementNumber, measurementNumber: measurementData.measurementNumber,
}, },
}, },
}) });
}, },
} };
} };
const ConnectedMeasurementTable = connect( const ConnectedMeasurementTable = connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps, mapDispatchToProps,
mergeProps mergeProps
)(MeasurementTable) )(MeasurementTable);
export default ConnectedMeasurementTable export default ConnectedMeasurementTable;

View File

@ -1,42 +1,42 @@
import { connect } from 'react-redux' import { connect } from 'react-redux';
import PluginSwitch from './PluginSwitch.js' import PluginSwitch from './PluginSwitch.js';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
const { setLayout } = OHIF.redux.actions const { setLayout } = OHIF.redux.actions;
const mapStateToProps = state => { const mapStateToProps = state => {
const { activeViewportIndex, layout } = state.viewports const { activeViewportIndex, layout } = state.viewports;
return { return {
activeViewportIndex, activeViewportIndex,
layout, layout,
} };
} };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
setLayout: data => { setLayout: data => {
dispatch(setLayout(data)) dispatch(setLayout(data));
}, },
} };
} };
function setSingleLayoutData(originalArray, viewportIndex, data) { function setSingleLayoutData(originalArray, viewportIndex, data) {
const viewports = originalArray.slice() const viewports = originalArray.slice();
const layoutData = Object.assign({}, viewports[viewportIndex], data) const layoutData = Object.assign({}, viewports[viewportIndex], data);
viewports[viewportIndex] = layoutData viewports[viewportIndex] = layoutData;
return viewports return viewports;
} }
const mergeProps = (propsFromState, propsFromDispatch, ownProps) => { const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
const { activeViewportIndex, layout } = propsFromState const { activeViewportIndex, layout } = propsFromState;
const { setLayout } = propsFromDispatch const { setLayout } = propsFromDispatch;
// TODO: Do not display certain options if the current display set // TODO: Do not display certain options if the current display set
// cannot be displayed using these view types // cannot be displayed using these view types
const Icons = `${window.config.routerBasename}/icons.svg`.replace('//', '/') const Icons = `${window.config.routerBasename}/icons.svg`.replace('//', '/');
const buttons = [ const buttons = [
{ {
text: 'Acquired', text: 'Acquired',
@ -44,15 +44,15 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
iconClasses: 'fa fa-bars', iconClasses: 'fa fa-bars',
active: false, active: false,
onClick: click => { onClick: click => {
console.warn('Original Acquisition') console.warn('Original Acquisition');
const layoutData = setSingleLayoutData( const layoutData = setSingleLayoutData(
layout.viewports, layout.viewports,
activeViewportIndex, activeViewportIndex,
{ plugin: 'cornerstone' } { plugin: 'cornerstone' }
) );
setLayout({ viewports: layoutData }) setLayout({ viewports: layoutData });
}, },
}, },
{ {
@ -61,22 +61,22 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
svgClasses: 'icon-rotate-120', svgClasses: 'icon-rotate-120',
active: false, active: false,
onClick: click => { onClick: click => {
console.warn('Axial') console.warn('Axial');
const data = { const data = {
plugin: 'vtk', plugin: 'vtk',
vtk: { vtk: {
mode: 'mpr', mode: 'mpr',
sliceNormal: [0, 0, 1], sliceNormal: [0, 0, 1],
}, },
} };
const layoutData = setSingleLayoutData( const layoutData = setSingleLayoutData(
layout.viewports, layout.viewports,
activeViewportIndex, activeViewportIndex,
data data
) );
setLayout({ viewports: layoutData }) setLayout({ viewports: layoutData });
}, },
}, },
{ {
@ -84,22 +84,22 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
svgUrl: `${Icons}#cube`, svgUrl: `${Icons}#cube`,
active: false, active: false,
onClick: click => { onClick: click => {
console.warn('Sagittal') console.warn('Sagittal');
const data = { const data = {
plugin: 'vtk', plugin: 'vtk',
vtk: { vtk: {
mode: 'mpr', mode: 'mpr',
sliceNormal: [1, 0, 0], sliceNormal: [1, 0, 0],
}, },
} };
const layoutData = setSingleLayoutData( const layoutData = setSingleLayoutData(
layout.viewports, layout.viewports,
activeViewportIndex, activeViewportIndex,
data data
) );
setLayout({ viewports: layoutData }) setLayout({ viewports: layoutData });
}, },
}, },
{ {
@ -108,22 +108,22 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
svgClasses: 'fa-rotate-90 fa-flip-horizontal', svgClasses: 'fa-rotate-90 fa-flip-horizontal',
active: false, active: false,
onClick: click => { onClick: click => {
console.warn('Coronal') console.warn('Coronal');
const data = { const data = {
plugin: 'vtk', plugin: 'vtk',
vtk: { vtk: {
mode: 'mpr', mode: 'mpr',
sliceNormal: [0, 1, 0], sliceNormal: [0, 1, 0],
}, },
} };
const layoutData = setSingleLayoutData( const layoutData = setSingleLayoutData(
layout.viewports, layout.viewports,
activeViewportIndex, activeViewportIndex,
data data
) );
setLayout({ viewports: layoutData }) setLayout({ viewports: layoutData });
}, },
}, },
/*{ /*{
@ -143,17 +143,17 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
setLayout({ viewports: layoutData }); setLayout({ viewports: layoutData });
} }
}*/ }*/
] ];
return { return {
buttons, buttons,
} };
} };
const ConnectedPluginSwitch = connect( const ConnectedPluginSwitch = connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps, mapDispatchToProps,
mergeProps mergeProps
)(PluginSwitch) )(PluginSwitch);
export default ConnectedPluginSwitch export default ConnectedPluginSwitch;

View File

@ -6,35 +6,35 @@ import cloneDeep from 'lodash.clonedeep';
// - Determine in which display set is active from Redux (activeViewportIndex and layout viewportData) // - Determine in which display set is active from Redux (activeViewportIndex and layout viewportData)
// - Pass in errors and stack loading progress from Redux // - Pass in errors and stack loading progress from Redux
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
// If we know that the stack loading progress details have changed, // If we know that the stack loading progress details have changed,
// we can try to update the component state so that the thumbnail // we can try to update the component state so that the thumbnail
// progress bar is updated // progress bar is updated
const stackLoadingProgressMap = state.loading.progress; const stackLoadingProgressMap = state.loading.progress;
const studiesWithLoadingData = cloneDeep(ownProps.studies); const studiesWithLoadingData = cloneDeep(ownProps.studies);
studiesWithLoadingData.forEach(study => { studiesWithLoadingData.forEach(study => {
study.thumbnails.forEach(data => { study.thumbnails.forEach(data => {
const { displaySetInstanceUid } = data const { displaySetInstanceUid } = data;
const stackId = `StackProgress:${displaySetInstanceUid}`; const stackId = `StackProgress:${displaySetInstanceUid}`;
const stackProgressData = stackLoadingProgressMap[stackId]; const stackProgressData = stackLoadingProgressMap[stackId];
let stackPercentComplete = 0; let stackPercentComplete = 0;
if (stackProgressData) { if (stackProgressData) {
stackPercentComplete = stackProgressData.percentComplete; stackPercentComplete = stackProgressData.percentComplete;
} }
data.stackPercentComplete = stackPercentComplete; data.stackPercentComplete = stackPercentComplete;
})
}); });
});
return { return {
studies: studiesWithLoadingData studies: studiesWithLoadingData,
}; };
}; };
const ConnectedStudyBrowser = connect( const ConnectedStudyBrowser = connect(
mapStateToProps, mapStateToProps,
null null
)(StudyBrowser); )(StudyBrowser);
export default ConnectedStudyBrowser; export default ConnectedStudyBrowser;

View File

@ -1,23 +1,26 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import StudyLoadingMonitor from '../components/StudyLoadingMonitor.js'; import StudyLoadingMonitor from '../components/StudyLoadingMonitor.js';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
const { setStudyLoadingProgress, clearStudyLoadingProgress } = OHIF.redux.actions; const {
setStudyLoadingProgress,
clearStudyLoadingProgress,
} = OHIF.redux.actions;
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
setStudyLoadingProgress: (progressId, progressData) => { setStudyLoadingProgress: (progressId, progressData) => {
dispatch(setStudyLoadingProgress(progressId, progressData)) dispatch(setStudyLoadingProgress(progressId, progressData));
}, },
clearStudyLoadingProgress: progressId => { clearStudyLoadingProgress: progressId => {
dispatch(clearStudyLoadingProgress(progressId)) dispatch(clearStudyLoadingProgress(progressId));
} },
}; };
}; };
const ConnectedStudyLoadingMonitor = connect( const ConnectedStudyLoadingMonitor = connect(
null, null,
mapDispatchToProps mapDispatchToProps
)(StudyLoadingMonitor); )(StudyLoadingMonitor);
export default ConnectedStudyLoadingMonitor; export default ConnectedStudyLoadingMonitor;

View File

@ -1,34 +1,34 @@
import { connect } from 'react-redux' import { connect } from 'react-redux';
import ToolContextMenu from './ToolContextMenu' import ToolContextMenu from './ToolContextMenu';
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
if (!state.ui || !state.ui.contextMenu) { if (!state.ui || !state.ui.contextMenu) {
return { return {
visible: false, visible: false,
} };
} }
const { viewportIndex } = ownProps const { viewportIndex } = ownProps;
const toolContextMenuData = state.ui.contextMenu[viewportIndex] const toolContextMenuData = state.ui.contextMenu[viewportIndex];
let availableTools let availableTools;
if ( if (
state.extensions && state.extensions &&
state.extensions.cornerstone && state.extensions.cornerstone &&
state.extensions.cornerstone.availableTools state.extensions.cornerstone.availableTools
) { ) {
availableTools = state.extensions.cornerstone.availableTools availableTools = state.extensions.cornerstone.availableTools;
} }
return { return {
...toolContextMenuData, ...toolContextMenuData,
availableTools, availableTools,
} };
} };
const ConnectedToolContextMenu = connect( const ConnectedToolContextMenu = connect(
mapStateToProps, mapStateToProps,
null null
)(ToolContextMenu) )(ToolContextMenu);
export default ConnectedToolContextMenu export default ConnectedToolContextMenu;

View File

@ -5,34 +5,38 @@ import { setLeftSidebarOpen, setRightSidebarOpen } from '../redux/actions.js';
const defaultPlugin = 'cornerstone'; const defaultPlugin = 'cornerstone';
const mapStateToProps = state => { const mapStateToProps = state => {
const { layout, viewportSpecificData, activeViewportIndex } = state.viewports; const { layout, viewportSpecificData, activeViewportIndex } = state.viewports;
const pluginInLayout = layout.viewports[activeViewportIndex] && layout.viewports[activeViewportIndex].plugin; const pluginInLayout =
const pluginInViewportData = viewportSpecificData[activeViewportIndex] && viewportSpecificData[activeViewportIndex].plugin; layout.viewports[activeViewportIndex] &&
const pluginInActiveViewport = pluginInLayout || pluginInViewportData || defaultPlugin; layout.viewports[activeViewportIndex].plugin;
// const extensionData = state.extensions[pluginInActiveViewport]; const pluginInViewportData =
viewportSpecificData[activeViewportIndex] &&
viewportSpecificData[activeViewportIndex].plugin;
const pluginInActiveViewport =
pluginInLayout || pluginInViewportData || defaultPlugin;
// const extensionData = state.extensions[pluginInActiveViewport];
return { return {
pluginId: pluginInActiveViewport, pluginId: pluginInActiveViewport,
leftSidebarOpen: state.ui.leftSidebarOpen, leftSidebarOpen: state.ui.leftSidebarOpen,
rightSidebarOpen: state.ui.rightSidebarOpen rightSidebarOpen: state.ui.rightSidebarOpen,
}; };
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
setLeftSidebarOpen: state => { setLeftSidebarOpen: state => {
dispatch(setLeftSidebarOpen(state)) dispatch(setLeftSidebarOpen(state));
}, },
setRightSidebarOpen: state => { setRightSidebarOpen: state => {
dispatch(setRightSidebarOpen(state)) dispatch(setRightSidebarOpen(state));
} },
}; };
}; };
const ConnectedToolbarRow = connect( const ConnectedToolbarRow = connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(ToolbarRow); )(ToolbarRow);
export default ConnectedToolbarRow; export default ConnectedToolbarRow;

View File

@ -1,29 +1,29 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { ToolbarSection } from 'react-viewerbase'; import { ToolbarSection } from 'react-viewerbase';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
const { setToolActive } = OHIF.redux.actions; const { setToolActive } = OHIF.redux.actions;
const mapStateToProps = state => { const mapStateToProps = state => {
const activeButton = state.tools.buttons.find(tool => tool.active === true); const activeButton = state.tools.buttons.find(tool => tool.active === true);
return { return {
buttons: state.tools.buttons, buttons: state.tools.buttons,
activeCommand: activeButton && activeButton.command activeCommand: activeButton && activeButton.command,
}; };
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
setToolActive: tool => { setToolActive: tool => {
dispatch(setToolActive(tool.command)) dispatch(setToolActive(tool.command));
} },
}; };
}; };
const ConnectedToolbarSection = connect( const ConnectedToolbarSection = connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(ToolbarSection); )(ToolbarSection);
export default ConnectedToolbarSection; export default ConnectedToolbarSection;

View File

@ -15,7 +15,7 @@ const mapStateToProps = state => {
: {}, : {},
hotKeysData: state.preferences[contextName] hotKeysData: state.preferences[contextName]
? state.preferences[contextName].hotKeysData ? state.preferences[contextName].hotKeysData
: {} : {},
}; };
}; };
@ -36,7 +36,7 @@ const mapDispatchToProps = dispatch => {
dispatch(setUserPreferences()); dispatch(setUserPreferences());
dispatch(setUserPreferencesModalOpen(false)); dispatch(setUserPreferencesModalOpen(false));
OHIF.hotkeysUtil.setHotkeys(); OHIF.hotkeysUtil.setHotkeys();
} },
}; };
}; };

View File

@ -11,7 +11,7 @@ const mapDispatchToProps = dispatch => {
}, },
onMeasurementsUpdated: measurements => { onMeasurementsUpdated: measurements => {
dispatch(setMeasurements(measurements)); dispatch(setMeasurements(measurements));
} },
}; };
}; };

View File

@ -1,44 +1,44 @@
import { connect } from 'react-redux' import { connect } from 'react-redux';
import ViewerMain from './ViewerMain' import ViewerMain from './ViewerMain';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
const { const {
setViewportSpecificData, setViewportSpecificData,
clearViewportSpecificData, clearViewportSpecificData,
setToolActive, setToolActive,
setActiveViewportSpecificData, setActiveViewportSpecificData,
} = OHIF.redux.actions } = OHIF.redux.actions;
const mapStateToProps = state => { const mapStateToProps = state => {
const { activeViewportIndex, layout, viewportSpecificData } = state.viewports const { activeViewportIndex, layout, viewportSpecificData } = state.viewports;
return { return {
activeViewportIndex, activeViewportIndex,
layout, layout,
viewportSpecificData, viewportSpecificData,
} };
} };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
setViewportSpecificData: (viewportIndex, data) => { setViewportSpecificData: (viewportIndex, data) => {
dispatch(setViewportSpecificData(viewportIndex, data)) dispatch(setViewportSpecificData(viewportIndex, data));
}, },
clearViewportSpecificData: () => { clearViewportSpecificData: () => {
dispatch(clearViewportSpecificData()) dispatch(clearViewportSpecificData());
}, },
setToolActive: tool => { setToolActive: tool => {
dispatch(setToolActive(tool)) dispatch(setToolActive(tool));
}, },
setActiveViewportSpecificData: viewport => { setActiveViewportSpecificData: viewport => {
dispatch(setActiveViewportSpecificData(viewport)) dispatch(setActiveViewportSpecificData(viewport));
}, },
} };
} };
const ConnectedViewerMain = connect( const ConnectedViewerMain = connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(ViewerMain) )(ViewerMain);
export default ConnectedViewerMain export default ConnectedViewerMain;

View File

@ -1,19 +1,19 @@
import { connect } from 'react-redux' import { connect } from 'react-redux';
import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js' import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js';
const isActive = a => a.active === true const isActive = a => a.active === true;
const mapStateToProps = state => { const mapStateToProps = state => {
const activeServer = state.servers.servers.find(isActive) const activeServer = state.servers.servers.find(isActive);
return { return {
server: activeServer, server: activeServer,
} };
} };
const ConnectedViewerRetrieveStudyData = connect( const ConnectedViewerRetrieveStudyData = connect(
mapStateToProps, mapStateToProps,
null null
)(ViewerRetrieveStudyData) )(ViewerRetrieveStudyData);
export default ConnectedViewerRetrieveStudyData export default ConnectedViewerRetrieveStudyData;

View File

@ -1,38 +1,38 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js' import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
import ConnectedViewerMain from './ConnectedViewerMain.js' import ConnectedViewerMain from './ConnectedViewerMain.js';
import ConnectedMeasurementTable from './ConnectedMeasurementTable' import ConnectedMeasurementTable from './ConnectedMeasurementTable';
import './FlexboxLayout.css' import './FlexboxLayout.css';
class FlexboxLayout extends Component { class FlexboxLayout extends Component {
static propTypes = { static propTypes = {
studies: PropTypes.array.isRequired, studies: PropTypes.array.isRequired,
leftSidebarOpen: PropTypes.bool.isRequired, leftSidebarOpen: PropTypes.bool.isRequired,
rightSidebarOpen: PropTypes.bool.isRequired, rightSidebarOpen: PropTypes.bool.isRequired,
} };
state = { state = {
studiesForBrowser: [], studiesForBrowser: [],
} };
componentDidMount() { componentDidMount() {
const studiesForBrowser = this.getStudiesForBrowser() const studiesForBrowser = this.getStudiesForBrowser();
this.setState({ this.setState({
studiesForBrowser, studiesForBrowser,
}) });
} }
getStudiesForBrowser = () => { getStudiesForBrowser = () => {
const { studies } = this.props const { studies } = this.props;
// TODO[react]: // TODO[react]:
// - Add sorting of display sets // - Add sorting of display sets
// - Add useMiddleSeriesInstanceAsThumbnail // - Add useMiddleSeriesInstanceAsThumbnail
// - Add showStackLoadingProgressBar option // - Add showStackLoadingProgressBar option
return studies.map(study => { return studies.map(study => {
const { studyInstanceUid } = study const { studyInstanceUid } = study;
const thumbnails = study.displaySets.map(displaySet => { const thumbnails = study.displaySets.map(displaySet => {
const { const {
@ -41,12 +41,12 @@ class FlexboxLayout extends Component {
seriesNumber, seriesNumber,
instanceNumber, instanceNumber,
numImageFrames, numImageFrames,
} = displaySet } = displaySet;
let imageId let imageId;
if (displaySet.images && displaySet.images.length) { if (displaySet.images && displaySet.images.length) {
imageId = displaySet.images[0].getImageId() imageId = displaySet.images[0].getImageId();
} }
return { return {
@ -56,24 +56,24 @@ class FlexboxLayout extends Component {
seriesNumber, seriesNumber,
instanceNumber, instanceNumber,
numImageFrames, numImageFrames,
} };
}) });
return { return {
studyInstanceUid, studyInstanceUid,
thumbnails, thumbnails,
} };
}) });
} };
render() { render() {
let mainContentClassName = 'main-content' let mainContentClassName = 'main-content';
if (this.props.leftSidebarOpen) { if (this.props.leftSidebarOpen) {
mainContentClassName += ' sidebar-left-open' mainContentClassName += ' sidebar-left-open';
} }
if (this.props.rightSidebarOpen) { if (this.props.rightSidebarOpen) {
mainContentClassName += ' sidebar-right-open' mainContentClassName += ' sidebar-right-open';
} }
// TODO[react]: Make ConnectedMeasurementTable extension with state.timepointManager // TODO[react]: Make ConnectedMeasurementTable extension with state.timepointManager
@ -101,8 +101,8 @@ class FlexboxLayout extends Component {
<ConnectedMeasurementTable /> <ConnectedMeasurementTable />
</div> </div>
</div> </div>
) );
} }
} }
export default FlexboxLayout export default FlexboxLayout;

View File

@ -1,23 +1,23 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import LabellingManager from '../components/Labelling/LabellingManager' import LabellingManager from '../components/Labelling/LabellingManager';
class LabellingOverlay extends Component { class LabellingOverlay extends Component {
static propTypes = { static propTypes = {
visible: PropTypes.bool.isRequired, visible: PropTypes.bool.isRequired,
} };
static defaultProps = { static defaultProps = {
visible: false, visible: false,
} };
render() { render() {
if (!this.props.visible) { if (!this.props.visible) {
return null return null;
} }
return <LabellingManager {...this.props} /> return <LabellingManager {...this.props} />;
} }
} }
export default LabellingOverlay export default LabellingOverlay;

View File

@ -5,7 +5,7 @@ import './PluginSwitch.css';
class PluginSwitch extends Component { class PluginSwitch extends Component {
static propTypes = { static propTypes = {
buttons: PropTypes.array buttons: PropTypes.array,
}; };
static defaultProps = {}; static defaultProps = {};

View File

@ -1,10 +1,10 @@
import React, { Component } from 'react' import React, { Component } 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 cornerstoneTools from 'cornerstone-tools';
import getMeasurementLocationCallback from '../lib/getMeasurementLocationCallback' import getMeasurementLocationCallback from '../lib/getMeasurementLocationCallback';
import './ToolContextMenu.css' import './ToolContextMenu.css';
const toolTypes = [ const toolTypes = [
'Angle', 'Angle',
@ -14,87 +14,87 @@ const toolTypes = [
'EllipticalRoi', 'EllipticalRoi',
'CircleRoi', 'CircleRoi',
'RectangleRoi', 'RectangleRoi',
] ];
let defaultDropdownItems = [ let defaultDropdownItems = [
{ {
actionType: 'Delete', actionType: 'Delete',
action: ({ nearbyToolData, eventData }) => { action: ({ nearbyToolData, eventData }) => {
const element = eventData.element const element = eventData.element;
cornerstoneTools.removeToolState( cornerstoneTools.removeToolState(
element, element,
nearbyToolData.toolType, nearbyToolData.toolType,
nearbyToolData.tool nearbyToolData.tool
) );
cornerstone.updateImage(element) cornerstone.updateImage(element);
}, },
}, },
{ {
actionType: 'setLabel', actionType: 'setLabel',
action: ({ nearbyToolData, eventData }) => { action: ({ nearbyToolData, eventData }) => {
const { tool } = nearbyToolData const { tool } = nearbyToolData;
const options = { const options = {
skipAddLabelButton: true, skipAddLabelButton: true,
editLocation: true, editLocation: true,
} };
getMeasurementLocationCallback(eventData, tool, options) getMeasurementLocationCallback(eventData, tool, options);
}, },
}, },
{ {
actionType: 'setDescription', actionType: 'setDescription',
action: ({ nearbyToolData, eventData }) => { action: ({ nearbyToolData, eventData }) => {
const { tool } = nearbyToolData const { tool } = nearbyToolData;
const options = { const options = {
editDescriptionOnDialog: true, editDescriptionOnDialog: true,
} };
getMeasurementLocationCallback(eventData, tool, options) getMeasurementLocationCallback(eventData, tool, options);
}, },
}, },
] ];
function getNearbyToolData(element, coords, toolTypes) { function getNearbyToolData(element, coords, toolTypes) {
const nearbyTool = {} const nearbyTool = {};
let pointNearTool = false let pointNearTool = false;
toolTypes.forEach(toolType => { toolTypes.forEach(toolType => {
const toolData = cornerstoneTools.getToolState(element, toolType) const toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) { if (!toolData) {
return return;
} }
toolData.data.forEach(function(data, index) { toolData.data.forEach(function(data, index) {
// TODO: Fix this, it's ugly // TODO: Fix this, it's ugly
let toolInterface = cornerstoneTools.getToolForElement(element, toolType) let toolInterface = cornerstoneTools.getToolForElement(element, toolType);
if (!toolInterface) { if (!toolInterface) {
toolInterface = cornerstoneTools.getToolForElement( toolInterface = cornerstoneTools.getToolForElement(
element, element,
`${toolType}Tool` `${toolType}Tool`
) );
} }
if (!toolInterface) { if (!toolInterface) {
throw new Error('Tool not found.') throw new Error('Tool not found.');
} }
if (toolInterface.pointNearTool(element, data, coords)) { if (toolInterface.pointNearTool(element, data, coords)) {
pointNearTool = true pointNearTool = true;
nearbyTool.tool = data nearbyTool.tool = data;
nearbyTool.index = index nearbyTool.index = index;
nearbyTool.toolType = toolType nearbyTool.toolType = toolType;
} }
}) });
if (pointNearTool) { if (pointNearTool) {
return false return false;
} }
}) });
return pointNearTool ? nearbyTool : undefined return pointNearTool ? nearbyTool : undefined;
} }
function getDropdownItems(eventData, isTouchEvent = false, availableTools) { function getDropdownItems(eventData, isTouchEvent = false, availableTools) {
@ -103,7 +103,7 @@ function getDropdownItems(eventData, isTouchEvent = false, availableTools) {
eventData.currentPoints.canvas, eventData.currentPoints.canvas,
toolTypes, toolTypes,
availableTools availableTools
) );
// Annotate tools for touch events already have a press handle to edit it, has a better UX for deleting it // Annotate tools for touch events already have a press handle to edit it, has a better UX for deleting it
if ( if (
@ -111,36 +111,36 @@ function getDropdownItems(eventData, isTouchEvent = false, availableTools) {
nearbyToolData && nearbyToolData &&
nearbyToolData.toolType === 'arrowAnnotate' nearbyToolData.toolType === 'arrowAnnotate'
) { ) {
return return;
} }
let dropdownItems = [] let dropdownItems = [];
if (nearbyToolData) { if (nearbyToolData) {
defaultDropdownItems.forEach(function(item) { defaultDropdownItems.forEach(function(item) {
item.params = { item.params = {
eventData, eventData,
nearbyToolData, nearbyToolData,
} };
if (item.actionType === 'Delete') { if (item.actionType === 'Delete') {
item.text = 'Delete measurement' item.text = 'Delete measurement';
} }
if (item.actionType === 'setLabel') { if (item.actionType === 'setLabel') {
item.text = 'Relabel' item.text = 'Relabel';
} }
if (item.actionType === 'setDescription') { if (item.actionType === 'setDescription') {
item.text = `${ item.text = `${
nearbyToolData.tool.description ? 'Edit' : 'Add' nearbyToolData.tool.description ? 'Edit' : 'Add'
} Description` } Description`;
} }
dropdownItems.push(item) dropdownItems.push(item);
}) });
} }
return dropdownItems return dropdownItems;
} }
class ToolContextMenu extends Component { class ToolContextMenu extends Component {
@ -150,43 +150,43 @@ class ToolContextMenu extends Component {
onClose: PropTypes.func, onClose: PropTypes.func,
availableTools: PropTypes.array, availableTools: PropTypes.array,
visible: PropTypes.bool.isRequired, visible: PropTypes.bool.isRequired,
} };
static defaultProps = { static defaultProps = {
visible: true, visible: true,
isTouchEvent: false, isTouchEvent: false,
} };
constructor(props) { constructor(props) {
super(props) super(props);
this.mainElement = React.createRef() this.mainElement = React.createRef();
} }
render() { render() {
if (!this.props.eventData) { if (!this.props.eventData) {
return null return null;
} }
const { isTouchEvent, eventData, availableTools } = this.props const { isTouchEvent, eventData, availableTools } = this.props;
const dropdownItems = getDropdownItems( const dropdownItems = getDropdownItems(
eventData, eventData,
isTouchEvent, isTouchEvent,
availableTools availableTools
) );
// Skip if there is no dropdown item // Skip if there is no dropdown item
if (!dropdownItems.length) { if (!dropdownItems.length) {
return '' return '';
} }
const dropdownComponents = dropdownItems.map(item => { const dropdownComponents = dropdownItems.map(item => {
const itemOnClick = event => { const itemOnClick = event => {
item.action(item.params) item.action(item.params);
if (this.props.onClose) { if (this.props.onClose) {
this.props.onClose() this.props.onClose();
} }
} };
return ( return (
<li key={item.actionType}> <li key={item.actionType}>
@ -194,32 +194,32 @@ class ToolContextMenu extends Component {
<span key={item.actionType}>{item.text}</span> <span key={item.actionType}>{item.text}</span>
</button> </button>
</li> </li>
) );
}) });
const position = { const position = {
top: `${eventData.currentPoints.canvas.y}px`, top: `${eventData.currentPoints.canvas.y}px`,
left: `${eventData.currentPoints.canvas.x}px`, left: `${eventData.currentPoints.canvas.x}px`,
} };
return ( return (
<div className="ToolContextMenu" style={position} ref={this.mainElement}> <div className="ToolContextMenu" style={position} ref={this.mainElement}>
<ul className="bounded">{dropdownComponents}</ul> <ul className="bounded">{dropdownComponents}</ul>
</div> </div>
) );
} }
componentDidMount = () => { componentDidMount = () => {
if (this.mainElement.current) { if (this.mainElement.current) {
this.updateElementPosition() this.updateElementPosition();
} }
} };
componentDidUpdate = () => { componentDidUpdate = () => {
if (this.mainElement.current) { if (this.mainElement.current) {
this.updateElementPosition() this.updateElementPosition();
} }
} };
updateElementPosition = () => { updateElementPosition = () => {
const { const {
@ -228,25 +228,26 @@ class ToolContextMenu extends Component {
offsetHeight, offsetHeight,
offsetWidth, offsetWidth,
offsetLeft, offsetLeft,
} = this.mainElement.current } = this.mainElement.current;
const { eventData } = this.props const { eventData } = this.props;
if (offsetTop + offsetHeight > offsetParent.offsetHeight) { if (offsetTop + offsetHeight > offsetParent.offsetHeight) {
const offBoundPixels = const offBoundPixels =
offsetTop + offsetHeight - offsetParent.offsetHeight offsetTop + offsetHeight - offsetParent.offsetHeight;
const top = eventData.currentPoints.canvas.y - offBoundPixels const top = eventData.currentPoints.canvas.y - offBoundPixels;
this.mainElement.current.style.top = `${top > 0 ? top : 0}px` this.mainElement.current.style.top = `${top > 0 ? top : 0}px`;
} }
if (offsetLeft + offsetWidth > offsetParent.offsetWidth) { if (offsetLeft + offsetWidth > offsetParent.offsetWidth) {
const offBoundPixels = offsetLeft + offsetWidth - offsetParent.offsetWidth const offBoundPixels =
const left = eventData.currentPoints.canvas.x - offBoundPixels offsetLeft + offsetWidth - offsetParent.offsetWidth;
const left = eventData.currentPoints.canvas.x - offBoundPixels;
this.mainElement.current.style.left = `${left > 0 ? left : 0}px` this.mainElement.current.style.left = `${left > 0 ? left : 0}px`;
} }
} };
} }
export default ToolContextMenu export default ToolContextMenu;

View File

@ -1,12 +1,12 @@
import React, { Component } from 'react' import React, { Component } from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
import { RoundedButtonGroup } from 'react-viewerbase' import { RoundedButtonGroup } from 'react-viewerbase';
import ConnectedLayoutButton from './ConnectedLayoutButton' import ConnectedLayoutButton from './ConnectedLayoutButton';
import ConnectedPluginSwitch from './ConnectedPluginSwitch.js' import ConnectedPluginSwitch from './ConnectedPluginSwitch.js';
import './ToolbarRow.css' import './ToolbarRow.css';
const Icons = `${window.config.routerBasename}/icons.svg`.replace('//', '/') const Icons = `${window.config.routerBasename}/icons.svg`.replace('//', '/');
class ToolbarRow extends Component { class ToolbarRow extends Component {
static propTypes = { static propTypes = {
@ -15,20 +15,20 @@ class ToolbarRow extends Component {
setLeftSidebarOpen: PropTypes.func, setLeftSidebarOpen: PropTypes.func,
setRightSidebarOpen: PropTypes.func, setRightSidebarOpen: PropTypes.func,
pluginId: PropTypes.string, pluginId: PropTypes.string,
} };
static defaultProps = { static defaultProps = {
leftSidebarOpen: false, leftSidebarOpen: false,
rightSidebarOpen: false, rightSidebarOpen: false,
} };
onLeftSidebarValueChanged = value => { onLeftSidebarValueChanged = value => {
this.props.setLeftSidebarOpen(!!value) this.props.setLeftSidebarOpen(!!value);
} };
onRightSidebarValueChanged = value => { onRightSidebarValueChanged = value => {
this.props.setRightSidebarOpen(!!value) this.props.setRightSidebarOpen(!!value);
} };
render() { render() {
const leftSidebarToggle = [ const leftSidebarToggle = [
@ -39,7 +39,7 @@ class ToolbarRow extends Component {
svgHeight: 13, svgHeight: 13,
bottomLabel: 'Series', bottomLabel: 'Series',
}, },
] ];
const rightSidebarToggle = [ const rightSidebarToggle = [
{ {
@ -49,28 +49,30 @@ class ToolbarRow extends Component {
svgHeight: 13, svgHeight: 13,
bottomLabel: 'Measurements', bottomLabel: 'Measurements',
}, },
] ];
const leftSidebarValue = this.props.leftSidebarOpen const leftSidebarValue = this.props.leftSidebarOpen
? leftSidebarToggle[0].value ? leftSidebarToggle[0].value
: null : null;
const rightSidebarValue = this.props.rightSidebarOpen const rightSidebarValue = this.props.rightSidebarOpen
? rightSidebarToggle[0].value ? rightSidebarToggle[0].value
: null : null;
const currentPluginId = this.props.pluginId const currentPluginId = this.props.pluginId;
const { PLUGIN_TYPES, availablePlugins } = OHIF.plugins const { PLUGIN_TYPES, availablePlugins } = OHIF.plugins;
const plugin = availablePlugins.find(entry => { const plugin = availablePlugins.find(entry => {
return entry.type === PLUGIN_TYPES.TOOLBAR && entry.id === currentPluginId return (
}) entry.type === PLUGIN_TYPES.TOOLBAR && entry.id === currentPluginId
);
});
let pluginComp let pluginComp;
if (plugin) { if (plugin) {
const PluginComponent = plugin.component const PluginComponent = plugin.component;
pluginComp = <PluginComponent /> pluginComp = <PluginComponent />;
} }
return ( return (
@ -93,8 +95,8 @@ class ToolbarRow extends Component {
/> />
</div> </div>
</div> </div>
) );
} }
} }
export default ToolbarRow export default ToolbarRow;

View File

@ -52,7 +52,7 @@ class Viewer extends Component {
studies: PropTypes.array, studies: PropTypes.array,
studyInstanceUids: PropTypes.array, studyInstanceUids: PropTypes.array,
onTimepointsUpdated: PropTypes.func, onTimepointsUpdated: PropTypes.func,
onMeasurementsUpdated: PropTypes.func onMeasurementsUpdated: PropTypes.func,
}; };
constructor(props) { constructor(props) {
@ -60,8 +60,8 @@ class Viewer extends Component {
OHIF.measurements.MeasurementApi.setConfiguration({ OHIF.measurements.MeasurementApi.setConfiguration({
dataExchange: { dataExchange: {
retrieve: this.retrieveMeasurements, retrieve: this.retrieveMeasurements,
store: this.storeMeasurements store: this.storeMeasurements,
} },
}); });
OHIF.measurements.TimepointApi.setConfiguration({ OHIF.measurements.TimepointApi.setConfiguration({
@ -70,8 +70,8 @@ class Viewer extends Component {
store: this.storeTimepoints, store: this.storeTimepoints,
remove: this.removeTimepoint, remove: this.removeTimepoint,
update: this.updateTimepoint, update: this.updateTimepoint,
disassociate: this.disassociateStudy disassociate: this.disassociateStudy,
} },
}); });
} }
@ -115,8 +115,8 @@ class Viewer extends Component {
patientId: filter.patientId, patientId: filter.patientId,
earliestDate, earliestDate,
latestDate, latestDate,
isLocked: false isLocked: false,
} },
]); ]);
}; };
@ -158,11 +158,11 @@ class Viewer extends Component {
const currentTimepointId = 'TimepointId'; const currentTimepointId = 'TimepointId';
const timepointApi = new TimepointApi(currentTimepointId, { const timepointApi = new TimepointApi(currentTimepointId, {
onTimepointsUpdated: this.onTimepointsUpdated onTimepointsUpdated: this.onTimepointsUpdated,
}); });
const measurementApi = new MeasurementApi(timepointApi, { const measurementApi = new MeasurementApi(timepointApi, {
onMeasurementsUpdated: this.onMeasurementsUpdated onMeasurementsUpdated: this.onMeasurementsUpdated,
}); });
const patientId = studies[0] && studies[0].patientId; const patientId = studies[0] && studies[0].patientId;

View File

@ -1,9 +1,9 @@
import { Component } from 'react' import { Component } from 'react';
import React from 'react' import React from 'react';
import PropTypes from 'prop-types' import PropTypes from 'prop-types';
import { OHIF } from 'ohif-core' import { OHIF } from 'ohif-core';
import ConnectedLayoutManager from './ConnectedLayoutManager.js' import ConnectedLayoutManager from './ConnectedLayoutManager.js';
import './ViewerMain.css' import './ViewerMain.css';
class ViewerMain extends Component { class ViewerMain extends Component {
static propTypes = { static propTypes = {
@ -12,10 +12,10 @@ class ViewerMain extends Component {
clearViewportSpecificData: PropTypes.func.isRequired, clearViewportSpecificData: PropTypes.func.isRequired,
setToolActive: PropTypes.func.isRequired, setToolActive: PropTypes.func.isRequired,
setActiveViewportSpecificData: PropTypes.func.isRequired, setActiveViewportSpecificData: PropTypes.func.isRequired,
} };
constructor(props) { constructor(props) {
super(props) super(props);
// Initialize hotkeys // Initialize hotkeys
new OHIF.HotkeysUtil('viewer', { new OHIF.HotkeysUtil('viewer', {
@ -23,41 +23,41 @@ class ViewerMain extends Component {
clearViewportSpecificData: props.clearViewportSpecificData, clearViewportSpecificData: props.clearViewportSpecificData,
setToolActive: props.setToolActive, setToolActive: props.setToolActive,
setActiveViewportSpecificData: props.setActiveViewportSpecificData, setActiveViewportSpecificData: props.setActiveViewportSpecificData,
}) });
this.state = { this.state = {
displaySets: [], displaySets: [],
} };
this.cachedViewportData = {} this.cachedViewportData = {};
} }
getDisplaySets(studies) { getDisplaySets(studies) {
const displaySets = [] const displaySets = [];
studies.forEach(study => { studies.forEach(study => {
study.displaySets.forEach(dSet => { study.displaySets.forEach(dSet => {
if (!dSet.plugin) { if (!dSet.plugin) {
dSet.plugin = 'cornerstone' dSet.plugin = 'cornerstone';
} }
displaySets.push(dSet) displaySets.push(dSet);
}) });
}) });
return displaySets return displaySets;
} }
findDisplaySet(studies, studyInstanceUid, displaySetInstanceUid) { findDisplaySet(studies, studyInstanceUid, displaySetInstanceUid) {
const study = studies.find(study => { const study = studies.find(study => {
return study.studyInstanceUid === studyInstanceUid return study.studyInstanceUid === studyInstanceUid;
}) });
if (!study) { if (!study) {
return return;
} }
return study.displaySets.find(displaySet => { return study.displaySets.find(displaySet => {
return displaySet.displaySetInstanceUid === displaySetInstanceUid return displaySet.displaySetInstanceUid === displaySetInstanceUid;
}) });
} }
componentDidMount() { componentDidMount() {
@ -65,27 +65,27 @@ class ViewerMain extends Component {
//window.addEventListener('beforeunload', unloadHandlers.beforeUnload); //window.addEventListener('beforeunload', unloadHandlers.beforeUnload);
// Get all the display sets for the viewer studies // Get all the display sets for the viewer studies
const displaySets = this.getDisplaySets(this.props.studies) const displaySets = this.getDisplaySets(this.props.studies);
this.setState({ this.setState({
displaySets, displaySets,
}) });
} }
getViewportData = () => { getViewportData = () => {
const viewportData = [] const viewportData = [];
const { layout, viewportSpecificData } = this.props const { layout, viewportSpecificData } = this.props;
for ( for (
let viewportIndex = 0; let viewportIndex = 0;
viewportIndex < layout.viewports.length; viewportIndex < layout.viewports.length;
viewportIndex++ viewportIndex++
) { ) {
let displaySet = viewportSpecificData[viewportIndex] let displaySet = viewportSpecificData[viewportIndex];
// Use the cached display set in viewport if the new one is empty // Use the cached display set in viewport if the new one is empty
if (displaySet && !displaySet.displaySetInstanceUid) { if (displaySet && !displaySet.displaySetInstanceUid) {
displaySet = this.cachedViewportData[viewportIndex] displaySet = this.cachedViewportData[viewportIndex];
} }
if ( if (
@ -98,35 +98,35 @@ class ViewerMain extends Component {
this.props.studies, this.props.studies,
displaySet.studyInstanceUid, displaySet.studyInstanceUid,
displaySet.displaySetInstanceUid displaySet.displaySetInstanceUid
) );
viewportData.push(Object.assign({}, originalDisplaySet, displaySet)) viewportData.push(Object.assign({}, originalDisplaySet, displaySet));
} else { } else {
// If the viewport is empty, get one available in study // If the viewport is empty, get one available in study
const { displaySets } = this.state const { displaySets } = this.state;
displaySet = displaySets.find( displaySet = displaySets.find(
ds => ds =>
!viewportData.some( !viewportData.some(
v => v.displaySetInstanceUid === ds.displaySetInstanceUid v => v.displaySetInstanceUid === ds.displaySetInstanceUid
) )
) );
viewportData.push(Object.assign({}, displaySet)) viewportData.push(Object.assign({}, displaySet));
} }
} }
this.cachedViewportData = viewportData this.cachedViewportData = viewportData;
return viewportData return viewportData;
} };
setViewportData = ({ viewportIndex, item }) => { setViewportData = ({ viewportIndex, item }) => {
const displaySet = this.findDisplaySet( const displaySet = this.findDisplaySet(
this.props.studies, this.props.studies,
item.studyInstanceUid, item.studyInstanceUid,
item.displaySetInstanceUid item.displaySetInstanceUid
) );
this.props.setViewportSpecificData(viewportIndex, displaySet) this.props.setViewportSpecificData(viewportIndex, displaySet);
} };
render() { render() {
return ( return (
@ -137,15 +137,15 @@ class ViewerMain extends Component {
setViewportData={this.setViewportData} setViewportData={this.setViewportData}
/> />
</div> </div>
) );
} }
componentWillUnmount() { componentWillUnmount() {
// Clear the entire viewport specific data // Clear the entire viewport specific data
const { viewportSpecificData } = this.props const { viewportSpecificData } = this.props;
Object.keys(viewportSpecificData).forEach(viewportIndex => { Object.keys(viewportSpecificData).forEach(viewportIndex => {
this.props.clearViewportSpecificData(viewportIndex) this.props.clearViewportSpecificData(viewportIndex);
}) });
// Remove beforeUnload event handler... // Remove beforeUnload event handler...
//window.removeEventListener('beforeunload', unloadHandlers.beforeUnload); //window.removeEventListener('beforeunload', unloadHandlers.beforeUnload);
@ -164,4 +164,4 @@ class ViewerMain extends Component {
} }
} }
export default ViewerMain export default ViewerMain;

View File

@ -9,12 +9,12 @@ class ViewerRetrieveStudyData extends Component {
static propTypes = { static propTypes = {
studyInstanceUids: PropTypes.array.isRequired, studyInstanceUids: PropTypes.array.isRequired,
seriesInstanceUids: PropTypes.array, seriesInstanceUids: PropTypes.array,
server: PropTypes.object server: PropTypes.object,
}; };
state = { state = {
studies: null, studies: null,
error: null error: null,
}; };
componentDidMount() { componentDidMount() {
@ -33,12 +33,12 @@ class ViewerRetrieveStudyData extends Component {
const updatedStudies = createDisplaySets(studies); const updatedStudies = createDisplaySets(studies);
this.setState({ this.setState({
studies: updatedStudies studies: updatedStudies,
}); });
}) })
.catch(error => { .catch(error => {
this.setState({ this.setState({
error: true error: true,
}); });
throw new Error(error); throw new Error(error);

View File

@ -2,21 +2,21 @@
* Entry point for development and production PWA builds. * Entry point for development and production PWA builds.
* Packaged (NPM) builds go through `index_publish.js` * Packaged (NPM) builds go through `index_publish.js`
*/ */
import App from './App.js' import App from './App.js';
import React from 'react' import React from 'react';
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom';
export { App } export { App };
window.config = window.config || {} window.config = window.config || {};
const applicationDefaults = { const applicationDefaults = {
routerBasename: '/', routerBasename: '/',
relativeWebWorkerScriptsPath: '', relativeWebWorkerScriptsPath: '',
} };
const applicationProps = Object.assign({}, applicationDefaults, window.config) const applicationProps = Object.assign({}, applicationDefaults, window.config);
const app = React.createElement(App, applicationProps, null) const app = React.createElement(App, applicationProps, null);
ReactDOM.render(app, document.getElementById('root')) ReactDOM.render(app, document.getElementById('root'));
/* /*
Example config with OIDC Example config with OIDC

View File

@ -1,21 +1,21 @@
import cornerstoneTools from 'cornerstone-tools' import cornerstoneTools from 'cornerstone-tools';
import updateTableWithNewMeasurementData from './updateTableWithNewMeasurementData' import updateTableWithNewMeasurementData from './updateTableWithNewMeasurementData';
export default function getMeasurementLocationCallback( export default function getMeasurementLocationCallback(
eventData, eventData,
tool, tool,
options options
) { ) {
const { toolType } = tool const { toolType } = tool;
const { element } = eventData const { element } = eventData;
const doneCallback = updateTableWithNewMeasurementData const doneCallback = updateTableWithNewMeasurementData;
const ToolInstance = cornerstoneTools.getToolForElement(element, toolType) const ToolInstance = cornerstoneTools.getToolForElement(element, toolType);
ToolInstance.configuration.getMeasurementLocationCallback( ToolInstance.configuration.getMeasurementLocationCallback(
tool, tool,
eventData, eventData,
doneCallback, doneCallback,
options options
) );
} }

View File

@ -1,4 +1,4 @@
import { OHIF } from 'ohif-core' import { OHIF } from 'ohif-core';
// TODO: Move this function to OHIF itself so we can use it on the OHIF measurment table (when it is finished) // TODO: Move this function to OHIF itself so we can use it on the OHIF measurment table (when it is finished)
@ -16,48 +16,48 @@ export default function jumpToRowItem(
timepointManagerState, timepointManagerState,
options = { invertViewportTimepointsOrder: false, childToolKey: null } options = { invertViewportTimepointsOrder: false, childToolKey: null }
) { ) {
const numViewports = viewportsState.layout.viewports.length const numViewports = viewportsState.layout.viewports.length;
const numTimepoints = timepointManagerState.timepoints.length const numTimepoints = timepointManagerState.timepoints.length;
const { measurements, timepoints } = timepointManagerState const { measurements, timepoints } = timepointManagerState;
const numViewportsToUpdate = Math.min(numTimepoints, numViewports) const numViewportsToUpdate = Math.min(numTimepoints, numViewports);
const { toolType, measurementNumber } = measurementData const { toolType, measurementNumber } = measurementData;
if (options.invertViewportTimepointsOrder) { if (options.invertViewportTimepointsOrder) {
timepoints.reverse() timepoints.reverse();
} }
const measurementsForToolGroup = measurements[toolType] const measurementsForToolGroup = measurements[toolType];
// Retrieve the measurements data // Retrieve the measurements data
const measurementsToJumpTo = [] const measurementsToJumpTo = [];
for (let i = 0; i < numViewportsToUpdate; i++) { for (let i = 0; i < numViewportsToUpdate; i++) {
const { timepointId } = timepoints[i] const { timepointId } = timepoints[i];
const dataAtThisTimepoint = measurementsForToolGroup.find(entry => { const dataAtThisTimepoint = measurementsForToolGroup.find(entry => {
return ( return (
entry.timepointId === timepointId && entry.timepointId === timepointId &&
entry.measurementNumber === measurementNumber entry.measurementNumber === measurementNumber
) );
}) });
if (!dataAtThisTimepoint) { if (!dataAtThisTimepoint) {
measurementsToJumpTo.push(null) measurementsToJumpTo.push(null);
continue continue;
} }
let measurement = dataAtThisTimepoint let measurement = dataAtThisTimepoint;
const { tool } = OHIF.measurements.MeasurementApi.getToolConfiguration( const { tool } = OHIF.measurements.MeasurementApi.getToolConfiguration(
toolType toolType
) );
if (options.childToolKey) { if (options.childToolKey) {
measurement = dataAtThisTimepoint[options.childToolKey] measurement = dataAtThisTimepoint[options.childToolKey];
} else if (Array.isArray(tool.childTools)) { } else if (Array.isArray(tool.childTools)) {
const key = tool.childTools.find(key => !!dataAtThisTimepoint[key]) const key = tool.childTools.find(key => !!dataAtThisTimepoint[key]);
measurement = dataAtThisTimepoint[key] measurement = dataAtThisTimepoint[key];
} }
measurementsToJumpTo.push(measurement) measurementsToJumpTo.push(measurement);
} }
// TODO: Add a single viewports state action which allows // TODO: Add a single viewports state action which allows
@ -70,41 +70,41 @@ export default function jumpToRowItem(
const displaySetContainsSopInstance = (displaySet, sopInstanceUid) => const displaySetContainsSopInstance = (displaySet, sopInstanceUid) =>
displaySet.images.find( displaySet.images.find(
image => image.getSOPInstanceUID() === sopInstanceUid image => image.getSOPInstanceUID() === sopInstanceUid
) );
const viewportSpecificData = [] const viewportSpecificData = [];
measurementsToJumpTo.forEach((data, viewportIndex) => { measurementsToJumpTo.forEach((data, viewportIndex) => {
// Skip if there is no measurement to jump // Skip if there is no measurement to jump
if (!data) { if (!data) {
return return;
} }
const study = OHIF.utils.studyMetadataManager.get(data.studyInstanceUid) const study = OHIF.utils.studyMetadataManager.get(data.studyInstanceUid);
if (!study) { if (!study) {
throw new Error('Study not found.') throw new Error('Study not found.');
} }
const displaySet = study.findDisplaySet(displaySet => { const displaySet = study.findDisplaySet(displaySet => {
return displaySetContainsSopInstance(displaySet, data.sopInstanceUid) return displaySetContainsSopInstance(displaySet, data.sopInstanceUid);
}) });
if (!displaySet) { if (!displaySet) {
throw new Error('Display set not found.') throw new Error('Display set not found.');
} }
displaySet.sopInstanceUid = data.sopInstanceUid displaySet.sopInstanceUid = data.sopInstanceUid;
if (data.frameIndex) { if (data.frameIndex) {
displaySet.frameIndex = data.frameIndex displaySet.frameIndex = data.frameIndex;
} }
viewportSpecificData.push({ viewportSpecificData.push({
viewportIndex, viewportIndex,
displaySet, displaySet,
}) });
}) });
return { return {
viewportSpecificData, viewportSpecificData,
layout: [], // TODO: if we need to change layout, we should return this here layout: [], // TODO: if we need to change layout, we should return this here
} };
} }

View File

@ -1,5 +1,5 @@
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
import cornerstone from 'cornerstone-core' import cornerstone from 'cornerstone-core';
export default function updateTableWithNewMeasurementData({ export default function updateTableWithNewMeasurementData({
toolType, toolType,
@ -8,22 +8,22 @@ export default function updateTableWithNewMeasurementData({
description, description,
}) { }) {
// Update all measurements by measurement number // Update all measurements by measurement number
const measurementApi = OHIF.measurements.MeasurementApi.Instance const measurementApi = OHIF.measurements.MeasurementApi.Instance;
const measurements = measurementApi.tools[toolType].filter( const measurements = measurementApi.tools[toolType].filter(
m => m.measurementNumber === measurementNumber m => m.measurementNumber === measurementNumber
) );
measurements.forEach(measurement => { measurements.forEach(measurement => {
measurement.location = location measurement.location = location;
measurement.description = description measurement.description = description;
measurementApi.updateMeasurement(measurement.toolType, measurement) measurementApi.updateMeasurement(measurement.toolType, measurement);
}) });
measurementApi.syncMeasurementsAndToolData() measurementApi.syncMeasurementsAndToolData();
// Update images in all active viewports // Update images in all active viewports
cornerstone.getEnabledElements().forEach(enabledElement => { cornerstone.getEnabledElements().forEach(enabledElement => {
cornerstone.updateImage(enabledElement.element) cornerstone.updateImage(enabledElement.element);
}) });
} }

View File

@ -1,46 +1,46 @@
export default function bounding(elementRef, currentPosition = {}) { export default function bounding(elementRef, currentPosition = {}) {
if (!elementRef.current) { if (!elementRef.current) {
return return;
} }
const currentElement = elementRef.current const currentElement = elementRef.current;
const { const {
offsetParent, offsetParent,
offsetTop, offsetTop,
offsetHeight, offsetHeight,
offsetLeft, offsetLeft,
offsetWidth, offsetWidth,
} = currentElement } = currentElement;
let top = currentPosition.top || offsetTop let top = currentPosition.top || offsetTop;
let left = currentPosition.left || offsetLeft let left = currentPosition.left || offsetLeft;
if (!offsetParent) { if (!offsetParent) {
return return;
} }
let maxHeight = `${offsetParent.offsetHeight}px` let maxHeight = `${offsetParent.offsetHeight}px`;
if (offsetHeight + top > offsetParent.offsetHeight) { if (offsetHeight + top > offsetParent.offsetHeight) {
top = top - (offsetHeight + top - offsetParent.offsetHeight) top = top - (offsetHeight + top - offsetParent.offsetHeight);
if (top < 0) { if (top < 0) {
top = 0 top = 0;
} }
} }
if (left + offsetWidth > offsetParent.offsetWidth) { if (left + offsetWidth > offsetParent.offsetWidth) {
left = offsetParent.offsetWidth - offsetWidth left = offsetParent.offsetWidth - offsetWidth;
if (left < 0) { if (left < 0) {
left = 0 left = 0;
} }
} }
if (maxHeight && currentElement.style.maxHeight !== maxHeight) { if (maxHeight && currentElement.style.maxHeight !== maxHeight) {
currentElement.style.maxHeight = maxHeight currentElement.style.maxHeight = maxHeight;
} }
if (currentElement.style.top !== `${top}px`) { if (currentElement.style.top !== `${top}px`) {
currentElement.style.top = `${top}px` currentElement.style.top = `${top}px`;
} }
if (currentElement.style.left !== `${left}px`) { if (currentElement.style.left !== `${left}px`) {
currentElement.style.left = `${left}px` currentElement.style.left = `${left}px`;
} }
} }

View File

@ -1,16 +1,16 @@
export const setLeftSidebarOpen = state => ({ export const setLeftSidebarOpen = state => ({
type: 'SET_LEFT_SIDEBAR_OPEN', type: 'SET_LEFT_SIDEBAR_OPEN',
state state,
}); });
export const setRightSidebarOpen = state => ({ export const setRightSidebarOpen = state => ({
type: 'SET_RIGHT_SIDEBAR_OPEN', type: 'SET_RIGHT_SIDEBAR_OPEN',
state state,
}); });
export const setUserPreferencesModalOpen = state => ({ export const setUserPreferencesModalOpen = state => ({
type: 'SET_USER_PREFERENCES_MODAL_OPEN', type: 'SET_USER_PREFERENCES_MODAL_OPEN',
state state,
}); });
const actions = { const actions = {

View File

@ -4,39 +4,39 @@ const defaultState = {
userPreferencesModalOpen: false, userPreferencesModalOpen: false,
labelling: {}, labelling: {},
contextMenu: {}, contextMenu: {},
} };
const ui = (state = defaultState, action) => { const ui = (state = defaultState, action) => {
switch (action.type) { switch (action.type) {
case 'SET_LEFT_SIDEBAR_OPEN': case 'SET_LEFT_SIDEBAR_OPEN':
return Object.assign({}, state, { leftSidebarOpen: action.state }) return Object.assign({}, state, { leftSidebarOpen: action.state });
case 'SET_RIGHT_SIDEBAR_OPEN': case 'SET_RIGHT_SIDEBAR_OPEN':
return Object.assign({}, state, { rightSidebarOpen: action.state }) return Object.assign({}, state, { rightSidebarOpen: action.state });
case 'SET_USER_PREFERENCES_MODAL_OPEN': case 'SET_USER_PREFERENCES_MODAL_OPEN':
return Object.assign({}, state, { return Object.assign({}, state, {
userPreferencesModalOpen: action.state, userPreferencesModalOpen: action.state,
}) });
case 'SET_LABELLING_FLOW_DATA': case 'SET_LABELLING_FLOW_DATA':
const labelling = Object.assign({}, action.labellingFlowData) const labelling = Object.assign({}, action.labellingFlowData);
return Object.assign({}, state, { labelling }) return Object.assign({}, state, { labelling });
case 'SET_TOOL_CONTEXT_MENU_DATA': case 'SET_TOOL_CONTEXT_MENU_DATA':
const contextMenu = Object.assign({}, state.contextMenu) const contextMenu = Object.assign({}, state.contextMenu);
contextMenu[action.viewportIndex] = Object.assign( contextMenu[action.viewportIndex] = Object.assign(
{}, {},
action.toolContextMenuData action.toolContextMenuData
) );
return Object.assign({}, state, { contextMenu }) return Object.assign({}, state, { contextMenu });
case 'RESET_LABELLING_AND_CONTEXT_MENU': case 'RESET_LABELLING_AND_CONTEXT_MENU':
return Object.assign({}, state, { return Object.assign({}, state, {
labelling: defaultState.labelling, labelling: defaultState.labelling,
contextMenu: defaultState.contextMenu, contextMenu: defaultState.contextMenu,
}) });
default: default:
return state return state;
} }
} };
export default ui export default ui;

View File

@ -1,45 +1,43 @@
import React from "react"; import React from 'react';
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import ViewerRetrieveStudyData from "../connectedComponents/ViewerRetrieveStudyData.js"; import ViewerRetrieveStudyData from '../connectedComponents/ViewerRetrieveStudyData.js';
function IHEInvokeImageDisplay({ match }) { function IHEInvokeImageDisplay({ match }) {
const requestType = match.params.query.requestType; const requestType = match.params.query.requestType;
let studyInstanceUids; let studyInstanceUids;
//let patientUids; //let patientUids;
let displayStudyList = false; let displayStudyList = false;
if (requestType === "STUDY") { if (requestType === 'STUDY') {
studyInstanceUids = match.params.query.studyUID.split(';'); studyInstanceUids = match.params.query.studyUID.split(';');
} else if (requestType === "STUDYBASE64") { } else if (requestType === 'STUDYBASE64') {
const uids = this.params.query.studyUID; const uids = this.params.query.studyUID;
const decodedData = window.atob(uids); const decodedData = window.atob(uids);
studyInstanceUids = decodedData.split(';'); studyInstanceUids = decodedData.split(';');
} else if (requestType === "PATIENT") { } else if (requestType === 'PATIENT') {
//patientUidspatientUids = this.params.query.patientID.split(';'); //patientUidspatientUids = this.params.query.patientID.split(';');
displayStudyList = true displayStudyList = true;
} else { } else {
displayStudyList = true displayStudyList = true;
} }
if (displayStudyList) { if (displayStudyList) {
return ('')//<StudyList patientUids={patientUids}/>); return ''; //<StudyList patientUids={patientUids}/>);
} }
return ( return <ViewerRetrieveStudyData studyInstanceUids={studyInstanceUids} />;
<ViewerRetrieveStudyData studyInstanceUids={studyInstanceUids}/>
);
} }
IHEInvokeImageDisplay.propTypes = { IHEInvokeImageDisplay.propTypes = {
match: PropTypes.shape({ match: PropTypes.shape({
params: PropTypes.shape({ params: PropTypes.shape({
query: PropTypes.shape({ query: PropTypes.shape({
requestType: PropTypes.string.isRequired, requestType: PropTypes.string.isRequired,
studyUID: PropTypes.string, studyUID: PropTypes.string,
patientID: PropTypes.string patientID: PropTypes.string,
}) }),
}) }),
}) }),
}; };
export default IHEInvokeImageDisplay; export default IHEInvokeImageDisplay;

View File

@ -9,12 +9,12 @@ const { createDisplaySets } = OHIF.utils;
class StandaloneRouting extends Component { class StandaloneRouting extends Component {
state = { state = {
studies: null, studies: null,
error: null error: null,
}; };
static propTypes = { static propTypes = {
location: PropTypes.object, location: PropTypes.object,
store: PropTypes.object store: PropTypes.object,
}; };
static parseQueryAndFetchStudies(query) { static parseQueryAndFetchStudies(query) {

View File

@ -1,32 +1,35 @@
import React from "react"; import React from 'react';
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import ConnectedViewerRetrieveStudyData from "../connectedComponents/ConnectedViewerRetrieveStudyData"; import ConnectedViewerRetrieveStudyData from '../connectedComponents/ConnectedViewerRetrieveStudyData';
function ViewerRouting({ match }) { function ViewerRouting({ match }) {
const { studyInstanceUids, seriesInstanceUids } = match.params; const { studyInstanceUids, seriesInstanceUids } = match.params;
let studyUIDs; let studyUIDs;
let seriesUIDs; let seriesUIDs;
if (studyInstanceUids && !seriesInstanceUids) { if (studyInstanceUids && !seriesInstanceUids) {
studyUIDs = studyInstanceUids.split(';'); studyUIDs = studyInstanceUids.split(';');
} else if (studyInstanceUids && seriesInstanceUids) { } else if (studyInstanceUids && seriesInstanceUids) {
studyUIDs = [match.params.studyInstanceUid]; studyUIDs = [match.params.studyInstanceUid];
seriesUIDs = match.params.seriesInstanceUids.split(';'); seriesUIDs = match.params.seriesInstanceUids.split(';');
} }
return ( return (
<ConnectedViewerRetrieveStudyData studyInstanceUids={studyUIDs} seriesInstanceUids={seriesUIDs}/> <ConnectedViewerRetrieveStudyData
); studyInstanceUids={studyUIDs}
seriesInstanceUids={seriesUIDs}
/>
);
} }
ViewerRouting.propTypes = { ViewerRouting.propTypes = {
match: PropTypes.shape({ match: PropTypes.shape({
params: PropTypes.shape({ params: PropTypes.shape({
studyInstanceUids: PropTypes.string.isRequired, studyInstanceUids: PropTypes.string.isRequired,
seriesInstanceUids: PropTypes.string seriesInstanceUids: PropTypes.string,
}) }),
}) }),
}; };
export default ViewerRouting; export default ViewerRouting;

View File

@ -1,8 +1,8 @@
describe('Sanity Test', () => { describe('Sanity Test', () => {
test('how many marbles?', () => { test('how many marbles?', () => {
const expectedMarbles = 4 const expectedMarbles = 4;
const actualMarbles = 2 + 2 const actualMarbles = 2 + 2;
expect(actualMarbles).toEqual(expectedMarbles) expect(actualMarbles).toEqual(expectedMarbles);
}) });
}) });

View File

@ -1,15 +1,15 @@
import OHIF from 'ohif-core' import OHIF from 'ohif-core';
import updateTableWithNewMeasurementData from './lib/updateTableWithNewMeasurementData' import updateTableWithNewMeasurementData from './lib/updateTableWithNewMeasurementData';
function getToolLabellingFlowCallback(store) { function getToolLabellingFlowCallback(store) {
const setLabellingFlowDataAction = labellingFlowData => ({ const setLabellingFlowDataAction = labellingFlowData => ({
type: 'SET_LABELLING_FLOW_DATA', type: 'SET_LABELLING_FLOW_DATA',
labellingFlowData, labellingFlowData,
}) });
const setLabellingFlowData = labellingFlowData => { const setLabellingFlowData = labellingFlowData => {
store.dispatch(setLabellingFlowDataAction(labellingFlowData)) store.dispatch(setLabellingFlowDataAction(labellingFlowData));
} };
return function toolLabellingFlowCallback( return function toolLabellingFlowCallback(
measurementData, measurementData,
@ -21,21 +21,21 @@ function getToolLabellingFlowCallback(store) {
// Update the measurement data with the labelling parameters // Update the measurement data with the labelling parameters
if (location) { if (location) {
measurementData.location = location measurementData.location = location;
} }
if (description) { if (description) {
measurementData.description = description measurementData.description = description;
} }
if (response) { if (response) {
measurementData.response = response measurementData.response = response;
} }
updateTableWithNewMeasurementData(measurementData) updateTableWithNewMeasurementData(measurementData);
} };
const labellingDoneCallback = () => { const labellingDoneCallback = () => {
setLabellingFlowData({ visible: false }) setLabellingFlowData({ visible: false });
} };
const labellingFlowData = { const labellingFlowData = {
visible: true, visible: true,
@ -48,99 +48,99 @@ function getToolLabellingFlowCallback(store) {
editDescriptionOnDialog: options.editDescriptionOnDialog, editDescriptionOnDialog: options.editDescriptionOnDialog,
labellingDoneCallback, labellingDoneCallback,
updateLabelling, updateLabelling,
} };
setLabellingFlowData(labellingFlowData) setLabellingFlowData(labellingFlowData);
} };
} }
const resetLabellingAndContextMenuAction = state => ({ const resetLabellingAndContextMenuAction = state => ({
type: 'RESET_LABELLING_AND_CONTEXT_MENU', type: 'RESET_LABELLING_AND_CONTEXT_MENU',
state, state,
}) });
const setToolContextMenuDataAction = (viewportIndex, toolContextMenuData) => ({ const setToolContextMenuDataAction = (viewportIndex, toolContextMenuData) => ({
type: 'SET_TOOL_CONTEXT_MENU_DATA', type: 'SET_TOOL_CONTEXT_MENU_DATA',
viewportIndex, viewportIndex,
toolContextMenuData, toolContextMenuData,
}) });
function getOnRightClickCallback(store) { function getOnRightClickCallback(store) {
const setToolContextMenuData = (viewportIndex, toolContextMenuData) => { const setToolContextMenuData = (viewportIndex, toolContextMenuData) => {
store.dispatch(resetLabellingAndContextMenuAction()) store.dispatch(resetLabellingAndContextMenuAction());
store.dispatch( store.dispatch(
setToolContextMenuDataAction(viewportIndex, toolContextMenuData) setToolContextMenuDataAction(viewportIndex, toolContextMenuData)
) );
} };
const getOnCloseCallback = viewportIndex => { const getOnCloseCallback = viewportIndex => {
return function onClose() { return function onClose() {
const toolContextMenuData = { const toolContextMenuData = {
visible: false, visible: false,
} };
store.dispatch( store.dispatch(
setToolContextMenuDataAction(viewportIndex, toolContextMenuData) setToolContextMenuDataAction(viewportIndex, toolContextMenuData)
) );
} };
} };
return function onRightClick(event) { return function onRightClick(event) {
const eventData = event.detail const eventData = event.detail;
const viewportIndex = parseInt(eventData.element.dataset.viewportIndex, 10) const viewportIndex = parseInt(eventData.element.dataset.viewportIndex, 10);
const toolContextMenuData = { const toolContextMenuData = {
eventData, eventData,
isTouchEvent: false, isTouchEvent: false,
onClose: getOnCloseCallback(viewportIndex), onClose: getOnCloseCallback(viewportIndex),
} };
setToolContextMenuData(viewportIndex, toolContextMenuData) setToolContextMenuData(viewportIndex, toolContextMenuData);
} };
} }
function getOnTouchPressCallback(store) { function getOnTouchPressCallback(store) {
const setToolContextMenuData = (viewportIndex, toolContextMenuData) => { const setToolContextMenuData = (viewportIndex, toolContextMenuData) => {
store.dispatch(resetLabellingAndContextMenuAction()) store.dispatch(resetLabellingAndContextMenuAction());
store.dispatch( store.dispatch(
setToolContextMenuDataAction(viewportIndex, toolContextMenuData) setToolContextMenuDataAction(viewportIndex, toolContextMenuData)
) );
} };
const getOnCloseCallback = viewportIndex => { const getOnCloseCallback = viewportIndex => {
return function onClose() { return function onClose() {
const toolContextMenuData = { const toolContextMenuData = {
visible: false, visible: false,
} };
store.dispatch( store.dispatch(
setToolContextMenuDataAction(viewportIndex, toolContextMenuData) setToolContextMenuDataAction(viewportIndex, toolContextMenuData)
) );
} };
} };
return function onTouchPress(event) { return function onTouchPress(event) {
const eventData = event.detail const eventData = event.detail;
const viewportIndex = parseInt(eventData.element.dataset.viewportIndex, 10) const viewportIndex = parseInt(eventData.element.dataset.viewportIndex, 10);
const toolContextMenuData = { const toolContextMenuData = {
eventData, eventData,
isTouchEvent: true, isTouchEvent: true,
onClose: getOnCloseCallback(viewportIndex), onClose: getOnCloseCallback(viewportIndex),
} };
setToolContextMenuData(viewportIndex, toolContextMenuData) setToolContextMenuData(viewportIndex, toolContextMenuData);
} };
} }
function getResetLabellingAndContextMenu(store) { function getResetLabellingAndContextMenu(store) {
return function resetLabellingAndContextMenu() { return function resetLabellingAndContextMenu() {
store.dispatch(resetLabellingAndContextMenuAction()) store.dispatch(resetLabellingAndContextMenuAction());
} };
} }
export default function setupTools(store) { export default function setupTools(store) {
const toolLabellingFlowCallback = getToolLabellingFlowCallback(store) const toolLabellingFlowCallback = getToolLabellingFlowCallback(store);
const availableTools = [ const availableTools = [
{ name: 'Pan', mouseButtonMasks: [1, 4] }, { name: 'Pan', mouseButtonMasks: [1, 4] },
{ name: 'Zoom', mouseButtonMasks: [1, 2] }, { name: 'Zoom', mouseButtonMasks: [1, 2] },
@ -214,13 +214,13 @@ export default function setupTools(store) {
{ name: 'ZoomTouchPinch' }, { name: 'ZoomTouchPinch' },
{ name: 'StackScrollMouseWheel' }, { name: 'StackScrollMouseWheel' },
{ name: 'StackScrollMultiTouch' }, { name: 'StackScrollMultiTouch' },
] ];
const onRightClick = getOnRightClickCallback(store) const onRightClick = getOnRightClickCallback(store);
const onTouchPress = getOnTouchPressCallback(store) const onTouchPress = getOnTouchPressCallback(store);
const onNewImage = getResetLabellingAndContextMenu(store) const onNewImage = getResetLabellingAndContextMenu(store);
const onMouseClick = getResetLabellingAndContextMenu(store) const onMouseClick = getResetLabellingAndContextMenu(store);
const onTouchStart = getResetLabellingAndContextMenu(store) const onTouchStart = getResetLabellingAndContextMenu(store);
const toolAction = OHIF.redux.actions.setExtensionData('cornerstone', { const toolAction = OHIF.redux.actions.setExtensionData('cornerstone', {
availableTools, availableTools,
onNewImage, onNewImage,
@ -228,7 +228,7 @@ export default function setupTools(store) {
onTouchPress, onTouchPress,
onTouchStart, onTouchStart,
onMouseClick, onMouseClick,
}) });
store.dispatch(toolAction) store.dispatch(toolAction);
} }

View File

@ -1,21 +1,21 @@
import { connect } from 'react-redux' import { connect } from 'react-redux';
import StudyListWithData from './StudyListWithData.js' import StudyListWithData from './StudyListWithData.js';
const isActive = a => a.active === true const isActive = a => a.active === true;
const mapStateToProps = state => { const mapStateToProps = state => {
const activeServer = state.servers.servers.find(isActive) const activeServer = state.servers.servers.find(isActive);
return { return {
server: activeServer, server: activeServer,
user: state.oidc.user, user: state.oidc.user,
} };
} };
const ConnectedStudyList = connect( const ConnectedStudyList = connect(
mapStateToProps, mapStateToProps,
null null
)(StudyListWithData) )(StudyListWithData);
export default ConnectedStudyList export default ConnectedStudyList;

View File

@ -1,24 +1,22 @@
import React from "react"; import React from 'react';
import PropTypes from "prop-types"; import PropTypes from 'prop-types';
import ConnectedStudyList from "./ConnectedStudyList"; import ConnectedStudyList from './ConnectedStudyList';
// TODO: Move to react-viewerbase // TODO: Move to react-viewerbase
function StudyListRouting({ match }) { function StudyListRouting({ match }) {
// TODO: Figure out which filters we want to pass in via a URL // TODO: Figure out which filters we want to pass in via a URL
//const { patientId } = match.params; //const { patientId } = match.params;
return ( return <ConnectedStudyList />;
<ConnectedStudyList/>
);
} }
StudyListRouting.propTypes = { StudyListRouting.propTypes = {
match: PropTypes.shape({ match: PropTypes.shape({
params: PropTypes.shape({ params: PropTypes.shape({
patientIds: PropTypes.string, patientIds: PropTypes.string,
}) }),
}) }),
}; };
export default StudyListRouting; export default StudyListRouting;

View File

@ -10,14 +10,14 @@ class StudyListWithData extends Component {
state = { state = {
searchData: {}, searchData: {},
studies: null, studies: null,
error: null error: null,
}; };
static propTypes = { static propTypes = {
patientId: PropTypes.string, patientId: PropTypes.string,
server: PropTypes.object, server: PropTypes.object,
user: PropTypes.object, user: PropTypes.object,
history: PropTypes.object history: PropTypes.object,
}; };
static rowsPerPage = 25; static rowsPerPage = 25;
@ -42,7 +42,7 @@ class StudyListWithData extends Component {
rowsPerPage: StudyListWithData.rowsPerPage, rowsPerPage: StudyListWithData.rowsPerPage,
studyDateFrom: StudyListWithData.defaultStudyDateFrom, studyDateFrom: StudyListWithData.defaultStudyDateFrom,
studyDateTo: StudyListWithData.defaultStudyDateTo, studyDateTo: StudyListWithData.defaultStudyDateTo,
sortData: StudyListWithData.defaultSort sortData: StudyListWithData.defaultSort,
} }
) => { ) => {
const { server } = this.props; const { server } = this.props;
@ -55,7 +55,7 @@ class StudyListWithData extends Component {
studyDateFrom: searchData.studyDateFrom, studyDateFrom: searchData.studyDateFrom,
studyDateTo: searchData.studyDateTo, studyDateTo: searchData.studyDateTo,
limit: searchData.rowsPerPage, limit: searchData.rowsPerPage,
offset: searchData.currentPage * searchData.rowsPerPage offset: searchData.currentPage * searchData.rowsPerPage,
}; };
// TODO: add sorting // TODO: add sorting
@ -97,12 +97,12 @@ class StudyListWithData extends Component {
}); });
this.setState({ this.setState({
studies: sortedStudies studies: sortedStudies,
}); });
}) })
.catch(error => { .catch(error => {
this.setState({ this.setState({
error: true error: true,
}); });
throw new Error(error); throw new Error(error);

View File

@ -3,15 +3,15 @@
* @param {String} [baseDirectory='/'] * @param {String} [baseDirectory='/']
*/ */
export default function(baseDirectory = '/') { export default function(baseDirectory = '/') {
const iconsFileName = 'icons.svg' const iconsFileName = 'icons.svg';
const sanitizedBaseDirectory = const sanitizedBaseDirectory =
baseDirectory[baseDirectory.length - 1] === '/' baseDirectory[baseDirectory.length - 1] === '/'
? baseDirectory ? baseDirectory
: `${baseDirectory}/` : `${baseDirectory}/`;
const relativePathToIcons = `${sanitizedBaseDirectory}${iconsFileName}`.replace( const relativePathToIcons = `${sanitizedBaseDirectory}${iconsFileName}`.replace(
'//', '//',
'/' '/'
) );
return [ return [
{ {
@ -112,5 +112,5 @@ export default function(baseDirectory = '/') {
svgUrl: `${relativePathToIcons}#icon-tools-reset`, svgUrl: `${relativePathToIcons}#icon-tools-reset`,
active: false, active: false,
}, },
] ];
} }

View File

@ -1,26 +1,26 @@
import getDefaultToolbarButtons from './getDefaultToolbarButtons.js' import getDefaultToolbarButtons from './getDefaultToolbarButtons.js';
describe('getDefaultToolbarButtons.js', () => { describe('getDefaultToolbarButtons.js', () => {
it('returns a non-empty array', () => { it('returns a non-empty array', () => {
const basePath = '/' const basePath = '/';
const buttons = getDefaultToolbarButtons(basePath) const buttons = getDefaultToolbarButtons(basePath);
expect(buttons.length).toBeGreaterThan(0) expect(buttons.length).toBeGreaterThan(0);
}) });
it('uses the provided basePath in buttons with an svgUrl property', () => { it('uses the provided basePath in buttons with an svgUrl property', () => {
const basePath = '/demo/' const basePath = '/demo/';
const buttons = getDefaultToolbarButtons(basePath) const buttons = getDefaultToolbarButtons(basePath);
const hasOneOrMoreButtonsWithSvgUrlProperty = buttons.some(btn => const hasOneOrMoreButtonsWithSvgUrlProperty = buttons.some(btn =>
btn.hasOwnProperty('svgUrl') btn.hasOwnProperty('svgUrl')
) );
const usesBasePathInButtonSvgUrls = buttons.every( const usesBasePathInButtonSvgUrls = buttons.every(
btn => !btn.hasOwnProperty('svgUrl') || btn.svgUrl.includes(basePath) btn => !btn.hasOwnProperty('svgUrl') || btn.svgUrl.includes(basePath)
) );
expect(hasOneOrMoreButtonsWithSvgUrlProperty).toBeTruthy() expect(hasOneOrMoreButtonsWithSvgUrlProperty).toBeTruthy();
expect(usesBasePathInButtonSvgUrls).toBeTruthy() expect(usesBasePathInButtonSvgUrls).toBeTruthy();
}) });
}) });

View File

@ -1,5 +1,5 @@
// https://github.com/maxmantz/redux-oidc/blob/master/docs/API.md // https://github.com/maxmantz/redux-oidc/blob/master/docs/API.md
import { loadUser, createUserManager } from 'redux-oidc' import { loadUser, createUserManager } from 'redux-oidc';
/** /**
* Creates a userManager from oidcSettings; * Creates a userManager from oidcSettings;
@ -17,7 +17,7 @@ import { loadUser, createUserManager } from 'redux-oidc'
*/ */
export default function(store, oidcSettings) { export default function(store, oidcSettings) {
if (!store || !oidcSettings) { if (!store || !oidcSettings) {
return return;
} }
const settings = { const settings = {
@ -27,11 +27,11 @@ export default function(store, oidcSettings) {
revokeAccessTokenOnSignout: true, revokeAccessTokenOnSignout: true,
filterProtocolClaims: true, filterProtocolClaims: true,
loadUserInfo: true, loadUserInfo: true,
} };
const userManager = createUserManager(settings) const userManager = createUserManager(settings);
loadUser(store, userManager) loadUser(store, userManager);
return userManager return userManager;
} }

View File

@ -1,23 +1,23 @@
import getUserManagerForOpenIdConnectClient from './getUserManagerForOpenIdConnectClient.js' import getUserManagerForOpenIdConnectClient from './getUserManagerForOpenIdConnectClient.js';
describe('getUserManagerForOpenIdConnectClient', () => { describe('getUserManagerForOpenIdConnectClient', () => {
it('returns undefined if store is not provided', () => { it('returns undefined if store is not provided', () => {
const expectedReturnVal = undefined const expectedReturnVal = undefined;
const returnVal = getUserManagerForOpenIdConnectClient(undefined, {}) const returnVal = getUserManagerForOpenIdConnectClient(undefined, {});
expect(returnVal).toEqual(expectedReturnVal) expect(returnVal).toEqual(expectedReturnVal);
}) });
it('returns undefined if oidcSettings are not provided', () => { it('returns undefined if oidcSettings are not provided', () => {
const expectedReturnVal = undefined const expectedReturnVal = undefined;
const returnVal = getUserManagerForOpenIdConnectClient({}, undefined) const returnVal = getUserManagerForOpenIdConnectClient({}, undefined);
expect(returnVal).toEqual(expectedReturnVal) expect(returnVal).toEqual(expectedReturnVal);
}) });
it('does not return undefined when store and oidcSettings are defined', () => { it('does not return undefined when store and oidcSettings are defined', () => {
const returnVal = getUserManagerForOpenIdConnectClient({}, {}) const returnVal = getUserManagerForOpenIdConnectClient({}, {});
expect(returnVal).not.toBe(undefined) expect(returnVal).not.toBe(undefined);
}) });
}) });

View File

@ -1,9 +1,9 @@
import getDefaultToolbarButtons from './getDefaultToolbarButtons.js' import getDefaultToolbarButtons from './getDefaultToolbarButtons.js';
import getUserManagerForOpenIdConnectClient from './getUserManagerForOpenIdConnectClient.js' import getUserManagerForOpenIdConnectClient from './getUserManagerForOpenIdConnectClient.js';
import initWebWorkers from './initWebWorkers.js' import initWebWorkers from './initWebWorkers.js';
export { export {
getDefaultToolbarButtons, getDefaultToolbarButtons,
getUserManagerForOpenIdConnectClient, getUserManagerForOpenIdConnectClient,
initWebWorkers, initWebWorkers,
} };

View File

@ -1,8 +1,8 @@
import * as utils from './index.js' import * as utils from './index.js';
describe('utils', () => { describe('utils', () => {
it('has the expected exports', () => { it('has the expected exports', () => {
const utilExports = Object.keys(utils).sort() const utilExports = Object.keys(utils).sort();
expect(utilExports).toEqual( expect(utilExports).toEqual(
[ [
@ -10,6 +10,6 @@ describe('utils', () => {
'getUserManagerForOpenIdConnectClient', 'getUserManagerForOpenIdConnectClient',
'initWebWorkers', 'initWebWorkers',
].sort() ].sort()
) );
}) });
}) });

View File

@ -1,4 +1,4 @@
import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
/** /**
* *
@ -8,7 +8,7 @@ import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
export default function(baseDirectory, webWorkScriptsPath) { export default function(baseDirectory, webWorkScriptsPath) {
const scriptsPath = `${window.location.protocol}//${ const scriptsPath = `${window.location.protocol}//${
window.location.host window.location.host
}${baseDirectory}/${webWorkScriptsPath}` }${baseDirectory}/${webWorkScriptsPath}`;
const config = { const config = {
maxWebWorkers: Math.max(navigator.hardwareConcurrency - 1, 1), maxWebWorkers: Math.max(navigator.hardwareConcurrency - 1, 1),
startWebWorkersOnDemand: true, startWebWorkersOnDemand: true,
@ -22,7 +22,7 @@ export default function(baseDirectory, webWorkScriptsPath) {
strict: false, strict: false,
}, },
}, },
} };
cornerstoneWADOImageLoader.webWorkerManager.initialize(config) cornerstoneWADOImageLoader.webWorkerManager.initialize(config);
} }

View File

@ -1,15 +1,15 @@
import initWebWorkers from './initWebWorkers.js' import initWebWorkers from './initWebWorkers.js';
import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
describe('initWebWorkers', () => { describe('initWebWorkers', () => {
it("initializes cornerstoneWADOImageLoader's web workers", () => { it("initializes cornerstoneWADOImageLoader's web workers", () => {
const basePath = '/' const basePath = '/';
const relativeWebWorkerScriptsPath = '' const relativeWebWorkerScriptsPath = '';
initWebWorkers(basePath, relativeWebWorkerScriptsPath) initWebWorkers(basePath, relativeWebWorkerScriptsPath);
expect( expect(
cornerstoneWADOImageLoader.webWorkerManager.initialize cornerstoneWADOImageLoader.webWorkerManager.initialize
).toHaveBeenCalled() ).toHaveBeenCalled();
}) });
}) });