Merge pull request #504 from dannyrb/master-semicolon-fix
semicolon fix
This commit is contained in:
commit
a3405e7a9e
@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
96
src/App.js
96
src/App.js
@ -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;
|
||||||
|
|||||||
@ -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() {
|
||||||
|
|||||||
@ -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)
|
||||||
)
|
);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -2,4 +2,4 @@ export default {
|
|||||||
webWorkerManager: {
|
webWorkerManager: {
|
||||||
initialize: jest.fn(),
|
initialize: jest.fn(),
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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 };
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
};
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 });
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
import Header from './Header'
|
import Header from './Header';
|
||||||
|
|
||||||
export default Header
|
export default Header;
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
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 {
|
||||||
@ -16,12 +16,12 @@ class StudyLoadingMonitor extends Component {
|
|||||||
// but this should definitely be cleaned up somehow.
|
// but this should definitely be cleaned up somehow.
|
||||||
const options = {
|
const options = {
|
||||||
_setProgressData: (progressId, progressData) => {
|
_setProgressData: (progressId, progressData) => {
|
||||||
this.props.setStudyLoadingProgress(progressId, progressData)
|
this.props.setStudyLoadingProgress(progressId, progressData);
|
||||||
},
|
},
|
||||||
_clearProgressById: (progressId) => {
|
_clearProgressById: progressId => {
|
||||||
this.props.clearStudyLoadingProgress(progressId)
|
this.props.clearStudyLoadingProgress(progressId);
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
const { StudyLoadingListener } = OHIF.classes;
|
const { StudyLoadingListener } = OHIF.classes;
|
||||||
this.studyLoadingListener = StudyLoadingListener.getInstance(options);
|
this.studyLoadingListener = StudyLoadingListener.getInstance(options);
|
||||||
@ -39,5 +39,4 @@ class StudyLoadingMonitor extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default StudyLoadingMonitor;
|
export default StudyLoadingMonitor;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
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;
|
||||||
@ -26,5 +26,4 @@ class StudyPrefetcherComponent extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default StudyPrefetcherComponent;
|
export default StudyPrefetcherComponent;
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|||||||
@ -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));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
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;
|
||||||
|
|
||||||
@ -21,15 +21,15 @@ const mapDispatchToProps = dispatch => {
|
|||||||
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));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
|
|
||||||
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];
|
||||||
|
|
||||||
@ -24,11 +24,11 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.stackPercentComplete = stackPercentComplete;
|
data.stackPercentComplete = stackPercentComplete;
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
studies: studiesWithLoadingData
|
studies: studiesWithLoadingData,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,17 +1,20 @@
|
|||||||
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));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -6,27 +6,31 @@ 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 pluginInViewportData =
|
||||||
|
viewportSpecificData[activeViewportIndex] &&
|
||||||
|
viewportSpecificData[activeViewportIndex].plugin;
|
||||||
|
const pluginInActiveViewport =
|
||||||
|
pluginInLayout || pluginInViewportData || defaultPlugin;
|
||||||
// const extensionData = state.extensions[pluginInActiveViewport];
|
// 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));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
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;
|
||||||
|
|
||||||
@ -9,15 +9,15 @@ const mapStateToProps = state => {
|
|||||||
|
|
||||||
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));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const mapDispatchToProps = dispatch => {
|
|||||||
},
|
},
|
||||||
onMeasurementsUpdated: measurements => {
|
onMeasurementsUpdated: measurements => {
|
||||||
dispatch(setMeasurements(measurements));
|
dispatch(setMeasurements(measurements));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 = {};
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
18
src/index.js
18
src/index.js
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 = {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
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;
|
||||||
@ -8,26 +8,24 @@ function IHEInvokeImageDisplay({ match }) {
|
|||||||
//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 = {
|
||||||
@ -36,10 +34,10 @@ IHEInvokeImageDisplay.propTypes = {
|
|||||||
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;
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
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;
|
||||||
@ -16,7 +16,10 @@ function ViewerRouting({ match }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConnectedViewerRetrieveStudyData studyInstanceUids={studyUIDs} seriesInstanceUids={seriesUIDs}/>
|
<ConnectedViewerRetrieveStudyData
|
||||||
|
studyInstanceUids={studyUIDs}
|
||||||
|
seriesInstanceUids={seriesUIDs}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,9 +27,9 @@ 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;
|
||||||
|
|||||||
@ -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);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
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
|
||||||
|
|
||||||
@ -8,17 +8,15 @@ 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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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,
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@ -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,
|
||||||
}
|
};
|
||||||
|
|||||||
@ -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()
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user