feat: Group findings table values with custom components/grouping functions (#4712)
This commit is contained in:
1 parent
0522d58d9b
commit
df8efba82c
48 files changed
+1256
-631
No files matched your search
@@ -24,7 +24,7 @@ function DataSourceConfigurationComponent({
|
||||
const dataSourceChangedCallback = async () => {
|
||||
const activeDataSourceDef = extensionManager.getActiveDataSourceDefinition();
|
||||
|
||||
if (!activeDataSourceDef.configuration.configurationAPI) {
|
||||
if (!activeDataSourceDef?.configuration?.configurationAPI) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ export default function CreateReportDialogPrompt({
|
||||
dataSourceName: undefined,
|
||||
});
|
||||
},
|
||||
defaultValue: title,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ import { useToggleHangingProtocolStore } from './stores/useToggleHangingProtocol
|
||||
import { useViewportsByPositionStore } from './stores/useViewportsByPositionStore';
|
||||
import { useToggleOneUpViewportGridStore } from './stores/useToggleOneUpViewportGridStore';
|
||||
import requestDisplaySetCreationForStudy from './Panels/requestDisplaySetCreationForStudy';
|
||||
import promptSaveReport from './utils/promptSaveReport';
|
||||
|
||||
export type HangingProtocolParams = {
|
||||
protocolId?: string;
|
||||
@@ -75,6 +76,14 @@ const commandsModule = ({
|
||||
}
|
||||
},
|
||||
|
||||
/** Displays a prompt and then save the report if relevant */
|
||||
promptSaveReport: props => {
|
||||
const { StudyInstanceUID } = props;
|
||||
promptSaveReport({ servicesManager, commandsManager, extensionManager }, props, {
|
||||
data: { StudyInstanceUID },
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensures that the specified study is available for display
|
||||
* Then, if commands is specified, runs the given commands list/instance
|
||||
@@ -140,8 +149,9 @@ const commandsModule = ({
|
||||
type: type,
|
||||
});
|
||||
},
|
||||
clearMeasurements: () => {
|
||||
measurementService.clearMeasurements();
|
||||
|
||||
clearMeasurements: options => {
|
||||
measurementService.clearMeasurements(options.measurementFilter);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -340,7 +350,6 @@ const commandsModule = ({
|
||||
const { protocol } = hangingProtocolService.getActiveProtocol();
|
||||
const onLayoutChange = protocol.callbacks?.onLayoutChange;
|
||||
if (commandsManager.run(onLayoutChange, { numRows, numCols }) === false) {
|
||||
console.log('setViewportGridLayout running', onLayoutChange, numRows, numCols);
|
||||
// Don't apply the layout if the run command returns false
|
||||
return;
|
||||
}
|
||||
@@ -621,6 +630,7 @@ const commandsModule = ({
|
||||
|
||||
const definitions = {
|
||||
multimonitor: actions.multimonitor,
|
||||
promptSaveReport: actions.promptSaveReport,
|
||||
loadStudy: actions.loadStudy,
|
||||
showContextMenu: actions.showContextMenu,
|
||||
closeContextMenu: actions.closeContextMenu,
|
||||
|
||||
@@ -94,12 +94,12 @@ export async function callInputDialogAutoComplete({
|
||||
const dropDownItems = labelConfig ? labelConfig.items : [];
|
||||
|
||||
const value = await new Promise<Map<string, string>>((resolve, reject) => {
|
||||
const labellingDoneCallback = value => {
|
||||
const labellingDoneCallback = newValue => {
|
||||
uiDialogService.hide('select-annotation');
|
||||
if (typeof value === 'string') {
|
||||
measurement.label = value;
|
||||
if (measurement && typeof newValue === 'string') {
|
||||
measurement.label = newValue;
|
||||
}
|
||||
resolve(measurement);
|
||||
resolve(newValue);
|
||||
};
|
||||
|
||||
uiDialogService.show({
|
||||
|
||||
@@ -1,58 +1,76 @@
|
||||
import { utils } from '@ohif/core';
|
||||
|
||||
import createReportAsync from '../Actions/createReportAsync';
|
||||
import { createReportDialogPrompt } from '../Panels';
|
||||
import getNextSRSeriesNumber from './getNextSRSeriesNumber';
|
||||
import PROMPT_RESPONSES from './_shared/PROMPT_RESPONSES';
|
||||
import createReportDialogPrompt from '../Panels/createReportDialogPrompt';
|
||||
|
||||
/**
|
||||
* Prompts the user to save a report and handles the report creation process
|
||||
* @param services - Object containing required services and managers
|
||||
* @param ctx - The current context containing tracked study and series information
|
||||
* @param evt - The event object containing viewport and save-related data
|
||||
*/
|
||||
async function promptSaveReport(services, ctx, evt) {
|
||||
const { servicesManager, extensionManager, commandsManager } = services;
|
||||
const {
|
||||
filterAnd,
|
||||
filterMeasurementsByStudyUID,
|
||||
filterMeasurementsBySeriesUID,
|
||||
filterPlanarMeasurement,
|
||||
} = utils.MeasurementFilters;
|
||||
|
||||
async function promptSaveReport({ servicesManager, commandsManager, extensionManager }, ctx, evt) {
|
||||
const { measurementService, displaySetService } = servicesManager.services;
|
||||
|
||||
const viewportId = evt.viewportId ?? evt.data?.viewportId;
|
||||
const isBackupSave = evt.isBackupSave ?? evt.data?.isBackupSave;
|
||||
const { StudyInstanceUID, SeriesInstanceUID } = evt?.data ?? {};
|
||||
|
||||
const { trackedStudy, trackedSeries } = ctx;
|
||||
const dataSources = extensionManager.getDataSources();
|
||||
const viewportId = evt.viewportId === undefined ? evt.data.viewportId : evt.viewportId;
|
||||
const isBackupSave = evt.isBackupSave === undefined ? evt.data.isBackupSave : evt.isBackupSave;
|
||||
const StudyInstanceUID = evt?.data?.StudyInstanceUID || ctx.trackedStudy;
|
||||
const SeriesInstanceUID = evt?.data?.SeriesInstanceUID;
|
||||
|
||||
const {
|
||||
value: reportName,
|
||||
dataSourceName: dataSource,
|
||||
action,
|
||||
} = await createReportDialogPrompt({
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
});
|
||||
trackedSeries,
|
||||
measurementFilter = filterAnd(
|
||||
filterMeasurementsByStudyUID(StudyInstanceUID),
|
||||
filterMeasurementsBySeriesUID(trackedSeries),
|
||||
filterPlanarMeasurement
|
||||
),
|
||||
defaultSaveTitle = 'Research Derived Series',
|
||||
} = ctx;
|
||||
let displaySetInstanceUIDs;
|
||||
|
||||
try {
|
||||
if (action === PROMPT_RESPONSES.CREATE_REPORT) {
|
||||
const selectedDataSource = dataSource ?? dataSources[0];
|
||||
const trackedMeasurements = getTrackedMeasurements(
|
||||
measurementService,
|
||||
trackedStudy,
|
||||
trackedSeries
|
||||
);
|
||||
const promptResult = await createReportDialogPrompt({
|
||||
title: defaultSaveTitle,
|
||||
extensionManager,
|
||||
servicesManager,
|
||||
});
|
||||
|
||||
if (promptResult.action === PROMPT_RESPONSES.CREATE_REPORT) {
|
||||
const dataSources = extensionManager.getDataSources();
|
||||
const dataSource = dataSources[0];
|
||||
const measurementData = measurementService.getMeasurements(measurementFilter);
|
||||
|
||||
const SeriesDescription = promptResult.value || defaultSaveTitle;
|
||||
|
||||
const SeriesNumber = getNextSRSeriesNumber(displaySetService);
|
||||
displaySetInstanceUIDs = await handleReportCreation({
|
||||
|
||||
const getReport = async () => {
|
||||
return commandsManager.runCommand(
|
||||
'storeMeasurements',
|
||||
{
|
||||
measurementData,
|
||||
dataSource,
|
||||
additionalFindingTypes: ['ArrowAnnotate'],
|
||||
options: {
|
||||
SeriesDescription,
|
||||
SeriesNumber,
|
||||
},
|
||||
},
|
||||
'CORNERSTONE_STRUCTURED_REPORT'
|
||||
);
|
||||
};
|
||||
displaySetInstanceUIDs = await createReportAsync({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
trackedMeasurements,
|
||||
selectedDataSource,
|
||||
reportName,
|
||||
SeriesNumber,
|
||||
getReport,
|
||||
});
|
||||
} else if (promptResult.action === RESPONSE.CANCEL) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
return {
|
||||
userResponse: action,
|
||||
userResponse: promptResult.action,
|
||||
createdDisplaySetInstanceUIDs: displaySetInstanceUIDs,
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
@@ -60,50 +78,9 @@ async function promptSaveReport(services, ctx, evt) {
|
||||
isBackupSave,
|
||||
};
|
||||
} catch (error) {
|
||||
console.warn('Unable to save report', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tracked measurements based on study and series criteria
|
||||
*/
|
||||
function getTrackedMeasurements(measurementService, trackedStudy, trackedSeries) {
|
||||
return measurementService
|
||||
.getMeasurements()
|
||||
.filter(
|
||||
m => trackedStudy === m.referenceStudyUID && trackedSeries.includes(m.referenceSeriesUID)
|
||||
)
|
||||
.filter(m => m.referencedImageId != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the creation of the report using the measurement service
|
||||
*/
|
||||
async function handleReportCreation({
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
trackedMeasurements,
|
||||
selectedDataSource,
|
||||
reportName,
|
||||
SeriesNumber,
|
||||
}) {
|
||||
return createReportAsync({
|
||||
servicesManager,
|
||||
getReport: () =>
|
||||
commandsManager.runCommand(
|
||||
'storeMeasurements',
|
||||
{
|
||||
measurementData: trackedMeasurements,
|
||||
dataSource: selectedDataSource,
|
||||
additionalFindingTypes: ['ArrowAnnotate'],
|
||||
options: {
|
||||
SeriesDescription: reportName,
|
||||
SeriesNumber,
|
||||
},
|
||||
},
|
||||
'CORNERSTONE_STRUCTURED_REPORT'
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
export default promptSaveReport;
|
||||
Reference in new issue
Block a user