diff --git a/modes/basic-dev-mode/src/index.js b/modes/basic-dev-mode/src/index.js index c252265909f..bcedc4aca8f 100644 --- a/modes/basic-dev-mode/src/index.js +++ b/modes/basic-dev-mode/src/index.js @@ -152,7 +152,10 @@ function modeFactory({ modeConfiguration }) { const modalities_list = modalities.split('\\'); // Slide Microscopy modality not supported by basic mode yet - return !modalities_list.includes('SM'); + return { + valid: !modalities_list.includes('SM'), + description: 'The mode does not support the following modalities: SM', + }; }, routes: [ { diff --git a/modes/basic-test-mode/src/index.ts b/modes/basic-test-mode/src/index.ts index 64a607d9a09..a6e9d0827ad 100644 --- a/modes/basic-test-mode/src/index.ts +++ b/modes/basic-test-mode/src/index.ts @@ -163,8 +163,12 @@ function modeFactory() { const modalities_list = modalities.split('\\'); // Exclude non-image modalities - return !!modalities_list.filter(modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1) - .length; + return { + valid: !!modalities_list.filter(modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1) + .length, + description: + 'The mode does not support studies that ONLY include the following modalities: SM, ECG, SR, SEG', + }; }, routes: [ { diff --git a/modes/longitudinal/src/index.js b/modes/longitudinal/src/index.js index 1052cbfd8e9..571d6a5f69e 100644 --- a/modes/longitudinal/src/index.js +++ b/modes/longitudinal/src/index.js @@ -202,8 +202,12 @@ function modeFactory({ modeConfiguration }) { const modalities_list = modalities.split('\\'); // Exclude non-image modalities - return !!modalities_list.filter(modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1) - .length; + return { + valid: !!modalities_list.filter(modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1) + .length, + description: + 'The mode does not support studies that ONLY include the following modalities: SM, ECG, SR, SEG, RTSTRUCT', + }; }, routes: [ { diff --git a/modes/microscopy/src/index.tsx b/modes/microscopy/src/index.tsx index d9ed5b54d41..557ec00d03b 100644 --- a/modes/microscopy/src/index.tsx +++ b/modes/microscopy/src/index.tsx @@ -71,8 +71,10 @@ function modeFactory({ modeConfiguration }) { isValidMode: ({ modalities }) => { const modalities_list = modalities.split('\\'); - // Slide Microscopy and ECG modality not supported by basic mode yet - return modalities_list.includes('SM'); + return { + valid: modalities_list.includes('SM'), + description: 'Microscopy mode only supports the SM modality', + }; }, routes: [ diff --git a/modes/segmentation/src/index.tsx b/modes/segmentation/src/index.tsx index 446f45b5666..57b46c60357 100644 --- a/modes/segmentation/src/index.tsx +++ b/modes/segmentation/src/index.tsx @@ -131,11 +131,10 @@ function modeFactory({ modeConfiguration }) { // Don't show the mode if the selected studies have only one modality // that is not supported by the mode const modalitiesArray = modalities.split('\\'); - if (modalitiesArray.length === 1) { - return !['SM', 'US', 'MG', 'OT', 'DOC', 'CR'].includes(modalitiesArray[0]); + return { + valid: modalitiesArray.length === 1 ? !['SM', 'US', 'MG', 'OT', 'DOC', 'CR'].includes(modalitiesArray[0]) : true, + description: 'The mode does not support studies that ONLY include the following modalities: SM, US, MG, OT, DOC, CR', } - - return true; }, /** * Mode Routes are used to define the mode's behavior. A list of Mode Route diff --git a/modes/tmtv/src/index.js b/modes/tmtv/src/index.js index 7796fae6caa..b21a375828c 100644 --- a/modes/tmtv/src/index.js +++ b/modes/tmtv/src/index.js @@ -197,7 +197,10 @@ function modeFactory({ modeConfiguration }) { study.studyInstanceUid !== '1.3.6.1.4.1.12842.1.1.14.3.20220915.105557.468.2963630849'; // there should be both CT and PT modalities and the modality should not be SM - return isValid; + return { + valid: isValid, + description: 'The mode requires both PT and CT series in the study', + }; }, routes: [ { diff --git a/platform/app/public/config/default.js b/platform/app/public/config/default.js index 00013529ea8..88f7b872e12 100644 --- a/platform/app/public/config/default.js +++ b/platform/app/public/config/default.js @@ -12,6 +12,7 @@ window.config = { showCPUFallbackMessage: true, showLoadingIndicator: true, strictZSpacingForVolumeViewport: true, + groupEnabledModesFirst: true, maxNumRequests: { interaction: 100, thumbnail: 75, diff --git a/platform/app/src/routes/WorkList/WorkList.tsx b/platform/app/src/routes/WorkList/WorkList.tsx index db022c83c8f..50cfccf2961 100644 --- a/platform/app/src/routes/WorkList/WorkList.tsx +++ b/platform/app/src/routes/WorkList/WorkList.tsx @@ -350,10 +350,24 @@ function WorkList({ } >
- {appConfig.loadedModes.map((mode, i) => { + {(appConfig.groupEnabledModesFirst + ? appConfig.loadedModes.sort((a, b) => { + const isValidA = a.isValidMode({ + modalities: modalities.replaceAll('/', '\\'), + study, + }).valid; + const isValidB = b.isValidMode({ + modalities: modalities.replaceAll('/', '\\'), + study, + }).valid; + + return isValidB - isValidA; + }) + : appConfig.loadedModes + ).map((mode, i) => { const modalitiesToCheck = modalities.replaceAll('/', '\\'); - const isValidMode = mode.isValidMode({ + const { valid: isValidMode, description: invalidModeDescription } = mode.isValidMode({ modalities: modalitiesToCheck, study, }); @@ -390,11 +404,10 @@ function WorkList({ type={ButtonEnums.type.primary} size={ButtonEnums.size.medium} disabled={!isValidMode} - tooltip={ + startIconTooltip={ !isValidMode ? (
- This study does not contain modalities supported by {mode.displayName}{' '} - mode + {invalidModeDescription}
) : null } diff --git a/platform/ui/src/components/Button/Button.tsx b/platform/ui/src/components/Button/Button.tsx index 39e4931163b..b1e750c5cb7 100644 --- a/platform/ui/src/components/Button/Button.tsx +++ b/platform/ui/src/components/Button/Button.tsx @@ -67,7 +67,8 @@ const Button = ({ name, className, onClick, - tooltip = null, + startIconTooltip = null, + endIconTooltip = null, }) => { const startIcon = startIconProp && ( <> @@ -110,9 +111,9 @@ const Button = ({ onClick={handleOnClick} data-cy={`${name}-btn`} > - {tooltip ? {startIcon} : startIcon} + {startIconTooltip ? {startIcon} : startIcon} {children} - {endIcon} + {endIconTooltip ? {endIcon} : endIcon} ); }; @@ -143,8 +144,10 @@ Button.propTypes = { endIcon: PropTypes.node, /** Additional TailwindCSS classnames */ className: PropTypes.string, - /** Tooltip for the button */ - tooltip: PropTypes.node, + /** Tooltip for the start icon */ + startIconTooltip: PropTypes.node, + /** Tooltip for the end icon */ + endIconTooltip: PropTypes.node, }; export default Button; diff --git a/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx b/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx index 2235f277d1c..4a3fa6f9316 100644 --- a/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx +++ b/platform/ui/src/components/StudyListTable/StudyListTableRow.tsx @@ -23,7 +23,7 @@ const StudyListTableRow = props => { className={classnames( 'w-full transition duration-300', { - 'border-primary-light hover:border-secondary-light mb-2 overflow-hidden rounded border': + 'border-primary-light hover:border-secondary-light mb-2 overflow-visible rounded border': isExpanded, }, {