ohif-viewer/platform/viewer/src/routes/Local/Local.tsx
M.D 075008c674
feat(microscopy): add dicom microscopy extension and mode (#3247)
* skeleton for dicom-microscopy extension

* skeleton for microscopy mode

* [feat] ported @radicalimaging/microscopy-dicom to OHIF's default extension

* [feat] ported microscopy mode from private repo

* added new definitions to the package.json

* webpack configuration update for microscopy extension

* register new icons for microscopy tools

* fixes to the microscopy extension and mode

* trivial error fix - typescript type import error

* link microscopy extension with default OHIF app plugin config

* demo config fix

* fix logs

* remove unsed imports

* [fix] loading of microscopy

* [fix] webworker script loading, normalizing denaturalized dataset

* found the latest version of dicom-microscopy-viewer that works with current OHIF extension : 0.35.2

* hide thumbnail pane by default, as we have issues with

* comments

* remove unused code

* [feat] microscopy - annotation selection

* [feat] microscopy - edit annotation label

* wip

* [bugfix] dicom-microscopy tool

* [bugfix] dicom microscopy annotations

* [fix] mixed-content blocking caused by BulkDataURI

* [fix] microscopy measurements panel - center button

* [fix] microscopy measurements panel - styling

* [fix] microscopy - controls

* fix local loading of microscopy

* fix local loading of dicom microscopy

* fix typo - indexof to indexOf

* [fix] remove unused icons

* remove commented out lines from webpack configuration

* platform/viewer/public/config/default.js - revert accidental changes

* [refactor] redirecting to microscopy mode on Local mode

* attribution to DMV and SLIM viewer

* [fix] code review feedbacks

* fix thumbnails

* [fix] microscopy - fix old publisher.publish() to PubSubService._broadcastEvent()

* [fix] interactions, webpack config, roi selection

* [feat] microscopy - remove select tool  from UI

* microscopy author

* [fix] saving and loading SR

* [bugfix] - missing publish() function in MicroscopyService, replace with _broadcastEvent

* remove author section from readme

* refactor SR saving feature

* fix webpack config after merge

* [bugfix] repeated import

* fix e2e

* webpack configuration

* hide "Create report" button for microscopy
2023-04-27 20:53:52 -04:00

159 lines
5.0 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import classnames from 'classnames';
import { useNavigate } from 'react-router-dom';
import { DicomMetadataStore, MODULE_TYPES } from '@ohif/core';
import Dropzone from 'react-dropzone';
import filesToStudies from './filesToStudies';
import { extensionManager } from '../../App.tsx';
import { Icon, Button, LoadingIndicatorProgress } from '@ohif/ui';
const getLoadButton = (onDrop, text, isDir) => {
return (
<Dropzone onDrop={onDrop} noDrag>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()}>
<Button
rounded="full"
variant="contained" // outlined
disabled={false}
endIcon={<Icon name="launch-arrow" />} // launch-arrow | launch-info
className={classnames('font-medium', 'ml-2')}
onClick={() => {}}
>
{text}
{isDir ? (
<input
{...getInputProps()}
webkitdirectory="true"
mozdirectory="true"
/>
) : (
<input {...getInputProps()} />
)}
</Button>
</div>
)}
</Dropzone>
);
};
function Local() {
const navigate = useNavigate();
const dropzoneRef = useRef();
const [dropInitiated, setDropInitiated] = React.useState(false);
// Initializing the dicom local dataSource
const dataSourceModules = extensionManager.modules[MODULE_TYPES.DATA_SOURCE];
const localDataSources = dataSourceModules.reduce((acc, curr) => {
const mods = [];
curr.module.forEach(mod => {
if (mod.type === 'localApi') {
mods.push(mod);
}
});
return acc.concat(mods);
}, []);
const firstLocalDataSource = localDataSources[0];
const dataSource = firstLocalDataSource.createDataSource({});
const microscopyExtensionLoaded = extensionManager.registeredExtensionIds.includes(
'@ohif/extension-dicom-microscopy'
);
let modePath = 'viewer';
const onDrop = async acceptedFiles => {
const studies = await filesToStudies(acceptedFiles, dataSource);
const query = new URLSearchParams();
if (microscopyExtensionLoaded) {
// TODO: for microscopy, we are forcing microscopy mode, which is not ideal.
// we should make the local drag and drop navigate to the worklist and
// there user can select microscopy mode
const smStudies = studies.filter(id => {
const study = DicomMetadataStore.getStudy(id);
return (
study.series.findIndex(
s => s.Modality === 'SM' || s.instances[0].Modality === 'SM'
) >= 0
);
});
if (smStudies.length > 0) {
smStudies.forEach(id => query.append('StudyInstanceUIDs', id));
modePath = 'microscopy';
}
}
// Todo: navigate to work list and let user select a mode
studies.forEach(id => query.append('StudyInstanceUIDs', id));
navigate(`/${modePath}/dicomlocal?${decodeURIComponent(query.toString())}`);
};
// Set body style
useEffect(() => {
document.body.classList.add('bg-black');
return () => {
document.body.classList.remove('bg-black');
};
}, []);
return (
<Dropzone
ref={dropzoneRef}
onDrop={acceptedFiles => {
setDropInitiated(true);
onDrop(acceptedFiles);
}}
noClick
>
{({ getRootProps }) => (
<div {...getRootProps()} style={{ width: '100%', height: '100%' }}>
<div className="h-screen w-screen flex justify-center items-center ">
<div className="py-8 px-8 mx-auto bg-secondary-dark drop-shadow-md space-y-2 rounded-lg">
<img
className="block mx-auto h-14"
src="./ohif-logo.svg"
alt="OHIF"
/>
<div className="text-center space-y-2 pt-4">
{dropInitiated ? (
<div className="flex flex-col items-center justify-center pt-48">
<LoadingIndicatorProgress
className={'w-full h-full bg-black'}
/>
</div>
) : (
<div className="space-y-2">
<p className="text-blue-300 text-base">
Note: You data is not uploaded to any server, it will stay
in your local browser application
</p>
<p className="text-xg text-primary-active font-semibold pt-6">
Drag and Drop DICOM files here to load them in the Viewer
</p>
<p className="text-blue-300 text-lg">Or click to </p>
</div>
)}
</div>
<div className="flex justify-around pt-4 ">
{getLoadButton(onDrop, 'Load files', false)}
{getLoadButton(onDrop, 'Load folders', true)}
</div>
</div>
</div>
</div>
)}
</Dropzone>
);
}
export default Local;