Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datasource selector UI #4556

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { useTranslation } from 'react-i18next';
import { Icon, useModal } from '@ohif/ui';
import { Types } from '@ohif/core';
import DataSourceConfigurationModalComponent from './DataSourceConfigurationModalComponent';
import {
DataSourceConfigurationAPI,
GoogleCloudDataSourceConfigurationAPI,
} from '../DataSourceConfigurationAPI';

function DataSourceConfigurationComponent({
servicesManager,
extensionManager,
}: withAppTypes): ReactElement {
type,
}: withAppTypes<{ type: string }>): ReactElement {
const { t } = useTranslation('DataSourceConfiguration');
const { show, hide } = useModal();

Expand All @@ -23,14 +28,22 @@ function DataSourceConfigurationComponent({

const dataSourceChangedCallback = async () => {
const activeDataSourceDef = extensionManager.getActiveDataSourceDefinition();
const { dataSourceSelectionApi } = extensionManager.appConfig;

if (!activeDataSourceDef.configuration.configurationAPI) {
if (!activeDataSourceDef.configuration.configurationAPI && !dataSourceSelectionApi) {
return;
}

const { factory: configurationAPIFactory } =
customizationService.get(activeDataSourceDef.configuration.configurationAPI) ?? {};

let configurationAPIFactory: (
sourceName: string
) => DataSourceConfigurationAPI | GoogleCloudDataSourceConfigurationAPI;
if (type === 'sourceSelector') {
configurationAPIFactory = customizationService.get(dataSourceSelectionApi)?.factory;
} else {
configurationAPIFactory = customizationService.get(
activeDataSourceDef.configuration.configurationAPI
)?.factory;
}
if (!configurationAPIFactory) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// PVR-447 show option to change data source from ui
import { ExtensionManager, Types } from '@ohif/core';
class DataSourceConfigurationAPIItem implements Types.BaseDataSourceConfigurationAPIItem {
id: string;
name: string;
}

class DataSourceConfigurationAPI implements Types.BaseDataSourceConfigurationAPI {
private _extensionManager: ExtensionManager;

constructor(extensionManager) {
this._extensionManager = extensionManager;
}

getItemLabels = () => ['Data Sources'];

async initialize(): Promise<Types.BaseDataSourceConfigurationAPIItem[]> {
const datasources = this._extensionManager.appConfig.dataSources.map(ds => {
return {
id: ds.sourceName,
name: ds.sourceName,
};
});

return new Promise(resolve => resolve(datasources));
}

async setCurrentItem(
anItem: Types.BaseDataSourceConfigurationAPIItem
): Promise<Types.BaseDataSourceConfigurationAPIItem[]> {
return new Promise(resolve => {
if (anItem) {
this._extensionManager.setActiveDataSource(anItem.name);
}
this.initialize().then(items => resolve(items));
});
}

async getConfiguredItems(): Promise<Array<DataSourceConfigurationAPIItem>> {
const activeDatasource = this._extensionManager.getActiveDataSourceDefinition();
return [
{
id: activeDatasource.sourceName,
name: activeDatasource.sourceName,
},
];
}
}

export { DataSourceConfigurationAPI };
4 changes: 4 additions & 0 deletions extensions/default/src/DataSourceConfigurationAPI/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { DataSourceConfigurationAPI } from './DataSourceConfigurationAPI';
import { GoogleCloudDataSourceConfigurationAPI } from './GoogleCloudDataSourceConfigurationAPI';

export { DataSourceConfigurationAPI, GoogleCloudDataSourceConfigurationAPI };
17 changes: 17 additions & 0 deletions extensions/default/src/getCustomizationModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ProgressDropdownWithService } from './Components/ProgressDropdownWithSe
import DataSourceConfigurationComponent from './Components/DataSourceConfigurationComponent';
import { GoogleCloudDataSourceConfigurationAPI } from './DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI';
import { utils } from '@ohif/core';
import { DataSourceConfigurationAPI } from './DataSourceConfigurationAPI';

const formatDate = utils.formatDate;

Expand Down Expand Up @@ -147,6 +148,17 @@ export default function getCustomizationModule({ servicesManager, extensionManag
component: DataSourceConfigurationComponent.bind(null, {
servicesManager,
extensionManager,
type: 'sourceConfigurationSelector',
}),
},

{
// the generic GUI component to change a data source using an instance of a BaseDataSourceConfigurationAPI
id: 'ohif.dataSourceSelectorComponent',
component: DataSourceConfigurationComponent.bind(null, {
servicesManager,
extensionManager,
type: 'sourceSelector',
}),
},

Expand All @@ -160,6 +172,11 @@ export default function getCustomizationModule({ servicesManager, extensionManag
extensionManager
),
},
{
// The factory for creating an instance of a BaseDataSourceConfigurationAPI for selecting data source
id: 'ohif.dataSourceSelectionAPI',
factory: () => new DataSourceConfigurationAPI(extensionManager),
},

{
id: 'progressDropdownWithServiceComponent',
Expand Down
1 change: 1 addition & 0 deletions platform/app/public/config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ window.config = {
// // regex: /(https:\/\/hospital.com(\/[0-9A-Za-z.]+)*)|(https:\/\/othersite.com(\/[0-9A-Za-z.]+)*)/
// regex: /.*/,
// },
dataSourceSelectionApi: 'ohif.dataSourceSelectionAPI',
dataSources: [
{
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
Expand Down
7 changes: 6 additions & 1 deletion platform/app/src/routes/WorkList/WorkList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,8 @@ function WorkList({

const { component: dataSourceConfigurationComponent } =
customizationService.get('ohif.dataSourceConfigurationComponent') ?? {};
const { component: dataSourceSelectorComponent } =
customizationService.get('ohif.dataSourceSelectorComponent') ?? {};

return (
<div className="flex h-screen flex-col bg-black">
Expand All @@ -541,7 +543,7 @@ function WorkList({
/>
<Onboarding />
<InvestigationalUseDialog dialogConfiguration={appConfig?.investigationalUseDialog} />
<div className="flex flex-col h-full overflow-y-auto">
<div className="flex h-full flex-col overflow-y-auto">
<ScrollArea>
<div className="flex grow flex-col">
<StudyListFilter
Expand All @@ -557,6 +559,9 @@ function WorkList({
? () => dataSourceConfigurationComponent()
: undefined
}
getDataSourceSelectorComponent={
dataSourceSelectorComponent ? () => dataSourceSelectorComponent() : undefined
}
/>
</div>
{hasStudies ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Data Source Selection

The worklist page displays the selected datasource at the top. Users can easily switch between available data sources configured in the configuration file by clicking the icon next to the data source name.

### UI Configuration

You can customize the datasource selection UI through two configuration options:

#### Datasource Selection API
- **Customization Module Key**: `ohif.dataSourceSelectionAPI`
- **Purpose**: Defines the API used for datasource selection. This is an implementation of the interface `BaseDataSourceConfigurationAPI`
- **Usage**: Provide a custom implementation to control what datasources are retrieved and managed

#### Datasource Selector Component
- **Customization Module Key**: `ohif.dataSourceSelectorComponent`
- **Purpose**: Specifies the component used for displaying and interacting with datasource selection
- **Usage**: UI component that shows the selected data source and the list of selectable data sources

Example configuration:
```javascript
{
id: 'ohif.dataSourceSelectionAPI',
factory: () => new DataSourceConfigurationAPI(extensionManager),
},
{
id: 'ohif.dataSourceSelectorComponent',
component: DataSourceConfigurationComponent.bind(null, {
servicesManager,
extensionManager,
type: 'sourceSelector',
}),
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const StudyListFilter = ({
numOfStudies,
onUploadClick,
getDataSourceConfigurationComponent,
getDataSourceSelectorComponent,
}) => {
const { t } = useTranslation('StudyList');
const { sortBy, sortDirection } = filterValues;
Expand All @@ -41,6 +42,7 @@ const StudyListFilter = ({
>
{t('StudyList')}
</Typography>
{getDataSourceSelectorComponent && getDataSourceSelectorComponent()}
{getDataSourceConfigurationComponent && getDataSourceConfigurationComponent()}
{onUploadClick && (
<div
Expand Down Expand Up @@ -139,6 +141,7 @@ StudyListFilter.propTypes = {
isFiltering: PropTypes.bool.isRequired,
onUploadClick: PropTypes.func,
getDataSourceConfigurationComponent: PropTypes.func,
getDataSourceSelectorComponent: PropTypes.func,
};

export default StudyListFilter;