fix: Several new worklist issues (#6130)
* fix: Several new worklist issues * refactor: Export a single OnStudyDoubleClick type from the StudyList barrel Addresses PR review feedback: the double-click handler signature was written out in both TableProps and the WorkList customization cast, so the two could drift apart. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: Run worklist study double-click as a command, registrable by modes - Modes can now export getCommandsModule on their definition; appInit registers it (via the new ExtensionManager.registerCommandsModule) before the mode is instantiated, in a new 'WORKLIST' commands context, so the commands are available on the worklist before any mode route is entered. - The workList.onStudyDoubleClick customization is now a command run input (name/options) instead of a bare function, defaulting to the new launchDefaultMode command, which launches the default workflow falling back to the first applicable one. commandOptions.workflowId overrides it to a specific mode. - Duplicate mode ids are now skipped before running their modeFactory rather than after. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dbb8b1526e
commit
6b6761088b
11 files changed
+230
-27
No files matched your search
+30
-10
@@ -130,19 +130,39 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
|
||||
}
|
||||
const { id } = mode;
|
||||
|
||||
if (mode.modeFactory) {
|
||||
// If the appConfig contains configuration for this mode, use it.
|
||||
const modeConfiguration =
|
||||
appConfig.modesConfiguration && appConfig.modesConfiguration[id]
|
||||
? appConfig.modesConfiguration[id]
|
||||
: {};
|
||||
|
||||
mode = await mode.modeFactory({ modeConfiguration, loadModules });
|
||||
}
|
||||
|
||||
if (modesById.has(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the appConfig contains configuration for this mode, use it.
|
||||
const modeConfiguration =
|
||||
appConfig.modesConfiguration && appConfig.modesConfiguration[id]
|
||||
? appConfig.modesConfiguration[id]
|
||||
: {};
|
||||
|
||||
// Mirrors the extension commands path for modes, but registers before the
|
||||
// mode is instantiated so the commands are usable on the worklist, ahead
|
||||
// of any mode route being entered. Definitions land in the 'WORKLIST'
|
||||
// context unless the module (or an individual command) declares its own.
|
||||
if (typeof mode.getCommandsModule === 'function') {
|
||||
extensionManager.registerCommandsModule(
|
||||
mode.getCommandsModule({
|
||||
appConfig,
|
||||
commandsManager,
|
||||
servicesManager,
|
||||
serviceProvidersManager,
|
||||
hotkeysManager,
|
||||
extensionManager,
|
||||
modeConfiguration,
|
||||
}),
|
||||
'WORKLIST'
|
||||
);
|
||||
}
|
||||
|
||||
if (mode.modeFactory) {
|
||||
mode = await mode.modeFactory({ modeConfiguration, loadModules });
|
||||
}
|
||||
|
||||
// Prevent duplication
|
||||
modesById.add(id);
|
||||
if (!mode || typeof mode !== 'object') {
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { useAppConfig } from '@state';
|
||||
import type { RunInput } from '@ohif/core/src/classes/CommandsManager';
|
||||
import { preserveQueryParameters } from '../../utils/preserveQueryParameters';
|
||||
import { useStudyListStateSync, useWorkListToolbarActions } from '../../hooks';
|
||||
|
||||
import { StudyList, Icons, InvestigationalUseDialog, type StudyRow } from '@ohif/ui-next';
|
||||
import {
|
||||
StudyList,
|
||||
Icons,
|
||||
InvestigationalUseDialog,
|
||||
type StudyRow,
|
||||
type OnStudyDoubleClick,
|
||||
} from '@ohif/ui-next';
|
||||
import { StudyListSettingsPopover } from './StudyListSettingsPopover';
|
||||
import { SidePanelPreview } from './SidePanelPreview';
|
||||
|
||||
@@ -26,6 +33,7 @@ export default function WorkList({
|
||||
onRefresh,
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
commandsManager,
|
||||
}: Props) {
|
||||
const [appConfig] = useAppConfig();
|
||||
const { customizationService } = servicesManager.services;
|
||||
@@ -47,6 +55,22 @@ export default function WorkList({
|
||||
const [selected, setSelected] = useState<StudyRow | null>(null);
|
||||
const [isPreviewOpen, setPreviewOpen] = useState(true);
|
||||
|
||||
// `workList.onStudyDoubleClick` is the command (or command list) run when a
|
||||
// study row is double-clicked — by default `launchDefaultMode`, which
|
||||
// launches the default workflow, falling back to the first applicable one.
|
||||
// The study and its applicable workflows are merged into the command options
|
||||
// at call time, so an override only needs to name a command and any static
|
||||
// options (e.g. a specific `workflowId`).
|
||||
const studyDoubleClickCommand = customizationService.getCustomization(
|
||||
'workList.onStudyDoubleClick'
|
||||
) as RunInput;
|
||||
const onStudyDoubleClick = useCallback<OnStudyDoubleClick>(
|
||||
(study, { defaultWorkflow, workflows }) => {
|
||||
commandsManager.run(studyDoubleClickCommand, { study, defaultWorkflow, workflows });
|
||||
},
|
||||
[commandsManager, studyDoubleClickCommand]
|
||||
);
|
||||
|
||||
const columns = useMemo(() => {
|
||||
// `workList.columns` is registered as a value (StudyList.defaultColumns) and
|
||||
// merged via customization commands, so we read the result directly.
|
||||
@@ -122,6 +146,7 @@ export default function WorkList({
|
||||
)
|
||||
}
|
||||
title={'Study List'}
|
||||
onStudyDoubleClick={studyDoubleClickCommand ? onStudyDoubleClick : undefined}
|
||||
onSelectionChange={sel => setSelected((sel as StudyRow[])[0] ?? null)}
|
||||
toolbarLeftComponent={logoComponent}
|
||||
toolbarRightActionsComponent={toolbarActions}
|
||||
|
||||
@@ -131,7 +131,7 @@ const createRoutes = ({
|
||||
path: '/',
|
||||
children: DataSourceWrapper,
|
||||
private: true,
|
||||
props: { children: WorkListComponent, servicesManager, extensionManager },
|
||||
props: { children: WorkListComponent, servicesManager, extensionManager, commandsManager },
|
||||
};
|
||||
|
||||
const customRoutes = customizationService.getCustomization('routes.customRoutes');
|
||||
|
||||
Reference in new issue
Block a user