feat(typings): Enhance typing support with withAppTypes and custom services throughout OHIF (#4090)

This commit is contained in:
Ibrahim authored and GitHub committed 2024-05-08 12:12:49 -04:00
1 parent b2cd0172d6
commit 374065bc3b
153 files changed
+842 -657

No files matched your search

@@ -5,7 +5,11 @@ import { DicomMetadataStore } from '@ohif/core';
*
* @param {*} servicesManager
*/
async function createReportAsync({ servicesManager, getReport, reportType = 'measurement' }) {
async function createReportAsync({
servicesManager,
getReport,
reportType = 'measurement',
}: withAppTypes) {
const { displaySetService, uiNotificationService, uiDialogService } = servicesManager.services;
const loadingDialogId = uiDialogService.create({
showOverlay: true,
@@ -1,18 +1,13 @@
import React, { ReactElement, useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Icon, useModal } from '@ohif/ui';
import { ExtensionManager, ServicesManager, Types } from '@ohif/core';
import { Types } from '@ohif/core';
import DataSourceConfigurationModalComponent from './DataSourceConfigurationModalComponent';
type DataSourceConfigurationComponentProps = {
servicesManager: ServicesManager;
extensionManager: ExtensionManager;
};
function DataSourceConfigurationComponent({
servicesManager,
extensionManager,
}: DataSourceConfigurationComponentProps): ReactElement {
}: withAppTypes): ReactElement {
const { t } = useTranslation('DataSourceConfiguration');
const { show, hide } = useModal();
@@ -1,9 +1,9 @@
import React, { useEffect, useState, useCallback } from 'react';
import { SidePanel } from '@ohif/ui';
import { PanelService, ServicesManager, Types } from '@ohif/core';
import { Types } from '@ohif/core';
export type SidePanelWithServicesProps = {
servicesManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
side: 'left' | 'right';
className: string;
activeTabIndex: number;
@@ -19,7 +19,7 @@ const SidePanelWithServices = ({
expandedWidth,
...props
}: SidePanelWithServicesProps) => {
const panelService: PanelService = servicesManager?.services?.panelService;
const panelService = servicesManager?.services?.panelService;
// Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM.
// Thus going to the Study List page and back to the viewer resets this flag for a SidePanel.
@@ -1,6 +1,6 @@
import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
import ContextMenu from '../../../../platform/ui/src/components/ContextMenu/ContextMenu';
import { CommandsManager, ServicesManager, Types } from '@ohif/core';
import { CommandsManager } from '@ohif/core';
import { annotation as CsAnnotation } from '@cornerstonejs/tools';
import { Menu, MenuItem, Point, ContextMenuProps } from './types';
@@ -17,11 +17,11 @@ import { Menu, MenuItem, Point, ContextMenuProps } from './types';
*/
export default class ContextMenuController {
commandsManager: CommandsManager;
services: Types.Services;
services: AppTypes.Services;
menuItems: Menu[] | MenuItem[];
constructor(servicesManager: ServicesManager, commandsManager: CommandsManager) {
this.services = servicesManager.services as Obj;
constructor(servicesManager: AppTypes.ServicesManager, commandsManager: CommandsManager) {
this.services = servicesManager.services;
this.commandsManager = commandsManager;
}
@@ -42,7 +42,7 @@ class GoogleCloudDataSourceConfigurationAPI implements Types.BaseDataSourceConfi
private _fetchOptions: { method: string; headers: unknown };
private _dataSourceName: string;
constructor(dataSourceName, servicesManager, extensionManager) {
constructor(dataSourceName, servicesManager: AppTypes.ServicesManager, extensionManager) {
this._dataSourceName = dataSourceName;
this._extensionManager = extensionManager;
const userAuthenticationService = servicesManager.services.userAuthenticationService;
@@ -8,13 +8,13 @@ import {
processResults,
processSeriesResults,
} from './qido.js';
import dcm4cheeReject from './dcm4cheeReject';
import dcm4cheeReject from './dcm4cheeReject.js';
import getImageId from './utils/getImageId';
import getImageId from './utils/getImageId.js';
import dcmjs from 'dcmjs';
import { retrieveStudyMetadata, deleteStudyMetadataPromise } from './retrieveStudyMetadata.js';
import StaticWadoClient from './utils/StaticWadoClient';
import getDirectURL from '../utils/getDirectURL';
import getDirectURL from '../utils/getDirectURL.js';
import { fixBulkDataURI } from './utils/fixBulkDataURI';
const { DicomMetaDictionary, DicomDict } = dcmjs.data;
@@ -89,9 +89,9 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
};
generateWadoHeader = () => {
let authorizationHeader = getAuthrorizationHeader();
const authorizationHeader = getAuthrorizationHeader();
//Generate accept header depending on config params
let formattedAcceptHeader = utils.generateAcceptHeader(
const formattedAcceptHeader = utils.generateAcceptHeader(
dicomWebConfig.acceptHeader,
dicomWebConfig.requestTransferSyntaxUID,
dicomWebConfig.omitQuotationForMultipartRequest
@@ -9,7 +9,7 @@ import { createDicomWebApi } from '../DicomWebDataSource/index';
* dicomWeb configuration array
*
*/
function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager: AppTypes.ServicesManager) {
const { name } = dicomWebProxyConfig;
let dicomWebDelegate = undefined;
@@ -21,7 +21,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
throw new Error(`No url for '${name}'`);
} else {
const response = await fetch(url);
let data = await response.json();
const data = await response.json();
if (!data.servers?.dicomWeb?.[0]) {
throw new Error('Invalid configuration returned by url');
}
@@ -167,7 +167,7 @@ export const callByRetrieveAETitle = ({
function createMergeDataSourceApi(
mergeConfig: MergeConfig,
servicesManager: unknown,
servicesManager: AppTypes.ServicesManager,
extensionManager
) {
const { seriesMerge } = mergeConfig;
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { utils, ServicesManager } from '@ohif/core';
import { utils } from '@ohif/core';
import {
MeasurementTable,
Dialog,
@@ -24,14 +24,13 @@ export default function PanelMeasurementTable({
servicesManager,
commandsManager,
extensionManager,
}): React.FunctionComponent {
}: withAppTypes): React.FunctionComponent {
const { t } = useTranslation('MeasurementTable');
const [viewportGrid, viewportGridService] = useViewportGrid();
const { activeViewportId, viewports } = viewportGrid;
const { measurementService, uiDialogService, uiNotificationService, displaySetService } = (
servicesManager as ServicesManager
).services;
const { measurementService, uiDialogService, uiNotificationService, displaySetService } =
servicesManager.services;
const [displayMeasurements, setDisplayMeasurements] = useState([]);
useEffect(() => {
@@ -245,7 +244,7 @@ export default function PanelMeasurementTable({
}
PanelMeasurementTable.propTypes = {
servicesManager: PropTypes.instanceOf(ServicesManager).isRequired,
servicesManager: PropTypes.object.isRequired,
};
function _getMappedMeasurements(measurementService) {
@@ -16,7 +16,7 @@ function PanelStudyBrowser({
getStudiesForPatientByMRN,
requestDisplaySetCreationForStudy,
dataSource,
}) {
}: withAppTypes) {
const { hangingProtocolService, displaySetService, uiNotificationService } =
servicesManager.services;
const navigate = useNavigate();
@@ -1,9 +1,8 @@
import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui';
import { ServicesManager } from '@ohif/core';
function LegacyLayoutSelectorWithServices({ servicesManager, ...props }) {
function LegacyLayoutSelectorWithServices({ servicesManager, ...props }: withAppTypes) {
const { toolbarService } = servicesManager.services;
const onSelection = useCallback(
@@ -76,7 +75,7 @@ LayoutSelector.propTypes = {
rows: PropTypes.number,
columns: PropTypes.number,
onLayoutChange: PropTypes.func,
servicesManager: PropTypes.instanceOf(ServicesManager),
servicesManager: PropTypes.object.isRequired,
};
LayoutSelector.defaultProps = {
@@ -1,7 +1,6 @@
import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { LayoutSelector as OHIFLayoutSelector, ToolbarButton, LayoutPreset } from '@ohif/ui';
import { ServicesManager } from '@ohif/core';
const defaultCommonPresets = [
{
@@ -45,7 +44,7 @@ const _areSelectorsValid = (hp, displaySets, hangingProtocolService) => {
);
};
const generateAdvancedPresets = ({ servicesManager }) => {
const generateAdvancedPresets = ({ servicesManager }: withAppTypes) => {
const { hangingProtocolService, viewportGridService, displaySetService } =
servicesManager.services;
@@ -84,7 +83,11 @@ const generateAdvancedPresets = ({ servicesManager }) => {
.filter(preset => preset !== null);
};
function ToolbarLayoutSelectorWithServices({ commandsManager, servicesManager, ...props }) {
function ToolbarLayoutSelectorWithServices({
commandsManager,
servicesManager,
...props
}: withAppTypes) {
const [isDisabled, setIsDisabled] = useState(false);
const handleMouseEnter = () => {
@@ -129,7 +132,7 @@ function LayoutSelector({
servicesManager,
tooltipDisabled,
...rest
}) {
}: withAppTypes) {
const [isOpen, setIsOpen] = useState(false);
const { customizationService } = servicesManager.services;
@@ -225,7 +228,7 @@ LayoutSelector.propTypes = {
rows: PropTypes.number,
columns: PropTypes.number,
onLayoutChange: PropTypes.func,
servicesManager: PropTypes.instanceOf(ServicesManager),
servicesManager: PropTypes.object.isRequired,
};
LayoutSelector.defaultProps = {
@@ -10,7 +10,7 @@ function ToolbarSplitButtonWithServices({
renderer,
onInteraction,
servicesManager,
}) {
}: withAppTypes) {
const { toolbarService } = servicesManager?.services;
/* Bubbles up individual item clicks */
@@ -10,7 +10,12 @@ import { Toolbar } from '../Toolbar/Toolbar';
const { availableLanguages, defaultLanguage, currentLanguage } = i18n;
function ViewerHeader({ hotkeysManager, extensionManager, servicesManager, appConfig }) {
function ViewerHeader({
hotkeysManager,
extensionManager,
servicesManager,
appConfig,
}: withAppTypes) {
const navigate = useNavigate();
const location = useLocation();
@@ -2,7 +2,7 @@ import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { ErrorBoundary, LoadingIndicatorProgress, InvestigationalUseDialog } from '@ohif/ui';
import { ServicesManager, HangingProtocolService, CommandsManager } from '@ohif/core';
import { HangingProtocolService, CommandsManager } from '@ohif/core';
import { useAppConfig } from '@state';
import ViewerHeader from './ViewerHeader';
import SidePanelWithServices from '../Components/SidePanelWithServices';
@@ -18,7 +18,7 @@ function ViewerLayout({
ViewportGridComp,
leftPanelClosed = false,
rightPanelClosed = false,
}): React.FunctionComponent {
}: withAppTypes): React.FunctionComponent {
const [appConfig] = useAppConfig();
const { panelService, hangingProtocolService } = servicesManager.services;
@@ -167,7 +167,7 @@ ViewerLayout.propTypes = {
getModuleEntry: PropTypes.func.isRequired,
}).isRequired,
commandsManager: PropTypes.instanceOf(CommandsManager),
servicesManager: PropTypes.instanceOf(ServicesManager),
servicesManager: PropTypes.object.isRequired,
// From modes
leftPanels: PropTypes.array,
rightPanels: PropTypes.array,
+2 -3
View File
@@ -1,4 +1,4 @@
import { ServicesManager, utils, Types } from '@ohif/core';
import { utils, Types } from '@ohif/core';
import { ContextMenuController, defaultContextMenu } from './CustomizableContextMenu';
import DicomTagBrowser from './DicomTagBrowser/DicomTagBrowser';
@@ -12,7 +12,6 @@ import { NavigateHistory } from './types/commandModuleTypes';
import { history } from '@ohif/app';
const { subscribeToNextViewportGridChange } = utils;
export type HangingProtocolParams = {
protocolId?: string;
stageIndex?: number;
@@ -38,7 +37,7 @@ const commandsModule = ({
viewportGridService,
displaySetService,
stateSyncService,
} = (servicesManager as ServicesManager).services;
} = servicesManager.services;
// Define a context menu controller for use with any context menus
const contextMenuController = new ContextMenuController(servicesManager, commandsManager);
@@ -1,5 +1,4 @@
import React, { useEffect, useState, useCallback, ReactElement } from 'react';
import { ServicesManager } from '@ohif/core';
import { ProgressDropdown } from '@ohif/ui';
const workflowStepsToDropdownOptions = (steps = []) =>
@@ -11,11 +10,7 @@ const workflowStepsToDropdownOptions = (steps = []) =>
completed: false,
}));
function ProgressDropdownWithService({
servicesManager,
}: {
servicesManager: ServicesManager;
}): ReactElement {
function ProgressDropdownWithService({ servicesManager }: withAppTypes): ReactElement {
const { workflowStepsService } = servicesManager.services;
const [activeStepId, setActiveStepId] = useState(workflowStepsService.activeWorkflowStep?.id);
@@ -5,7 +5,7 @@
import { createDicomWebApi } from './DicomWebDataSource/index.js';
import { createDicomJSONApi } from './DicomJSONDataSource/index.js';
import { createDicomLocalApi } from './DicomLocalDataSource/index.js';
import { createDicomWebProxyApi } from './DicomWebProxyDataSource/index.js';
import { createDicomWebProxyApi } from './DicomWebProxyDataSource/index';
import { createMergeDataSourceApi } from './MergeDataSource/index';
/**
+1 -1
View File
@@ -13,7 +13,7 @@ const getClassName = isToggled => {
};
};
export default function getToolbarModule({ commandsManager, servicesManager }) {
export default function getToolbarModule({ commandsManager, servicesManager }: withAppTypes) {
const { cineService } = servicesManager.services;
return [
{
+2 -2
View File
@@ -1,4 +1,4 @@
import { ServicesManager, CommandsManager, ExtensionManager } from '@ohif/core';
import { CommandsManager, ExtensionManager } from '@ohif/core';
import LineChartViewport from './Components/LineChartViewport/index';
const getViewportModule = ({
@@ -6,7 +6,7 @@ const getViewportModule = ({
commandsManager,
extensionManager,
}: {
servicesManager: ServicesManager;
servicesManager: AppTypes.ServicesManager;
commandsManager: CommandsManager;
extensionManager: ExtensionManager;
}) => {
+5 -1
View File
@@ -10,7 +10,11 @@ const metadataProvider = classes.MetadataProvider;
* @param {Object} servicesManager
* @param {Object} configuration
*/
export default function init({ servicesManager, configuration = {}, commandsManager }): void {
export default function init({
servicesManager,
configuration = {},
commandsManager,
}: withAppTypes): void {
const { stateSyncService, toolbarService, cineService, viewportGridService } =
servicesManager.services;