2025-04-07 16:05:22 +02:00
|
|
|
import React, { useEffect, useMemo, useState } from 'react';
|
2025-02-28 21:17:55 +01:00
|
|
|
import { InputDialog } from '@ohif/ui-next';
|
|
|
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ohif/ui-next';
|
2025-04-07 16:05:22 +02:00
|
|
|
import { useSystem } from '@ohif/core';
|
2025-02-28 21:17:55 +01:00
|
|
|
|
|
|
|
|
type DataSource = {
|
|
|
|
|
value: string;
|
|
|
|
|
label: string;
|
|
|
|
|
placeHolder: string;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type ReportDialogProps = {
|
|
|
|
|
dataSources: DataSource[];
|
|
|
|
|
hide: () => void;
|
2025-04-07 16:05:22 +02:00
|
|
|
onSave: (data: { reportName: string; dataSource: string | null; series: string | null }) => void;
|
2025-02-28 21:17:55 +01:00
|
|
|
onCancel: () => void;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function ReportDialog({ dataSources, hide, onSave, onCancel }: ReportDialogProps) {
|
2025-04-07 16:05:22 +02:00
|
|
|
const { servicesManager } = useSystem();
|
2025-02-28 21:17:55 +01:00
|
|
|
const [selectedDataSource, setSelectedDataSource] = useState<string | null>(
|
|
|
|
|
dataSources?.[0]?.value ?? null
|
|
|
|
|
);
|
2025-04-07 16:05:22 +02:00
|
|
|
const [selectedSeries, setSelectedSeries] = useState<string | null>(null);
|
2025-03-07 04:19:47 +01:00
|
|
|
const [reportName, setReportName] = useState('');
|
|
|
|
|
|
2025-04-07 16:05:22 +02:00
|
|
|
const { displaySetService } = servicesManager.services;
|
|
|
|
|
|
|
|
|
|
const seriesOptions = useMemo(() => {
|
|
|
|
|
const displaySetsMap = displaySetService.getDisplaySetCache();
|
|
|
|
|
const displaySets = Array.from(displaySetsMap.values());
|
|
|
|
|
const options = displaySets
|
|
|
|
|
.filter(ds => ds.Modality === 'SR')
|
|
|
|
|
.map(ds => ({
|
|
|
|
|
value: ds.SeriesInstanceUID,
|
|
|
|
|
description: ds.SeriesDescription,
|
|
|
|
|
label: `${ds.SeriesDescription} ${ds.SeriesDate}/${ds.SeriesTime} ${ds.SeriesNumber}`,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
value: null,
|
|
|
|
|
description: null,
|
|
|
|
|
label: 'Create new series',
|
|
|
|
|
},
|
|
|
|
|
...options,
|
|
|
|
|
];
|
|
|
|
|
}, [displaySetService]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const seriesOption = seriesOptions.find(s => s.value === selectedSeries);
|
|
|
|
|
const newReportName =
|
|
|
|
|
selectedSeries && seriesOption?.description ? seriesOption.description : '';
|
|
|
|
|
setReportName(newReportName);
|
|
|
|
|
}, [selectedSeries, seriesOptions]);
|
|
|
|
|
|
2025-03-07 04:19:47 +01:00
|
|
|
const handleSave = () => {
|
2025-02-28 21:17:55 +01:00
|
|
|
onSave({
|
|
|
|
|
reportName,
|
|
|
|
|
dataSource: selectedDataSource,
|
2025-04-07 16:05:22 +02:00
|
|
|
series: selectedSeries,
|
2025-02-28 21:17:55 +01:00
|
|
|
});
|
|
|
|
|
hide();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleCancel = () => {
|
|
|
|
|
onCancel();
|
|
|
|
|
hide();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const showDataSourceSelect = dataSources?.length > 1;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="text-foreground mt-2 flex min-w-[400px] max-w-md flex-col gap-4">
|
|
|
|
|
<div className="flex flex-col gap-3">
|
2025-04-07 16:05:22 +02:00
|
|
|
<div className="flex gap-4">
|
2025-02-28 21:17:55 +01:00
|
|
|
{showDataSourceSelect && (
|
2025-04-07 16:05:22 +02:00
|
|
|
<div className="mt-1 w-1/2">
|
2025-04-08 23:21:08 +02:00
|
|
|
<div className="mb-1 pl-1 text-base">Data source</div>
|
2025-02-28 21:17:55 +01:00
|
|
|
<Select
|
|
|
|
|
value={selectedDataSource}
|
|
|
|
|
onValueChange={setSelectedDataSource}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="Select a data source" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{dataSources.map(source => (
|
|
|
|
|
<SelectItem
|
|
|
|
|
key={source.value}
|
|
|
|
|
value={source.value}
|
|
|
|
|
>
|
|
|
|
|
{source.label}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-04-07 16:05:22 +02:00
|
|
|
<div className={showDataSourceSelect ? 'mt-1 w-1/2' : 'mt-1 w-full'}>
|
2025-04-08 23:21:08 +02:00
|
|
|
<div className="mb-1 pl-1 text-base">Series</div>
|
2025-04-07 16:05:22 +02:00
|
|
|
<Select
|
|
|
|
|
value={selectedSeries}
|
|
|
|
|
onValueChange={setSelectedSeries}
|
|
|
|
|
>
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
<SelectValue placeholder="Select a series" />
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
{seriesOptions.map(series => (
|
|
|
|
|
<SelectItem
|
|
|
|
|
key={series.value}
|
|
|
|
|
value={series.value}
|
|
|
|
|
>
|
|
|
|
|
{series.label}
|
|
|
|
|
</SelectItem>
|
|
|
|
|
))}
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={showDataSourceSelect ? 'flex gap-4' : ''}>
|
|
|
|
|
<div className="mt-4 w-full">
|
2025-03-07 04:19:47 +01:00
|
|
|
<InputDialog
|
|
|
|
|
value={reportName}
|
|
|
|
|
onChange={setReportName}
|
|
|
|
|
submitOnEnter
|
|
|
|
|
>
|
2025-02-28 21:17:55 +01:00
|
|
|
<InputDialog.Field>
|
2025-04-07 16:05:22 +02:00
|
|
|
<InputDialog.Input
|
|
|
|
|
placeholder="Report name"
|
|
|
|
|
disabled={!!selectedSeries}
|
|
|
|
|
/>
|
2025-02-28 21:17:55 +01:00
|
|
|
</InputDialog.Field>
|
|
|
|
|
</InputDialog>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="flex justify-end gap-2">
|
|
|
|
|
<InputDialog>
|
|
|
|
|
<InputDialog.Actions>
|
|
|
|
|
<InputDialog.ActionsSecondary onClick={handleCancel}>
|
|
|
|
|
Cancel
|
|
|
|
|
</InputDialog.ActionsSecondary>
|
|
|
|
|
<InputDialog.ActionsPrimary onClick={handleSave}>Save</InputDialog.ActionsPrimary>
|
|
|
|
|
</InputDialog.Actions>
|
|
|
|
|
</InputDialog>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export { ReportDialog };
|
|
|
|
|
export default {
|
|
|
|
|
'ohif.createReportDialog': ReportDialog,
|
|
|
|
|
};
|