Fix/update branch cherry pick (#2039)
* Update all the icons * Turn off global tool sync; watch as the world burns * Shift a bunch of things around so we can start tracking/setting per element * ToolBarService to initiate one of three different calls; callback passed to all button types * SplitButton and Toolbar Button to use new `onInteraction` prop and new toolbar state * Changes to toolbar button interface and config * Fix broken layout selector * Update SR viewport to activate tools in viewport component * Duplicate activation logic in measurement tracking extension * Add alternative/dashed variants for SR Viewport * pass through "setToolActive" commands for other viewport types * fix small overlay bugs (no wwwc or scale info) * Show SpacingBetweenSlices instead of PixelSpacing in patient information dialog * Fix prop-types * Update tracked viewport to have alternative tracked styling * alt styling for SR viewports * Update to support isLocked + isRehydratable * fix broken logic * fix broken logic * switch icon style * fix icon styles * hover and click to start flow * expedited workflow when data is not dirty (just after SR hydration) * fix: setting elliptical roi tool * fix arrow annotate dialog * fix: do not show learn more button for now * remove dead code * simpler cache invalidation * simpler cache invalidation part 2 * Fix for unable to spand study cards on separate pages
This commit is contained in:
1 parent
365ba2fa72
commit
cae54b0779
78 files changed
+1678
-1263
No files matched your search
@@ -5,7 +5,6 @@ import log from '../log.js';
|
||||
*
|
||||
* @typedef {Object} CommandDefinition
|
||||
* @property {Function} commandFn - Command to call
|
||||
* @property {Array} storeContexts - Array of string of modules required from store
|
||||
* @property {Object} options - Object of params to pass action
|
||||
*/
|
||||
|
||||
@@ -161,19 +160,10 @@ export class CommandsManager {
|
||||
return;
|
||||
}
|
||||
|
||||
const { commandFn, storeContexts = [] } = definition;
|
||||
const definitionOptions = definition.options;
|
||||
|
||||
let commandParams = {};
|
||||
const appState = this._getAppState();
|
||||
storeContexts.forEach(context => {
|
||||
commandParams[context] = appState[context];
|
||||
});
|
||||
|
||||
commandParams = Object.assign(
|
||||
const { commandFn } = definition;
|
||||
const commandParams = Object.assign(
|
||||
{},
|
||||
commandParams, // Required store contexts
|
||||
definitionOptions, // "Command configuration"
|
||||
definition.options, // "Command configuration"
|
||||
options // "Time of call" info
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import log from './../log.js';
|
||||
|
||||
export default class ServicesManager {
|
||||
constructor() {
|
||||
constructor(commandsManager) {
|
||||
this._commandsManager = commandsManager;
|
||||
this.services = {};
|
||||
this.registeredServiceNames = [];
|
||||
}
|
||||
@@ -35,6 +36,7 @@ export default class ServicesManager {
|
||||
if (service.create) {
|
||||
this.services[service.name] = service.create({
|
||||
configuration,
|
||||
commandsManager: this._commandsManager,
|
||||
});
|
||||
} else {
|
||||
log.warn(`Service create factory function not defined. Exiting early.`);
|
||||
|
||||
@@ -3,10 +3,13 @@ import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
|
||||
|
||||
const EVENTS = {
|
||||
TOOL_BAR_MODIFIED: 'event::toolBarService:toolBarModified',
|
||||
TOOL_BAR_STATE_MODIFIED: 'event::toolBarService:toolBarStateModified',
|
||||
};
|
||||
|
||||
export default class ToolBarService {
|
||||
constructor() {
|
||||
constructor(commandsManager) {
|
||||
this._commandsManager = commandsManager;
|
||||
//
|
||||
this.EVENTS = EVENTS;
|
||||
this.listeners = {};
|
||||
this.buttons = {};
|
||||
@@ -17,6 +20,18 @@ export default class ToolBarService {
|
||||
*/
|
||||
};
|
||||
|
||||
// TODO: Do we need to track per context? Or do we allow for a mixed
|
||||
// definition that adapts based on context?
|
||||
this.state = {
|
||||
primaryToolId: 'Wwwc',
|
||||
toggles: {
|
||||
/* id: true/false */
|
||||
},
|
||||
groups: {
|
||||
/* track most recent click per group...? */
|
||||
},
|
||||
};
|
||||
|
||||
Object.assign(this, pubSubServiceInterface);
|
||||
}
|
||||
|
||||
@@ -24,17 +39,59 @@ export default class ToolBarService {
|
||||
this.extensionManager = extensionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} interaction
|
||||
*/
|
||||
recordInteraction(interaction) {
|
||||
const commandsManager = this._commandsManager;
|
||||
const { groupId, itemId, interactionType } = interaction;
|
||||
|
||||
switch (interactionType) {
|
||||
case 'action': {
|
||||
break;
|
||||
}
|
||||
case 'tool': {
|
||||
this.state.primaryToolId = itemId;
|
||||
// TODO: Force run this for all contexts? Even inactive?
|
||||
// or... They'll just detect primaryToolId when they spin up and apply...
|
||||
commandsManager.runCommand('setToolActive', interaction.commandOptions);
|
||||
break;
|
||||
}
|
||||
case 'toggle': {
|
||||
this.state.toggles[itemId] =
|
||||
this.state.toggles[itemId] === undefined
|
||||
? true
|
||||
: !this.state.toggles[itemId];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Run command if there's one associated
|
||||
//
|
||||
// NOTE: Should probably just do this for tools as well?
|
||||
// But would be nice if we could enforce at least the command name?
|
||||
if (interaction.commandName) {
|
||||
commandsManager.runCommand(
|
||||
interaction.commandName,
|
||||
interaction.commandOptions
|
||||
);
|
||||
}
|
||||
|
||||
// Track last touched id for each group
|
||||
if (groupId) {
|
||||
this.state.groups[groupId] = itemId;
|
||||
}
|
||||
|
||||
this._broadcastChange(this.EVENTS.TOOL_BAR_STATE_MODIFIED, {});
|
||||
}
|
||||
|
||||
getButtons() {
|
||||
return this.buttons;
|
||||
}
|
||||
|
||||
getActiveTools() {
|
||||
return Object.keys(this.buttons).filter(key => {
|
||||
const button = this.buttons[key];
|
||||
if (button && button.props && button.props.isActive) {
|
||||
return button;
|
||||
}
|
||||
});
|
||||
return [this.state.primaryToolId, ...Object.keys(this.state.toggles)];
|
||||
}
|
||||
|
||||
setButton(id, button) {
|
||||
@@ -43,7 +100,7 @@ export default class ToolBarService {
|
||||
this._broadcastChange(this.EVENTS.TOOL_BAR_MODIFIED, {
|
||||
buttons: this.buttons,
|
||||
button: this.buttons[id],
|
||||
buttonSections: this.buttonSections
|
||||
buttonSections: this.buttonSections,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -52,7 +109,7 @@ export default class ToolBarService {
|
||||
this.buttons = buttons;
|
||||
this._broadcastChange(this.EVENTS.TOOL_BAR_MODIFIED, {
|
||||
buttons: this.buttons,
|
||||
buttonSections: this.buttonSections
|
||||
buttonSections: this.buttonSections,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -84,41 +141,27 @@ export default class ToolBarService {
|
||||
this._broadcastChange(this.EVENTS.TOOL_BAR_MODIFIED, {});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Finds a button section by it's name, then maps the list of string name
|
||||
* identifiers to schema/values that can be used to render the buttons.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {*} props
|
||||
*/
|
||||
getButtonSection(key, props) {
|
||||
const buttonSectionIds = this.buttonSections[key];
|
||||
const buttonsInSection = [];
|
||||
|
||||
if (!buttonSectionIds) {
|
||||
return buttonsInSection;
|
||||
}
|
||||
|
||||
buttonSectionIds.forEach(btnIdOrArray => {
|
||||
const isNested = Array.isArray(btnIdOrArray);
|
||||
|
||||
if (isNested) {
|
||||
const btnIds = btnIdOrArray;
|
||||
const nestedButtons = [];
|
||||
|
||||
btnIds.forEach(nestedBtnId => {
|
||||
const nestedBtn = this.buttons[nestedBtnId];
|
||||
const metadata = { isNested: true };
|
||||
const mappedNestedBtn = this._mapButtonToDisplay(nestedBtn, key, metadata, props);
|
||||
|
||||
nestedButtons.push(mappedNestedBtn);
|
||||
});
|
||||
|
||||
if (nestedButtons.length) {
|
||||
buttonsInSection.push(nestedButtons);
|
||||
}
|
||||
} else {
|
||||
const btnId = btnIdOrArray;
|
||||
if (buttonSectionIds && buttonSectionIds.length !== 0) {
|
||||
buttonSectionIds.forEach(btnId => {
|
||||
const btn = this.buttons[btnId];
|
||||
const metadata = { isNested: false };
|
||||
const metadata = {};
|
||||
const mappedBtn = this._mapButtonToDisplay(btn, key, metadata, props);
|
||||
|
||||
buttonsInSection.push(mappedBtn);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return buttonsInSection;
|
||||
}
|
||||
@@ -159,6 +202,8 @@ export default class ToolBarService {
|
||||
*
|
||||
* @param {*} btn
|
||||
* @param {*} btnSection
|
||||
* @param {*} metadata
|
||||
* @param {*} props - Props set by the Viewer layer
|
||||
*/
|
||||
_mapButtonToDisplay(btn, btnSection, metadata, props) {
|
||||
const { id, type, component } = btn;
|
||||
@@ -168,25 +213,10 @@ export default class ToolBarService {
|
||||
return;
|
||||
}
|
||||
|
||||
const onClick = evt => {
|
||||
if (buttonType.clickHandler) {
|
||||
buttonType.clickHandler(evt, btn, btnSection, metadata, props);
|
||||
}
|
||||
if (btn.props.onClick) {
|
||||
btn.onClick(evt, btn, btnSection);
|
||||
}
|
||||
if (btn.props.clickHandler) {
|
||||
btn.clickHandler(evt, btn, btnSection);
|
||||
}
|
||||
if (props && props.onClick) {
|
||||
props.onClick(evt, btn, btnSection, props);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
id,
|
||||
Component: component || buttonType.defaultComponent,
|
||||
componentProps: Object.assign({}, btn.props, { onClick }), //
|
||||
componentProps: Object.assign({}, btn.props, props),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import ToolBarService from './ToolBarService';
|
||||
|
||||
export default {
|
||||
name: 'ToolBarService',
|
||||
create: ({ configuration = {} }) => {
|
||||
return new ToolBarService();
|
||||
create: ({ configuration = {}, commandsManager }) => {
|
||||
return new ToolBarService(commandsManager);
|
||||
},
|
||||
};
|
||||
Reference in new issue
Block a user