From e62f5f8dd28ab363f23671cd21cee115abb870ff Mon Sep 17 00:00:00 2001 From: Igor Octaviano Date: Mon, 11 Nov 2019 23:03:36 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Update=20hotkeys=20and?= =?UTF-8?q?=20user=20preferences=20modal=20(#1135)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 Update hotkeys and user preferences modal This feature fix incompatibility with existent hotkeys component and adds user preferences modal back Closes: #923 * Update preferences structure in store * Hide window level section of user preferences * Update modal to reflect current hotkey value * Clone object with hotkeys before passing to manager * CR Update: Extract hotkeys manager format code to manager * Fix broken cypress test * Use new modal provider * Rename hotkeyDefinitions in hotkeyspreferences and use array as representation * Update study test and remove unused styles --- platform/core/src/classes/HotkeysManager.js | 6 +- .../core/src/redux/reducers/preferences.js | 21 ++-- platform/ui/src/components/index.js | 6 +- .../GeneralPreferences.js | 0 .../HotKeysPreferences.js | 68 ++++------- .../HotKeysPreferences.styl | 0 .../UserPreferences.js | 30 ++--- .../UserPreferences.styl | 0 .../UserPreferencesForm.js | 86 ++++++++++++++ .../UserPreferencesForm.styl} | 13 ++- .../WindowLevelPreferences.js | 0 .../WindowLevelPreferences.styl | 0 .../__docs__/about.mdx | 0 .../__docs__/generalDefaults.js | 0 .../__docs__/hotkeyDefaults.js | 0 .../__docs__/userPreferences.mdx | 16 +-- .../__docs__/windowLevelDefaults.js | 0 .../hotKeysConfig.js | 56 ++++----- .../index.js | 2 +- .../UserPreferencesModal.js | 107 ------------------ platform/ui/src/index.js | 4 +- .../common/OHIFStudyViewer.spec.js | 8 +- .../viewer/src/components/Header/Header.css | 4 + .../viewer/src/components/Header/Header.js | 43 +++---- .../connectedComponents/ConnectedHeader.js | 8 +- .../ConnectedUserPreferencesForm.js | 41 +++++++ 26 files changed, 263 insertions(+), 256 deletions(-) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/GeneralPreferences.js (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/HotKeysPreferences.js (78%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/HotKeysPreferences.styl (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/UserPreferences.js (82%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/UserPreferences.styl (100%) create mode 100644 platform/ui/src/components/userPreferencesForm/UserPreferencesForm.js rename platform/ui/src/components/{userPreferencesModal/UserPreferencesModal.styl => userPreferencesForm/UserPreferencesForm.styl} (64%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/WindowLevelPreferences.js (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/WindowLevelPreferences.styl (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/__docs__/about.mdx (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/__docs__/generalDefaults.js (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/__docs__/hotkeyDefaults.js (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/__docs__/userPreferences.mdx (77%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/__docs__/windowLevelDefaults.js (100%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/hotKeysConfig.js (74%) rename platform/ui/src/components/{userPreferencesModal => userPreferencesForm}/index.js (74%) delete mode 100644 platform/ui/src/components/userPreferencesModal/UserPreferencesModal.js create mode 100644 platform/viewer/src/connectedComponents/ConnectedUserPreferencesForm.js diff --git a/platform/core/src/classes/HotkeysManager.js b/platform/core/src/classes/HotkeysManager.js index b5a0ed20d..280c045ce 100644 --- a/platform/core/src/classes/HotkeysManager.js +++ b/platform/core/src/classes/HotkeysManager.js @@ -1,3 +1,4 @@ +import cloneDeep from 'lodash.clonedeep'; import hotkeys from './hotkeys'; import log from './../log.js'; @@ -51,10 +52,11 @@ export class HotkeysManager { * @param {Boolean} [isDefaultDefinitions] */ setHotkeys(hotkeyDefinitions, isDefaultDefinitions = false) { - hotkeyDefinitions.forEach(definition => this.registerHotkeys(definition)); + const definitions = cloneDeep(hotkeyDefinitions); + definitions.forEach(definition => this.registerHotkeys(definition)); if (isDefaultDefinitions) { - this.hotkeyDefaults = hotkeyDefinitions; + this.hotkeyDefaults = definitions; } } diff --git a/platform/core/src/redux/reducers/preferences.js b/platform/core/src/redux/reducers/preferences.js index 2c9ccdf76..443996adc 100644 --- a/platform/core/src/redux/reducers/preferences.js +++ b/platform/core/src/redux/reducers/preferences.js @@ -1,18 +1,15 @@ import cloneDeep from 'lodash.clonedeep'; const defaultState = { - // Top level key - viewer: { - // First tab - hotKeysData: { - // hotkeyName, label, keys, column - // zoom: { label: 'Zoom', command: 'Z', column: 0 }, - }, - // Second tab - windowLevelData: { - // order, description, window (int), level (int) - // 0: { description: 'Soft tissue', window: '', level: '' }, - }, + // First tab + hotkeyDefinitions: [ + // commandName, label, keys + // [{ zoom: { label: 'Zoom', keys: ['z'] }}] + ], + // Second tab + windowLevelData: { + // order, description, window (int), level (int) + // 0: { description: 'Soft tissue', window: '', level: '' }, }, }; diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js index df935085f..81ae9dfe4 100644 --- a/platform/ui/src/components/index.js +++ b/platform/ui/src/components/index.js @@ -6,8 +6,8 @@ import { TableList, TableListItem } from './tableList'; import { AboutContent, UserPreferences, - UserPreferencesModal, -} from './userPreferencesModal'; + UserPreferencesForm, +} from './userPreferencesForm'; import { Checkbox } from './checkbox'; import { CineDialog } from './cineDialog'; @@ -52,6 +52,6 @@ export { Tooltip, AboutContent, UserPreferences, - UserPreferencesModal, + UserPreferencesForm, OHIFModal, }; diff --git a/platform/ui/src/components/userPreferencesModal/GeneralPreferences.js b/platform/ui/src/components/userPreferencesForm/GeneralPreferences.js similarity index 100% rename from platform/ui/src/components/userPreferencesModal/GeneralPreferences.js rename to platform/ui/src/components/userPreferencesForm/GeneralPreferences.js diff --git a/platform/ui/src/components/userPreferencesModal/HotKeysPreferences.js b/platform/ui/src/components/userPreferencesForm/HotKeysPreferences.js similarity index 78% rename from platform/ui/src/components/userPreferencesModal/HotKeysPreferences.js rename to platform/ui/src/components/userPreferencesForm/HotKeysPreferences.js index ea97a144b..1acf00a39 100644 --- a/platform/ui/src/components/userPreferencesModal/HotKeysPreferences.js +++ b/platform/ui/src/components/userPreferencesForm/HotKeysPreferences.js @@ -10,31 +10,14 @@ import PropTypes from 'prop-types'; export class HotKeysPreferences extends Component { static propTypes = { - hotKeysData: PropTypes.objectOf( - PropTypes.shape({ - keys: PropTypes.arrayOf(PropTypes.string).isRequired, - label: PropTypes.string.isRequired, - }) - ).isRequired, - onChange: PropTypes.func, + hotkeyDefinitions: PropTypes.array.isRequired, }; constructor(props) { super(props); - const hotkeyCommands = Object.keys(this.props.hotKeysData); - const localHotKeys = hotkeyCommands.map(commandName => { - const definition = this.props.hotKeysData[commandName]; - - return { - commandName, - keys: definition.keys, - label: definition.label, - }; - }); - this.state = { - hotKeys: localHotKeys, + hotKeys: this.props.hotkeyDefinitions, errorMessages: {}, }; @@ -53,24 +36,28 @@ export class HotKeysPreferences extends Component { const { ctrlKey, altKey, shiftKey } = keyDownEvent; if (ctrlKey && !altKey) { - keysPressedArray.push('CTRL'); + keysPressedArray.push('ctrl'); } if (shiftKey && !altKey) { - keysPressedArray.push('SHIFT'); + keysPressedArray.push('shift'); } if (altKey && !ctrlKey) { - keysPressedArray.push('ALT'); + keysPressedArray.push('alt'); } return keysPressedArray; } - getConflictingCommand(currentToolKey, hotKeyCommand) { - return Object.keys(this.state.hotKeys).find(tool => { - const value = this.state.hotKeys[tool].command; - return value && value === hotKeyCommand && tool !== currentToolKey; + getConflictingCommand(currentCommandName, currentHotKeys) { + return this.state.hotKeys.find((tool, index) => { + const toolHotKeys = tool.keys[0]; + return ( + toolHotKeys && + toolHotKeys === currentHotKeys && + tool.commandName !== currentCommandName + ); }); } @@ -89,7 +76,7 @@ export class HotKeysPreferences extends Component { specialKeyName || keyDownEvent.key || String.fromCharCode(keyDownEvent.keyCode); - pressedKeys.push(keyName.toUpperCase()); + pressedKeys.push(keyName); } this.updateHotKeysState(commandName, pressedKeys.join('+')); @@ -136,17 +123,17 @@ export class HotKeysPreferences extends Component { const hotKey = this.state.hotKeys[hotKeyIndex]; const keys = hotKey.keys[0]; const pressedKeys = keys.split('+'); - const lastPressedKey = pressedKeys[pressedKeys.length - 1].toUpperCase(); + const lastPressedKey = pressedKeys[pressedKeys.length - 1]; // clear the prior errors this.setState({ errorMessages: {} }, () => { // Check if it has a valid modifier - const isModifier = ['CTRL', 'ALT', 'SHIFT'].includes(lastPressedKey); + const isModifier = ['ctrl', 'alt', 'shift'].includes(lastPressedKey); if (isModifier) { this.updateHotKeysState(commandName, ''); this.updateErrorsState( commandName, - "It's not possible to define only modifier keys (CTRL, ALT and SHIFT) as a shortcut" + "It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut" ); return; } @@ -154,21 +141,13 @@ export class HotKeysPreferences extends Component { /* * Check if it has some conflict */ - const conflictedCommandKey = this.getConflictingCommand( - commandName, - keys - ); - if (conflictedCommandKey) { - const conflictedCommand = this.state.hotKeys[conflictedCommandKey]; - + const conflictedCommand = this.getConflictingCommand(commandName, keys); + if (conflictedCommand) { + this.updateHotKeysState(commandName, ''); this.updateErrorsState( commandName, - `"${conflictedCommand.label}" is already using the "${ - conflictedCommand.command - }" shortcut.` + `"${conflictedCommand.label}" is already using the "${keys}" shortcut.` ); - this.updateErrorsState(conflictedCommandKey, ''); - this.updateHotKeysState(commandName, ''); return; } @@ -177,8 +156,7 @@ export class HotKeysPreferences extends Component { */ const modifierCommand = pressedKeys .slice(0, pressedKeys.length - 1) - .join('+') - .toUpperCase(); + .join('+'); const disallowedCombination = disallowedCombinations[modifierCommand]; const hasDisallowedCombinations = disallowedCombination @@ -189,7 +167,7 @@ export class HotKeysPreferences extends Component { this.updateHotKeysState(commandName, ''); this.updateErrorsState( commandName, - "It's not possible to define only modifier keys (CTRL, ALT and SHIFT) as a shortcut" + `"${pressedKeys.join('+')}" shortcut combination is not allowed` ); return; } diff --git a/platform/ui/src/components/userPreferencesModal/HotKeysPreferences.styl b/platform/ui/src/components/userPreferencesForm/HotKeysPreferences.styl similarity index 100% rename from platform/ui/src/components/userPreferencesModal/HotKeysPreferences.styl rename to platform/ui/src/components/userPreferencesForm/HotKeysPreferences.styl diff --git a/platform/ui/src/components/userPreferencesModal/UserPreferences.js b/platform/ui/src/components/userPreferencesForm/UserPreferences.js similarity index 82% rename from platform/ui/src/components/userPreferencesModal/UserPreferences.js rename to platform/ui/src/components/userPreferencesForm/UserPreferences.js index 584137e4c..9bcebe617 100644 --- a/platform/ui/src/components/userPreferencesModal/UserPreferences.js +++ b/platform/ui/src/components/userPreferencesForm/UserPreferences.js @@ -8,14 +8,14 @@ import './UserPreferences.styl'; export class UserPreferences extends Component { static defaultProps = { - hotKeysData: {}, + hotkeyDefinitions: [], windowLevelData: {}, generalData: {}, }; // TODO: Make this more generic. Tabs should not be restricted to these entries static propTypes = { - hotKeysData: PropTypes.object.isRequired, + hotkeyDefinitions: PropTypes.array.isRequired, windowLevelData: PropTypes.object.isRequired, generalData: PropTypes.object.isRequired, }; @@ -32,7 +32,9 @@ export class UserPreferences extends Component { return (
- +
); @@ -66,8 +68,8 @@ export class UserPreferences extends Component { switch (tabIndex) { case 0: return this.renderHotkeysTab(); - case 1: - return this.renderWindowLevelTab(); + /* case 1: + return this.renderWindowLevelTab(); */ case 2: return this.renderGeneralTab(); @@ -93,14 +95,16 @@ export class UserPreferences extends Component { > -
  • { - this.tabClick(1); - }} - className={this.getTabClass(1)} - > - -
  • + {false && ( +
  • { + this.tabClick(1); + }} + className={this.getTabClass(1)} + > + +
  • + )}
  • { this.tabClick(2); diff --git a/platform/ui/src/components/userPreferencesModal/UserPreferences.styl b/platform/ui/src/components/userPreferencesForm/UserPreferences.styl similarity index 100% rename from platform/ui/src/components/userPreferencesModal/UserPreferences.styl rename to platform/ui/src/components/userPreferencesForm/UserPreferences.styl diff --git a/platform/ui/src/components/userPreferencesForm/UserPreferencesForm.js b/platform/ui/src/components/userPreferencesForm/UserPreferencesForm.js new file mode 100644 index 000000000..d33626991 --- /dev/null +++ b/platform/ui/src/components/userPreferencesForm/UserPreferencesForm.js @@ -0,0 +1,86 @@ +import './UserPreferencesForm.styl'; + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { withTranslation } from '../../utils/LanguageProvider'; + +import cloneDeep from 'lodash.clonedeep'; +import isEqual from 'lodash.isequal'; +import { UserPreferences } from './UserPreferences'; + +class UserPreferencesForm extends Component { + // TODO: Make this component more generic to allow things other than W/L and hotkeys... + static propTypes = { + onClose: PropTypes.func, + onSave: PropTypes.func, + onResetToDefaults: PropTypes.func, + windowLevelData: PropTypes.object, + hotkeyDefinitions: PropTypes.array, + t: PropTypes.func, + }; + + constructor(props) { + super(props); + + this.state = { + windowLevelData: cloneDeep(props.windowLevelData), + hotkeyDefinitions: cloneDeep(props.hotkeyDefinitions), + }; + } + + save = () => { + this.props.onSave({ + windowLevelData: this.state.windowLevelData, + hotkeyDefinitions: this.state.hotkeyDefinitions, + }); + }; + + componentDidUpdate(prev, next) { + const newStateData = {}; + + if (!isEqual(prev.windowLevelData, next.windowLevelData)) { + newStateData.windowLevelData = prev.windowLevelData; + } + + if (!isEqual(prev.hotkeyDefinitions, next.hotkeyDefinitions)) { + newStateData.hotkeyDefinitions = prev.hotkeyDefinitions; + } + + if (newStateData.hotkeyDefinitions || newStateData.windowLevelData) { + this.setState(newStateData); + } + } + + render() { + return ( +
    + +
    + +
    +
    + {this.props.t('Cancel')} +
    + +
    +
    +
    + ); + } +} + +const connectedComponent = withTranslation('UserPreferencesForm')( + UserPreferencesForm +); +export { connectedComponent as UserPreferencesForm }; +export default connectedComponent; diff --git a/platform/ui/src/components/userPreferencesModal/UserPreferencesModal.styl b/platform/ui/src/components/userPreferencesForm/UserPreferencesForm.styl similarity index 64% rename from platform/ui/src/components/userPreferencesModal/UserPreferencesModal.styl rename to platform/ui/src/components/userPreferencesForm/UserPreferencesForm.styl index 0dea62f53..6a62b1b08 100644 --- a/platform/ui/src/components/userPreferencesModal/UserPreferencesModal.styl +++ b/platform/ui/src/components/userPreferencesForm/UserPreferencesForm.styl @@ -12,6 +12,13 @@ text-shadow: 0 1px 0 #fff; opacity: .2; -.ModalHeader - ol, ul - margin-top: 0; +.UserPreferencesForm + .footer + display: flex + flex-direction: row + padding-bottom: 20px + justify-content: space-between + + div + button:last-child + margin-left: 10px diff --git a/platform/ui/src/components/userPreferencesModal/WindowLevelPreferences.js b/platform/ui/src/components/userPreferencesForm/WindowLevelPreferences.js similarity index 100% rename from platform/ui/src/components/userPreferencesModal/WindowLevelPreferences.js rename to platform/ui/src/components/userPreferencesForm/WindowLevelPreferences.js diff --git a/platform/ui/src/components/userPreferencesModal/WindowLevelPreferences.styl b/platform/ui/src/components/userPreferencesForm/WindowLevelPreferences.styl similarity index 100% rename from platform/ui/src/components/userPreferencesModal/WindowLevelPreferences.styl rename to platform/ui/src/components/userPreferencesForm/WindowLevelPreferences.styl diff --git a/platform/ui/src/components/userPreferencesModal/__docs__/about.mdx b/platform/ui/src/components/userPreferencesForm/__docs__/about.mdx similarity index 100% rename from platform/ui/src/components/userPreferencesModal/__docs__/about.mdx rename to platform/ui/src/components/userPreferencesForm/__docs__/about.mdx diff --git a/platform/ui/src/components/userPreferencesModal/__docs__/generalDefaults.js b/platform/ui/src/components/userPreferencesForm/__docs__/generalDefaults.js similarity index 100% rename from platform/ui/src/components/userPreferencesModal/__docs__/generalDefaults.js rename to platform/ui/src/components/userPreferencesForm/__docs__/generalDefaults.js diff --git a/platform/ui/src/components/userPreferencesModal/__docs__/hotkeyDefaults.js b/platform/ui/src/components/userPreferencesForm/__docs__/hotkeyDefaults.js similarity index 100% rename from platform/ui/src/components/userPreferencesModal/__docs__/hotkeyDefaults.js rename to platform/ui/src/components/userPreferencesForm/__docs__/hotkeyDefaults.js diff --git a/platform/ui/src/components/userPreferencesModal/__docs__/userPreferences.mdx b/platform/ui/src/components/userPreferencesForm/__docs__/userPreferences.mdx similarity index 77% rename from platform/ui/src/components/userPreferencesModal/__docs__/userPreferences.mdx rename to platform/ui/src/components/userPreferencesForm/__docs__/userPreferences.mdx index 60b5ff69f..8bff79a90 100644 --- a/platform/ui/src/components/userPreferencesModal/__docs__/userPreferences.mdx +++ b/platform/ui/src/components/userPreferencesForm/__docs__/userPreferences.mdx @@ -1,18 +1,18 @@ --- -name: User Preferences Modal +name: User Preferences Form menu: Components -route: /components/user-preferences-modal +route: /components/user-preferences-form --- import { Playground, Props } from 'docz' import { State } from 'react-powerplug' -import { UserPreferencesModal } from './../index.js' +import { UserPreferencesForm } from './../index.js' import NameSpace from '../../../__docs__/NameSpace' // import windowLevelDefaults from './windowLevelDefaults.js' import hotkeyDefaults from './hotkeyDefaults.js' -# User Preferences Modal +# User Preferences Form ## Basic usage @@ -20,7 +20,7 @@ import hotkeyDefaults from './hotkeyDefaults.js' {({ state, setState }) => ( @@ -32,7 +32,7 @@ import hotkeyDefaults from './hotkeyDefaults.js' > Open user preferences - setState({ isOpen: false })} onSave={() => alert('on save')} @@ -47,8 +47,8 @@ import hotkeyDefaults from './hotkeyDefaults.js' ## API - + ## Translation Namespace - + diff --git a/platform/ui/src/components/userPreferencesModal/__docs__/windowLevelDefaults.js b/platform/ui/src/components/userPreferencesForm/__docs__/windowLevelDefaults.js similarity index 100% rename from platform/ui/src/components/userPreferencesModal/__docs__/windowLevelDefaults.js rename to platform/ui/src/components/userPreferencesForm/__docs__/windowLevelDefaults.js diff --git a/platform/ui/src/components/userPreferencesModal/hotKeysConfig.js b/platform/ui/src/components/userPreferencesForm/hotKeysConfig.js similarity index 74% rename from platform/ui/src/components/userPreferencesModal/hotKeysConfig.js rename to platform/ui/src/components/userPreferencesForm/hotKeysConfig.js index cb3cd51f8..9a0b2a2af 100644 --- a/platform/ui/src/components/userPreferencesModal/hotKeysConfig.js +++ b/platform/ui/src/components/userPreferencesForm/hotKeysConfig.js @@ -4,38 +4,38 @@ const range = (start, end) => { export const disallowedCombinations = { '': [], - ALT: ['SPACE'], - SHIFT: [], - CTRL: [ - 'F4', - 'F5', - 'F11', - 'W', - 'R', - 'T', - 'O', - 'P', - 'A', - 'D', - 'F', - 'G', - 'H', - 'J', - 'L', - 'Z', - 'X', - 'C', - 'V', - 'B', - 'N', - 'PAGEDOWN', - 'PAGEUP', + alt: ['space'], + shift: [], + ctrl: [ + 'f4', + 'f5', + 'f11', + 'w', + 'r', + 't', + 'o', + 'p', + 'a', + 'd', + 'f', + 'g', + 'h', + 'j', + 'l', + 'z', + 'x', + 'c', + 'v', + 'b', + 'n', + 'pagedown', + 'pageup', ], - 'CTRL+SHIFT': ['Q', 'W', 'R', 'T', 'P', 'A', 'H', 'V', 'B', 'N'], + 'ctrl+shift': ['q', 'w', 'r', 't', 'p', 'a', 'h', 'v', 'b', 'n'], }; export const allowedKeys = [ - ...[8, 13, 27, 32, 46], // BACKSPACE, ENTER, ESCAPE, SPACE, DELETE + ...[8, 13, 27, 32, 46], // backspace, enter, escape, space, delete ...[12, 106, 107, 109, 110, 111], // Numpad keys ...range(218, 220), // [\] ...range(185, 190), // ;=,-./ diff --git a/platform/ui/src/components/userPreferencesModal/index.js b/platform/ui/src/components/userPreferencesForm/index.js similarity index 74% rename from platform/ui/src/components/userPreferencesModal/index.js rename to platform/ui/src/components/userPreferencesForm/index.js index d1a9c2a7b..06e18ab08 100644 --- a/platform/ui/src/components/userPreferencesModal/index.js +++ b/platform/ui/src/components/userPreferencesForm/index.js @@ -1,4 +1,4 @@ export { UserPreferences } from './UserPreferences.js'; export { AboutContent } from '../content/aboutContent/AboutContent.js'; -export { UserPreferencesModal } from './UserPreferencesModal.js'; +export { UserPreferencesForm } from './UserPreferencesForm.js'; export { GeneralPreferences } from './GeneralPreferences.js'; diff --git a/platform/ui/src/components/userPreferencesModal/UserPreferencesModal.js b/platform/ui/src/components/userPreferencesModal/UserPreferencesModal.js deleted file mode 100644 index 0b54504dd..000000000 --- a/platform/ui/src/components/userPreferencesModal/UserPreferencesModal.js +++ /dev/null @@ -1,107 +0,0 @@ -import './UserPreferencesModal.styl'; - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import Modal from 'react-bootstrap-modal'; -import { withTranslation } from '../../utils/LanguageProvider'; - -import 'react-bootstrap-modal/lib/css/rbm-patch.css'; -import cloneDeep from 'lodash.clonedeep'; -import isEqual from 'lodash.isequal'; -import { UserPreferences } from './UserPreferences'; - -// TODO: Is this the only component importing these? -import './../../design/styles/common/modal.styl'; - -class UserPreferencesModal extends Component { - // TODO: Make this component more generic to allow things other than W/L and hotkeys... - static propTypes = { - isOpen: PropTypes.bool.isRequired, - onCancel: PropTypes.func, - onSave: PropTypes.func, - onResetToDefaults: PropTypes.func, - windowLevelData: PropTypes.object, - hotKeysData: PropTypes.object, - t: PropTypes.func, - }; - - constructor(props) { - super(props); - - this.state = { - windowLevelData: cloneDeep(props.windowLevelData), - hotKeysData: cloneDeep(props.hotKeysData), - }; - } - - static defaultProps = { - isOpen: false, - }; - - save = () => { - this.props.onSave({ - windowLevelData: this.state.windowLevelData, - hotKeysData: this.state.hotKeysData, - }); - }; - - componentDidUpdate(prev, next) { - const newStateData = {}; - - if (!isEqual(prev.windowLevelData, next.windowLevelData)) { - newStateData.windowLevelData = prev.windowLevelData; - } - - if (!isEqual(prev.hotKeysData, next.hotKeysData)) { - newStateData.hotKeysData = prev.hotKeysData; - } - - if (newStateData.hotKeysData || newStateData.windowLevelData) { - this.setState(newStateData); - } - } - - render() { - return ( - - - {this.props.t('User Preferences')} - - - - - - - - {this.props.t('Cancel')} - - - - - ); - } -} - -const connectedComponent = withTranslation('UserPreferencesModal')( - UserPreferencesModal -); -export { connectedComponent as UserPreferencesModal }; -export default connectedComponent; diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js index c608b4521..191620d71 100644 --- a/platform/ui/src/index.js +++ b/platform/ui/src/index.js @@ -24,7 +24,7 @@ import { Tooltip, AboutContent, UserPreferences, - UserPreferencesModal, + UserPreferencesForm, OHIFModal, } from './components'; import { useDebounce, useMedia } from './hooks'; @@ -101,7 +101,7 @@ export { Tooltip, AboutContent, UserPreferences, - UserPreferencesModal, + UserPreferencesForm, ViewerbaseDragDropContext, SnackbarProvider, useSnackbarContext, diff --git a/platform/viewer/cypress/integration/common/OHIFStudyViewer.spec.js b/platform/viewer/cypress/integration/common/OHIFStudyViewer.spec.js index a58ea1004..54f7dc0f3 100644 --- a/platform/viewer/cypress/integration/common/OHIFStudyViewer.spec.js +++ b/platform/viewer/cypress/integration/common/OHIFStudyViewer.spec.js @@ -267,8 +267,12 @@ describe('OHIF Study Viewer Page', function() { }); it('opens About modal and verify the displayed information', function() { - cy.get('[data-cy="options-menu"]').click(); - cy.get('[data-cy="about-item-menu"]').click(); + cy.get('[data-cy="options-menu"]') + .first() + .click(); + cy.get('[data-cy="about-item-menu"]') + .first() + .click(); cy.get('.modal-content') .as('aboutOverlay') .should('be.visible'); diff --git a/platform/viewer/src/components/Header/Header.css b/platform/viewer/src/components/Header/Header.css index 0ced9e7c4..d356665c5 100644 --- a/platform/viewer/src/components/Header/Header.css +++ b/platform/viewer/src/components/Header/Header.css @@ -4,6 +4,10 @@ height: var(--top-bar-height); } +.dd-item { + width: 100%; +} + /* Home Page */ .entry-header.header-big { background: rgba(21, 25, 30, 0.7); diff --git a/platform/viewer/src/components/Header/Header.js b/platform/viewer/src/components/Header/Header.js index a37b136e3..882c065d5 100644 --- a/platform/viewer/src/components/Header/Header.js +++ b/platform/viewer/src/components/Header/Header.js @@ -3,13 +3,11 @@ import { Link, withRouter } from 'react-router-dom'; import { withTranslation } from 'react-i18next'; import PropTypes from 'prop-types'; -import { Dropdown } from '@ohif/ui'; -import { AboutContent } from '@ohif/ui'; -import { withModal } from '@ohif/ui'; - +import ConnectedUserPreferencesForm from '../../connectedComponents/ConnectedUserPreferencesForm'; +import { Dropdown, AboutContent, withModal } from '@ohif/ui'; import OHIFLogo from '../OHIFLogo/OHIFLogo.js'; -import { hotkeysManager } from './../../App.js'; import './Header.css'; + // Context import AppContext from './../../context/AppContext'; @@ -30,23 +28,9 @@ class Header extends Component { children: OHIFLogo(), }; - // onSave: data => { - // const contextName = store.getState().commandContext.context; - // const preferences = cloneDeep(store.getState().preferences); - // preferences[contextName] = data; - // dispatch(setUserPreferences(preferences)); - // dispatch(setUserPreferencesModalOpen(false)); - // OHIF.hotkeysUtil.setHotkeys(data.hotKeysData); - // }, - // onResetToDefaults: () => { - // dispatch(setUserPreferences()); - // dispatch(setUserPreferencesModalOpen(false)); - // OHIF.hotkeysUtil.setHotkeys(); - // }, - constructor(props) { super(props); - this.state = { isUserPreferencesOpen: false, isOpen: false }; + this.state = { isOpen: false }; this.loadOptions(); } @@ -68,6 +52,16 @@ class Header extends Component { customClassName: 'AboutContent', }), }, + { + title: 'Preferences ', + icon: { + name: 'user', + }, + onClick: () => + show(ConnectedUserPreferencesForm, { + title: t('User Preferences'), + }), + }, ]; if (user && userManager) { @@ -77,15 +71,6 @@ class Header extends Component { onClick: () => userManager.signoutRedirect(), }); } - - this.hotKeysData = hotkeysManager.hotkeyDefinitions; - } - - onUserPreferencesSave({ windowLevelData, hotKeysData }) { - // console.log(windowLevelData); - // console.log(hotKeysData); - // TODO: Update hotkeysManager - // TODO: reset `this.hotKeysData` } // ANTD -- Hamburger, Drawer, Menu diff --git a/platform/viewer/src/connectedComponents/ConnectedHeader.js b/platform/viewer/src/connectedComponents/ConnectedHeader.js index 74425cca1..0a47c045f 100644 --- a/platform/viewer/src/connectedComponents/ConnectedHeader.js +++ b/platform/viewer/src/connectedComponents/ConnectedHeader.js @@ -1,10 +1,16 @@ import Header from '../components/Header/Header.js'; import { connect } from 'react-redux'; +import { hotkeysManager } from '../App.js'; const mapStateToProps = state => { + const hotkeyDefinitions = + state.preferences.hotkeyDefinitions.length > 0 + ? state.preferences.hotkeyDefinitions + : hotkeysManager.hotkeyDefaults; + hotkeysManager.setHotkeys(hotkeyDefinitions); + return { user: state.oidc && state.oidc.user, - isOpen: state.ui.userPreferencesModalOpen, }; }; diff --git a/platform/viewer/src/connectedComponents/ConnectedUserPreferencesForm.js b/platform/viewer/src/connectedComponents/ConnectedUserPreferencesForm.js new file mode 100644 index 000000000..f1ceedce8 --- /dev/null +++ b/platform/viewer/src/connectedComponents/ConnectedUserPreferencesForm.js @@ -0,0 +1,41 @@ +import { connect } from 'react-redux'; +import { UserPreferencesForm } from '@ohif/ui'; +import OHIF from '@ohif/core'; +import { hotkeysManager } from '../App.js'; + +const { setUserPreferences } = OHIF.redux.actions; + +const mapStateToProps = (state, ownProps) => { + const hotkeyDefinitions = + state.preferences.hotkeyDefinitions.length > 0 + ? state.preferences.hotkeyDefinitions + : hotkeysManager.hotkeyDefaults; + hotkeysManager.setHotkeys(hotkeyDefinitions); + return { + onClose: ownProps.hide, + windowLevelData: state.preferences ? state.preferences.windowLevelData : {}, + hotkeyDefinitions, + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + onSave: ({ windowLevelData, hotkeyDefinitions }) => { + hotkeysManager.setHotkeys(hotkeyDefinitions); + ownProps.hide(); + dispatch(setUserPreferences({ windowLevelData, hotkeyDefinitions })); + }, + onResetToDefaults: () => { + hotkeysManager.restoreDefaultBindings(); + ownProps.hide(); + dispatch(setUserPreferences()); + }, + }; +}; + +const ConnectedUserPreferencesForm = connect( + mapStateToProps, + mapDispatchToProps +)(UserPreferencesForm); + +export default ConnectedUserPreferencesForm;