fix: make datasource selection work and UI fixes (#4952)

Co-authored-by: Pedro Köhler <pedrokohlerbh@gmail.com>
Co-authored-by: Dan Rukas <dan.rukas@gmail.com>
This commit is contained in:
authored and GitHub committed 2025-04-11 15:57:29 -04:00
1 parent 0b6e9cba76
commit aaba8bf1b0
19 files changed
+288 -282

No files matched your search

+1 -1
View File
@@ -53,7 +53,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^3.9.5",
"@cornerstonejs/dicom-image-loader": "^3.10.1",
"@emotion/serialize": "^1.1.3",
"@ohif/core": "3.10.0",
"@ohif/extension-cornerstone": "3.10.0",
+2 -2
View File
@@ -37,8 +37,8 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.4",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/core": "^3.9.5",
"@cornerstonejs/dicom-image-loader": "^3.9.5",
"@cornerstonejs/core": "^3.10.1",
"@cornerstonejs/dicom-image-loader": "^3.10.1",
"@ohif/ui": "3.10.0",
"cornerstone-math": "0.1.9",
"dicom-parser": "^1.8.21"
@@ -87,9 +87,7 @@ export default class ExtensionManager extends PubSubService {
};
private dataSourceMap: Record<string, any>;
private dataSourceDefs: Record<string, any>;
private defaultDataSourceName: string;
private activeDataSource: string;
private peerImport: (moduleId) => Promise<any>;
private activeDataSourceName: string;
constructor({
commandsManager,
@@ -117,20 +115,20 @@ export default class ExtensionManager extends PubSubService {
this.dataSourceMap = {};
this.dataSourceDefs = {};
this.defaultDataSourceName = appConfig.defaultDataSourceName;
this.activeDataSource = appConfig.defaultDataSourceName;
this.activeDataSourceName = appConfig.defaultDataSourceName;
this.peerImport = appConfig.peerImport;
}
public setActiveDataSource(dataSource: string): void {
if (this.activeDataSource === dataSource) {
if (this.activeDataSourceName === dataSource) {
return;
}
this.activeDataSource = dataSource;
this.activeDataSourceName = dataSource;
this._broadcastEvent(
ExtensionManager.EVENTS.ACTIVE_DATA_SOURCE_CHANGED,
this.dataSourceDefs[this.activeDataSource]
this.dataSourceDefs[this.activeDataSourceName]
);
}
@@ -375,7 +373,7 @@ export default class ExtensionManager extends PubSubService {
getDataSources = dataSourceName => {
if (dataSourceName === undefined) {
// Default to the activeDataSource
dataSourceName = this.activeDataSource;
dataSourceName = this.activeDataSourceName;
}
// Note: this currently uses the data source name, which feels weird...
@@ -387,7 +385,7 @@ export default class ExtensionManager extends PubSubService {
};
getActiveDataSource = () => {
return this.dataSourceMap[this.activeDataSource];
return this.dataSourceMap[this.activeDataSourceName];
};
/**
@@ -400,7 +398,7 @@ export default class ExtensionManager extends PubSubService {
getDataSourceDefinition = dataSourceName => {
if (dataSourceName === undefined) {
// Default to the activeDataSource
dataSourceName = this.activeDataSource;
dataSourceName = this.activeDataSourceName;
}
return this.dataSourceDefs[dataSourceName];
@@ -410,7 +408,7 @@ export default class ExtensionManager extends PubSubService {
* Gets the data source definition for the active data source.
*/
getActiveDataSourceDefinition = () => {
return this.getDataSourceDefinition(this.activeDataSource);
return this.getDataSourceDefinition(this.activeDataSourceName);
};
/**
@@ -424,16 +422,21 @@ export default class ExtensionManager extends PubSubService {
return [];
}
return Object.keys(this.dataSourceMap)
.filter(ds => {
const configuration = this.dataSourceDefs[ds]?.configuration;
return configuration?.supportsStow ?? configuration?.wadoRoot;
})
.map(ds => ({
value: ds,
label: ds,
placeHolder: ds,
}));
const inactiveDataSourceNames = Object.keys(this.dataSourceMap).filter(ds => {
const configuration = this.dataSourceDefs[ds]?.configuration;
const isNotActiveDataSource =
this.dataSourceDefs[ds].sourceName !== this.activeDataSourceName;
const supportsStowOrWado = configuration?.supportsStow ?? configuration?.wadoRoot;
return supportsStowOrWado && isNotActiveDataSource;
});
const allDatasourcesForUI = [this.activeDataSourceName, ...inactiveDataSourceNames].map(ds => ({
value: ds,
label: ds,
placeHolder: ds,
}));
return allDatasourcesForUI;
};
/**
@@ -555,7 +558,7 @@ export default class ExtensionManager extends PubSubService {
dataSourceDef.configuration = dataSourceConfiguration;
this._createDataSourceInstance(dataSourceDef);
if (this.activeDataSource === dataSourceName) {
if (this.activeDataSourceName === dataSourceName) {
// When the active data source is changed/set, fire an event to indicate that its configuration has changed.
this._broadcastEvent(ExtensionManager.EVENTS.ACTIVE_DATA_SOURCE_CHANGED, dataSourceDef);
}
@@ -57,7 +57,7 @@ const ScrollArea = React.forwardRef<
<ScrollAreaPrimitive.Root
ref={ref}
className={cn('relative h-full overflow-hidden', className)}
type={props.type || 'auto'}
type={props.type}
{...props}
>
<ScrollAreaPrimitive.Viewport
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import { StudyItem } from '../StudyItem';
import { StudyBrowserSort } from '../StudyBrowserSort';
import { StudyBrowserViewOptions } from '../StudyBrowserViewOptions';
import { ScrollArea } from '../ScrollArea';
const noop = () => {};
@@ -59,26 +60,28 @@ const StudyBrowser = ({
};
return (
<div
className="ohif-scrollbar invisible-scrollbar bg-bkg-low flex flex-1 flex-col gap-[4px] overflow-auto"
data-cy={'studyBrowser-panel'}
>
<div className="flex flex-col gap-[4px]">
{showSettings && (
<div className="w-100 bg-bkg-low flex h-[48px] items-center justify-center gap-[10px] px-[8px] py-[10px]">
<>
<StudyBrowserViewOptions
tabs={tabs}
onSelectTab={onClickTab}
activeTabName={activeTabName}
/>
<StudyBrowserSort servicesManager={servicesManager} />
</>
</div>
)}
{getTabContent()}
<ScrollArea>
<div
className="bg-bkg-low flex flex-1 flex-col gap-[4px]"
data-cy={'studyBrowser-panel'}
>
<div className="flex flex-col gap-[4px]">
{showSettings && (
<div className="w-100 bg-bkg-low flex h-[48px] items-center justify-center gap-[10px] px-[8px] py-[10px]">
<>
<StudyBrowserViewOptions
tabs={tabs}
onSelectTab={onClickTab}
activeTabName={activeTabName}
/>
<StudyBrowserSort servicesManager={servicesManager} />
</>
</div>
)}
{getTabContent()}
</div>
</div>
</div>
</ScrollArea>
);
};
@@ -63,7 +63,7 @@ const Thumbnail = ({
<div
className={classnames(
'flex h-full w-full flex-col items-center justify-center gap-[2px] p-[4px]',
isActive && 'bg-popover'
isActive && 'bg-popover rounded'
)}
>
<div className="h-[114px] w-[128px]">
@@ -80,7 +80,7 @@ const Thumbnail = ({
)}
{/* bottom left */}
<div className="absolute bottom-0 left-0 flex h-[14px] items-center gap-[4px] rounded-tr pt-[10px] pb-[8px] pr-[6px] pl-[3px]">
<div className="absolute bottom-0 left-0 flex h-[14px] items-center gap-[4px] rounded-tr pt-[10px] pb-[10px] pr-[6px] pl-[5px]">
<div
className={classnames(
'h-[10px] w-[10px] rounded-[2px]',
@@ -135,7 +135,7 @@ const Thumbnail = ({
</div>
</div>
</div>
<div className="flex h-[52px] w-[128px] flex-col justify-end">
<div className="flex h-[52px] w-[128px] flex-col justify-start pt-px">
<Tooltip>
<TooltipContent>{description}</TooltipContent>
<TooltipTrigger>
@@ -167,18 +167,18 @@ const Thumbnail = ({
<div
className={classnames(
'flex h-full w-full items-center justify-between pr-[8px] pl-[8px] pt-[4px] pb-[4px]',
isActive && 'bg-popover'
isActive && 'bg-popover rounded'
)}
>
<div className="relative flex h-[32px] w-full items-center gap-[8px] overflow-hidden">
<div
className={classnames(
'h-[32px] w-[4px] min-w-[4px] rounded-[2px]',
'h-[32px] w-[4px] min-w-[4px] rounded',
isActive || isHydratedForDerivedDisplaySet ? 'bg-highlight' : 'bg-primary/65',
loadingProgress && loadingProgress < 1 && 'bg-primary/25'
)}
></div>
<div className="flex h-full w-[calc(100%-12px)] flex-col">
<div className="flex h-full w-[calc(100%-12px)] flex-col justify-start">
<div className="flex items-center gap-[7px]">
<div className="text-[13px] font-semibold text-white">{modality}</div>
<Tooltip>
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import { Thumbnail } from '../Thumbnail';
import { useDynamicMaxHeight } from '../../hooks/useDynamicMaxHeight';
import { ScrollArea } from '../ScrollArea';
const ThumbnailList = ({
thumbnails,
@@ -27,11 +26,10 @@ const ThumbnailList = ({
);
return (
<ScrollArea className="flex flex-col gap-[4px] pt-[4px] pr-[2.5px] pl-[5px] pb-[4px]">
<div className="flex flex-col">
<div
ref={ref}
style={{ maxHeight: maxHeight, minHeight: '300px' }}
className="flex flex-col gap-[4px] pt-[4px] pr-[2.5px] pl-[5px] pb-[4px]"
className="flex flex-col gap-[2px] pt-[4px] pr-[2.5px] pl-[5px] pb-[4px]"
>
{thumbnailItems.length > 0 && (
<div
@@ -88,7 +86,7 @@ const ThumbnailList = ({
</div>
)}
</div>
</ScrollArea>
</div>
);
};