Segmentation UI for VTKjs (#1685)
* Add single viewport configuration * Multiple viewport configuration * Improve performance by using independent set methods * Add jump to slice command * Add context configuration * Cache panel visibility * Fix sync between vtk and cornerstone * Remove apis index * Add approach * Add loading to update volumes * Fix broken configuration * Bump vtk version * Use loading label * Update cy tests after vtk loading label changed * Remove loading for segs
This commit is contained in:
1 parent
19a8e71317
commit
42c22df1b6
22 files changed
+516
-173
No files matched your search
@@ -21,8 +21,8 @@ describe('OHIF VTK Extension', () => {
|
||||
//Select 2D MPR button
|
||||
cy.get('[data-cy="2d mpr"]').click();
|
||||
|
||||
//Wait Reformatting Images
|
||||
cy.waitVTKReformatting();
|
||||
//Wait waitVTKLoading Images
|
||||
cy.waitVTKLoading();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@ describe('Visual Regression - OHIF VTK Extension', () => {
|
||||
//Select 2D MPR button
|
||||
cy.get('[data-cy="2d mpr"]').click();
|
||||
|
||||
//Wait Reformatting Images
|
||||
cy.waitVTKReformatting();
|
||||
//Wait waitVTKLoading Images
|
||||
cy.waitVTKwaitVTKLoading();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -107,15 +107,15 @@ Cypress.Commands.add('waitStudyList', () => {
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitVTKReformatting', () => {
|
||||
// Wait for start reformatting
|
||||
Cypress.Commands.add('waitVTKLoading', () => {
|
||||
// Wait for start loading
|
||||
cy.get('[data-cy="viewprt-grid"]', { timeout: 10000 }).should($grid => {
|
||||
expect($grid).to.contain.text('Reform');
|
||||
expect($grid).to.contain.text('Loading');
|
||||
});
|
||||
|
||||
// Wait for finish reformatting
|
||||
// Wait for finish loading
|
||||
cy.get('[data-cy="viewprt-grid"]', { timeout: 30000 }).should($grid => {
|
||||
expect($grid).not.to.contain.text('Reform');
|
||||
expect($grid).not.to.contain.text('Loading');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ import store from './store';
|
||||
/** Contexts */
|
||||
import WhiteLabelingContext from './context/WhiteLabelingContext';
|
||||
import UserManagerContext from './context/UserManagerContext';
|
||||
import AppContext from './context/AppContext';
|
||||
import { AppProvider, useAppContext, CONTEXTS } from './context/AppContext';
|
||||
|
||||
/** ~~~~~~~~~~~~~ Application Setup */
|
||||
const commandsManagerConfig = {
|
||||
@@ -159,8 +159,8 @@ class App extends Component {
|
||||
|
||||
if (this._userManager) {
|
||||
return (
|
||||
<AppContext.Provider value={{ appConfig: this._appConfig }}>
|
||||
<Provider store={store}>
|
||||
<Provider store={store}>
|
||||
<AppProvider config={this._appConfig}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<OidcProvider store={store} userManager={this._userManager}>
|
||||
<UserManagerContext.Provider value={this._userManager}>
|
||||
@@ -183,14 +183,14 @@ class App extends Component {
|
||||
</UserManagerContext.Provider>
|
||||
</OidcProvider>
|
||||
</I18nextProvider>
|
||||
</Provider>
|
||||
</AppContext.Provider>
|
||||
</AppProvider>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={{ appConfig: this._appConfig }}>
|
||||
<Provider store={store}>
|
||||
<Provider store={store}>
|
||||
<AppProvider config={this._appConfig}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<Router basename={routerBasename}>
|
||||
<WhiteLabelingContext.Provider value={whiteLabeling}>
|
||||
@@ -204,8 +204,8 @@ class App extends Component {
|
||||
</WhiteLabelingContext.Provider>
|
||||
</Router>
|
||||
</I18nextProvider>
|
||||
</Provider>
|
||||
</AppContext.Provider>
|
||||
</AppProvider>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -255,6 +255,12 @@ function _initExtensions(extensions, cornerstoneExtensionConfig, appConfig) {
|
||||
commandsManager,
|
||||
servicesManager,
|
||||
appConfig,
|
||||
api: {
|
||||
contexts: CONTEXTS,
|
||||
hooks: {
|
||||
useAppContext
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const requiredExtensions = [
|
||||
|
||||
@@ -191,8 +191,8 @@ class OHIFStandaloneViewer extends Component {
|
||||
{match === null ? (
|
||||
<></>
|
||||
) : (
|
||||
<Component match={match} location={this.props.location} />
|
||||
)}
|
||||
<Component match={match} location={this.props.location} />
|
||||
)}
|
||||
</CSSTransition>
|
||||
)}
|
||||
</Route>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
// TODO: REPLACE THIS WITH A CONTEXT PROVIDER
|
||||
// EVERYTHING IN `VIEWER.JS` COULD USE THIS FOR APPROPRIATE CONTEXT
|
||||
import ToolbarRow from './ToolbarRow';
|
||||
import { connect } from 'react-redux';
|
||||
import { getActiveContexts } from './../store/layout/selectors.js';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
activeContexts: getActiveContexts(state),
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedToolbarRow = connect(mapStateToProps)(ToolbarRow);
|
||||
|
||||
export default ConnectedToolbarRow;
|
||||
@@ -16,6 +16,7 @@ import { commandsManager, extensionManager } from './../App.js';
|
||||
|
||||
import ConnectedCineDialog from './ConnectedCineDialog';
|
||||
import ConnectedLayoutButton from './ConnectedLayoutButton';
|
||||
import { withAppContext } from '../context/AppContext';
|
||||
|
||||
class ToolbarRow extends Component {
|
||||
// TODO: Simplify these? isOpen can be computed if we say "any" value for selected,
|
||||
@@ -381,5 +382,5 @@ function _handleBuiltIn(button) {
|
||||
}
|
||||
|
||||
export default withTranslation(['Common', 'ViewportDownloadForm'])(
|
||||
withModal(withDialog(ToolbarRow))
|
||||
withModal(withDialog(withAppContext(ToolbarRow)))
|
||||
);
|
||||
@@ -7,7 +7,7 @@ import OHIF, { DICOMSR } from '@ohif/core';
|
||||
import { withDialog } from '@ohif/ui';
|
||||
import moment from 'moment';
|
||||
import ConnectedHeader from './ConnectedHeader.js';
|
||||
import ConnectedToolbarRow from './ConnectedToolbarRow.js';
|
||||
import ToolbarRow from './ToolbarRow.js';
|
||||
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
|
||||
import ConnectedViewerMain from './ConnectedViewerMain.js';
|
||||
import SidePanel from './../components/SidePanel.js';
|
||||
@@ -256,7 +256,7 @@ class Viewer extends Component {
|
||||
</WhiteLabelingContext.Consumer>
|
||||
|
||||
{/* TOOLBAR */}
|
||||
<ConnectedToolbarRow
|
||||
<ToolbarRow
|
||||
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
|
||||
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
|
||||
selectedLeftSidePanel={
|
||||
@@ -307,11 +307,11 @@ class Viewer extends Component {
|
||||
activeIndex={this.props.activeViewportIndex}
|
||||
/>
|
||||
) : (
|
||||
<ConnectedStudyBrowser
|
||||
studies={this.state.thumbnails}
|
||||
studyMetadata={this.props.studies}
|
||||
/>
|
||||
)}
|
||||
<ConnectedStudyBrowser
|
||||
studies={this.state.thumbnails}
|
||||
studyMetadata={this.props.studies}
|
||||
/>
|
||||
)}
|
||||
</SidePanel>
|
||||
|
||||
{/* MAIN */}
|
||||
@@ -349,7 +349,7 @@ export default withDialog(Viewer);
|
||||
* @param {Study[]} studies
|
||||
* @param {DisplaySet[]} studies[].displaySets
|
||||
*/
|
||||
const _mapStudiesToThumbnails = function(studies) {
|
||||
const _mapStudiesToThumbnails = function (studies) {
|
||||
return studies.map(study => {
|
||||
const { StudyInstanceUID } = study;
|
||||
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
import React from 'react';
|
||||
import React, { useContext } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { getActiveContexts } from '../store/layout/selectors.js';
|
||||
|
||||
let AppContext = React.createContext({});
|
||||
|
||||
export const CONTEXTS = {
|
||||
CORNERSTONE: 'ACTIVE_VIEWPORT::CORNERSTONE',
|
||||
VTK: 'ACTIVE_VIEWPORT::VTK'
|
||||
};
|
||||
|
||||
export const useAppContext = () => useContext(AppContext);
|
||||
|
||||
export const AppProvider = ({ children, config }) => {
|
||||
const activeContexts = useSelector(state => getActiveContexts(state));
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={{ appConfig: config, activeContexts }}>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const withAppContext = Component => {
|
||||
return function WrappedComponent(props) {
|
||||
const { appConfig, activeContexts } = useAppContext();
|
||||
return (
|
||||
<Component {...props} appConfig={appConfig} activeContexts={activeContexts} />
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
export default AppContext;
|
||||
Reference in new issue
Block a user