feat: is disabled flag for sidepanels (#1461)

* chore: updated autofix settings

* chore: remove dead code

* chore: further identify study schema/props

* chore: sketch out beginnings of isDisabled method for sidePanel menuOptions

* chore: set API as studies object

* docs: update docs to include isDisabled computed

* chore: note regarding reactivity

* chore: handle function not set (preserve non-breaking)

* chore: clarify how props are added

* chore: specify left side for built-in series button (thumbnails)

* chore: remove 'from', and push to correct key
This commit is contained in:
Danny Brown 2020-03-05 10:05:51 -05:00 committed by GitHub
commit c785a5e975
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 53 deletions

View File

@ -28,5 +28,8 @@
],
"prettier.disableLanguages": ["html"],
"prettier.endOfLine": "lf",
"workbench.colorCustomizations": {}
"workbench.colorCustomizations": {},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}

View File

@ -40,6 +40,10 @@ export default {
from: 'right',
// The target component to toggle open/close
target: 'target-component-id',
// UI Hint; If the target panel is in a "disabled" state
isDisabled: studies => {
return false;
},
// Overrides `defaultContext`, if specified
context: ['ACTIVE_VIEWPORT:MAGIC'],
},

View File

@ -21,7 +21,6 @@ export default {
/**
* MODULE GETTERS
*/
getViewportModule() {
return '... react component ...';
},
@ -98,6 +97,9 @@ const panelModule = {
icon: 'th-list',
label: 'Segments',
target: 'segment-panel',
isDisabled: studies => {
return false;
},
},
],
components: [

View File

@ -25,9 +25,17 @@ class ToolbarRow extends Component {
isRightSidePanelOpen: PropTypes.bool.isRequired,
selectedLeftSidePanel: PropTypes.string.isRequired,
selectedRightSidePanel: PropTypes.string.isRequired,
handleSidePanelChange: PropTypes.func,
handleSidePanelChange: PropTypes.func.isRequired,
activeContexts: PropTypes.arrayOf(PropTypes.string).isRequired,
studies: PropTypes.array,
t: PropTypes.func.isRequired,
// NOTE: withDialog, withModal HOCs
dialog: PropTypes.any,
modal: PropTypes.any,
};
static defaultProps = {
studies: [],
};
constructor(props) {
@ -50,30 +58,30 @@ class ToolbarRow extends Component {
this._handleBuiltIn = _handleBuiltIn.bind(this);
const panelModules = extensionManager.modules[MODULE_TYPES.PANEL];
this.buttonGroups = {
left: [
// TODO: This should come from extensions, instead of being baked in
{
value: 'studies',
icon: 'th-large',
bottomLabel: this.props.t('Series'),
},
],
left: [],
right: [],
};
// ~ FIND MENU OPTIONS
panelModules.forEach(panelExtension => {
const panelModule = panelExtension.module;
const defaultContexts = Array.from(panelModule.defaultContext);
// MENU OPTIONS
panelModule.menuOptions.forEach(menuOption => {
const contexts = Array.from(menuOption.context || defaultContexts);
const activeContextIncludesAnyPanelContexts = this.props.activeContexts.some(
actx => contexts.includes(actx)
const hasActiveContext = this.props.activeContexts.some(actx =>
contexts.includes(actx)
);
if (activeContextIncludesAnyPanelContexts) {
// It's a bit beefy to pass studies; probably only need to be reactive on `studyInstanceUIDs` and activeViewport?
// Note: This does not cleanly handle `studies` prop updating with panel open
const isDisabled =
typeof menuOption.isDisabled === 'function' &&
menuOption.isDisabled(this.props.studies);
if (hasActiveContext && !isDisabled) {
const menuOptionEntry = {
value: menuOption.target,
icon: menuOption.icon,
@ -85,6 +93,13 @@ class ToolbarRow extends Component {
}
});
});
// TODO: This should come from extensions, instead of being baked in
this.buttonGroups.left.unshift({
value: 'studies',
icon: 'th-large',
bottomLabel: this.props.t('Series'),
});
}
componentDidUpdate(prevProps) {
@ -222,6 +237,10 @@ function _getButtonComponents(toolbarButtons, activeButtons) {
}
/**
* TODO: DEPRECATE
* This is used exclusively in `extensions/cornerstone/src`
* We have better ways with new UI Services to trigger "builtin" behaviors
*
* A handy way for us to handle different button types. IE. firing commands for
* buttons, or initiation built in behavior.
*
@ -273,7 +292,7 @@ function _getVisibleToolbarButtons() {
function _handleBuiltIn(button) {
/* TODO: Keep cine button active until its unselected. */
const { dialog, modal, t } = this.props;
const { dialog, t } = this.props;
const { dialogId } = this.state;
const { id, options } = button;

View File

@ -18,45 +18,30 @@ import WhiteLabellingContext from '../context/WhiteLabellingContext.js';
import UserManagerContext from '../context/UserManagerContext';
import './Viewer.css';
/**
* Inits OHIF Hanging Protocol's onReady.
* It waits for OHIF Hanging Protocol to be ready to instantiate the ProtocolEngine
* Hanging Protocol will use OHIF LayoutManager to render viewports properly
*/
/*const initHangingProtocol = () => {
// When Hanging Protocol is ready
HP.ProtocolStore.onReady(() => {
// Gets all StudyMetadata objects: necessary for Hanging Protocol to access study metadata
const studyMetadataList = OHIF.viewer.StudyMetadataList.all();
// Instantiate StudyMetadataSource: necessary for Hanging Protocol to get study metadata
const studyMetadataSource = new OHIF.studies.classes.OHIFStudyMetadataSource();
// Get prior studies map
const studyPriorsMap = OHIF.studylist.functions.getStudyPriorsMap(studyMetadataList);
// Creates Protocol Engine object with required arguments
const ProtocolEngine = new HP.ProtocolEngine(layoutManager, studyMetadataList, studyPriorsMap, studyMetadataSource);
// Sets up Hanging Protocol engine
HP.setEngine(ProtocolEngine);
});
};*/
/*const viewportUtils = OHIF.viewerbase.viewportUtils;
OHIF.viewer.functionList = {
toggleCineDialog: viewportUtils.toggleCineDialog,
toggleCinePlay: viewportUtils.toggleCinePlay,
clearTools: viewportUtils.clearTools,
resetViewport: viewportUtils.resetViewport,
invert: viewportUtils.invert
};*/
class Viewer extends Component {
static propTypes = {
studies: PropTypes.array,
studies: PropTypes.arrayOf(
PropTypes.shape({
studyInstanceUid: PropTypes.string.isRequired,
studyDate: PropTypes.string,
displaySets: PropTypes.arrayOf(
PropTypes.shape({
displaySetInstanceUid: PropTypes.string.isRequired,
seriesDescription: PropTypes.string,
seriesNumber: PropTypes.number,
instanceNumber: PropTypes.number,
numImageFrames: PropTypes.number,
modality: PropTypes.string.isRequired,
images: PropTypes.arrayOf(
PropTypes.shape({
getImageId: PropTypes.func.isRequired,
})
),
})
),
})
),
studyInstanceUids: PropTypes.array,
activeServer: PropTypes.shape({
type: PropTypes.string,