OHIF with Cornerstone3D 2.0 (#4347)

This commit is contained in:
Alireza authored and GitHub committed 2024-11-06 07:15:27 -05:00
1 parent 8981a61b8c
commit 7ce7127d7c
803 files changed
+32760 -15893

No files matched your search

+1
View File
@@ -1,2 +1,3 @@
.vercel
test-results
store.json
@@ -1,7 +1,7 @@
# docker-compose
# --------------
# This dockerfile is used by the `docker-compose.yml` adjacent file. When
# running `docker-compose build`, this dockerfile helps build the "webapp" image.
# running `docker compose build`, this dockerfile helps build the "webapp" image.
# All paths are relative to the `context`, which is the project root directory.
#
# docker build
@@ -1,7 +1,7 @@
# docker-compose
# --------------
# This dockerfile is used by the `docker-compose.yml` adjacent file. When
# running `docker-compose build`, this dockerfile helps build the "webapp" image.
# running `docker compose build`, this dockerfile helps build the "webapp" image.
# All paths are relative to the `context`, which is the project root directory.
#
# docker build
+24 -14
View File
@@ -18,12 +18,18 @@ const PUBLIC_DIR = path.join(__dirname, '../public');
const HTML_TEMPLATE = process.env.HTML_TEMPLATE || 'index.html';
const PUBLIC_URL = process.env.PUBLIC_URL || '/';
const APP_CONFIG = process.env.APP_CONFIG || 'config/default.js';
// proxy settings
const PROXY_TARGET = process.env.PROXY_TARGET;
const PROXY_DOMAIN = process.env.PROXY_DOMAIN;
const PROXY_PATH_REWRITE_FROM = process.env.PROXY_PATH_REWRITE_FROM;
const PROXY_PATH_REWRITE_TO = process.env.PROXY_PATH_REWRITE_TO;
const OHIF_PORT = Number(process.env.OHIF_PORT || 3000);
const ENTRY_TARGET = process.env.ENTRY_TARGET || `${SRC_DIR}/index.js`;
const Dotenv = require('dotenv-webpack');
const writePluginImportFile = require('./writePluginImportsFile.js');
// const MillionLint = require('@million/lint');
const copyPluginFromExtensions = writePluginImportFile(SRC_DIR, DIST_DIR);
@@ -75,6 +81,8 @@ module.exports = (env, argv) => {
],
},
plugins: [
// For debugging re-renders
// MillionLint.webpack(),
new Dotenv(),
// Clean output.path
new CleanWebpackPlugin(),
@@ -104,21 +112,12 @@ module.exports = (env, argv) => {
to: `${DIST_DIR}/app-config.js`,
},
// Copy Dicom Microscopy Viewer build files
// This is in pluginCOnfig.json now
// {
// from: '../../../node_modules/dicom-microscopy-viewer/dist/dynamic-import',
// to: DIST_DIR,
// globOptions: {
// ignore: ['**/*.min.js.map'],
// },
// // The dicom-microscopy-viewer is optional, so if it doeesn't get
// // installed, it shouldn't cause issues.
// noErrorOnMissing: true,
// },
// Copy dicom-image-loader build files
{
from: '../../../node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import',
from: '../../../node_modules/dicom-microscopy-viewer/dist/dynamic-import',
to: DIST_DIR,
globOptions: {
ignore: ['**/*.min.js.map'],
},
},
],
}),
@@ -179,12 +178,23 @@ module.exports = (env, argv) => {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
},
devMiddleware: {
writeToDisk: true,
},
},
});
if (hasProxy) {
mergedConfig.devServer.proxy = mergedConfig.devServer.proxy || {};
mergedConfig.devServer.proxy[PROXY_TARGET] = PROXY_DOMAIN;
mergedConfig.devServer.proxy = {
[PROXY_TARGET]: {
target: PROXY_DOMAIN,
changeOrigin: true,
pathRewrite: {
[`^${PROXY_PATH_REWRITE_FROM}`]: PROXY_PATH_REWRITE_TO,
},
},
};
}
if (isProdBuild) {
-4
View File
@@ -13,10 +13,6 @@ export default defineConfig({
console.log(launchOptions.args); // print all current args
console.log('***', browser.family, browser.name, '***');
if (browser.family === 'chromium' && browser.name !== 'electron') {
// auto open devtools
launchOptions.args.push('--enable-features=SharedArrayBuffer');
}
// whatever you return here becomes the launchOptions
return launchOptions;
@@ -11,7 +11,7 @@ describe('OHIF HP', () => {
});
it('Should display 3 up', () => {
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', 3);
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', 4);
});
it('Should navigate next/previous stage', () => {
@@ -10,11 +10,11 @@ describe('OHIF Double Click', () => {
});
it('Should double click each viewport to one up and back', () => {
const numExpectedViewports = 3;
const numExpectedViewports = 4;
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', numExpectedViewports);
for (let i = 0; i < numExpectedViewports; i += 1) {
cy.wait(2000);
for (let i = 0; i < 3; i += 1) {
cy.wait(1000);
// For whatever reason, with Cypress tests, we have to activate the
// viewport we are double clicking first.
@@ -12,7 +12,7 @@ describe('OHIF Context Menu', function () {
// Add length measurement
cy.addLengthMeasurement();
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').as('yesBtn').click();
cy.get('[data-cy="measurement-item"]').as('measurementItem').click();
cy.get('[data-cy="data-row"]').as('measurementItem').click();
const [x1, y1] = [150, 100];
cy.get('@viewport')
@@ -30,6 +30,6 @@ describe('OHIF Context Menu', function () {
// Click "Finding" subMenu
cy.get('[data-cy="context-menu-item"]').as('item').contains('Aortic insufficiency').click();
cy.get('[data-cy="measurement-item"]').as('measure-item').contains('Aortic insufficiency');
cy.get('[data-cy="data-row"]').as('measure-item').contains('Aortic insufficiency');
});
});
@@ -85,7 +85,7 @@ describe('OHIF Cornerstone Toolbar', () => {
// The exact text is slightly dependent on the viewport resolution, so leave a range
cy.get('@viewportInfoBottomLeft').should($txt => {
const text = $txt.text();
expect(text).to.include('W:118').include('L:479');
expect(text).to.include('L:479');
});
});
@@ -117,7 +117,7 @@ describe('OHIF Cornerstone Toolbar', () => {
//Verify the measurement exists in the table
cy.get('@measurementsPanel').should('be.visible');
cy.get('[data-cy="measurement-item"]').as('measure').its('length').should('be.at.least', 1);
cy.get('[data-cy="data-row"]').as('measure').its('length').should('be.at.least', 1);
});
/*it('checks if angle annotation can be added on viewport without causing any errors', () => {
@@ -351,7 +351,7 @@ describe('OHIF Cornerstone Toolbar', () => {
//Verify if measurement annotation was added into the measurements panel
cy.get('@measurementsBtn').click();
cy.get('[data-cy="measurement-item"]')
cy.get('[data-cy="data-row"]')
.its('length')
.should('be.at.least', 2);
@@ -29,16 +29,17 @@ describe('OHIF Measurement Panel', function () {
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').as('yesBtn').click();
cy.get('[data-cy="measurement-item"]').as('measurementItem').click();
cy.get('[data-cy="data-row"]').as('measurementItem').click();
cy.get('[data-cy="measurement-item"]').find('svg').eq(0).as('measurementItemSvg').click();
cy.get('[data-cy="data-row"]').find('svg').eq(0).as('measurementItemSvg').click();
// enter Bone label
cy.get('[data-cy="input-annotation"]').should('exist');
cy.get('[data-cy="input-annotation"]').should('be.visible');
cy.get('[data-cy="input-annotation"]').type('Bone{enter}');
// Todo: move it to the new annotation input with drop down
// cy.get('[data-cy="input-annotation"]').should('exist');
// cy.get('[data-cy="input-annotation"]').should('be.visible');
// cy.get('[data-cy="input-annotation"]').type('Bone{enter}');
cy.get('[data-cy="measurement-item"]').as('measurementItem').should('contain.text', 'Bone');
// cy.get('[data-cy="data-row"]').as('measurementItem').should('contain.text', 'Bone');
});
it('checks if image would jump when clicked on a measurement item', function () {
@@ -58,7 +59,7 @@ describe('OHIF Measurement Panel', function () {
cy.get('@viewportInfoBottomRight').should('contains.text', '(14/');
// Click on first measurement item
cy.get('[data-cy="measurement-item"]').eq(0).click();
cy.get('[data-cy="data-row"]').eq(0).click();
cy.get('@viewportInfoBottomRight').should('contains.text', '(1/');
cy.get('@viewportInfoBottomRight').should('not.contains.text', '(14/');
-6
View File
@@ -39,9 +39,3 @@
no-cache,
no-store,
must-revalidate'''
# COMMENT: For sharedArrayBuffer, see https://developer.chrome.com/blog/enabling-shared-array-buffer/
Cross-Origin-Embedder-Policy = "require-corp"
Cross-Origin-Opener-Policy = "same-origin"
# set CORP to cross-origin for anyone who wants to use the viewer in an iframe
Cross-Origin-Resource-Policy = "cross-origin"
+5 -4
View File
@@ -29,8 +29,8 @@
"clean:deep": "yarn run clean && shx rm -rf node_modules",
"dev": "cross-env NODE_ENV=development webpack serve --config .webpack/webpack.pwa.js",
"dev:no:cache": "cross-env NODE_ENV=development webpack serve --no-cache --config .webpack/webpack.pwa.js",
"dev:orthanc": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker-nginx-orthanc.js webpack serve --config .webpack/webpack.pwa.js",
"dev:orthanc:no:cache": "cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker-nginx-orthanc.js webpack serve --no-cache --config .webpack/webpack.pwa.js",
"dev:orthanc": "cross-env NODE_ENV=development PROXY_TARGET=http://localhost:3000/pacs/dicom-web PROXY_DOMAIN=http://localhost:8042 PROXY_PATH_REWRITE_FROM=/pacs/dicom-web PROXY_PATH_REWRITE_TO=/dicom-web APP_CONFIG=config/docker-nginx-orthanc.js webpack serve --config .webpack/webpack.pwa.js",
"dev:orthanc:no:cache": "cross-env NODE_ENV=development PROXY_TARGET=http://localhost:3000/pacs/dicom-web PROXY_DOMAIN=http://localhost:8042 PROXY_PATH_REWRITE_FROM=/pacs/dicom-web PROXY_PATH_REWRITE_TO=/dicom-web APP_CONFIG=config/docker-nginx-orthanc.js webpack serve --no-cache --config .webpack/webpack.pwa.js",
"dev:dcm4chee": "cross-env NODE_ENV=development APP_CONFIG=config/local_dcm4chee.js webpack serve --config .webpack/webpack.pwa.js",
"dev:static": "cross-env NODE_ENV=development APP_CONFIG=config/local_static.js webpack serve --config .webpack/webpack.pwa.js",
"dev:viewer": "yarn run dev",
@@ -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": "^1.86.0",
"@cornerstonejs/dicom-image-loader": "^2.1.13",
"@emotion/serialize": "^1.1.3",
"@ohif/core": "3.9.0-beta.105",
"@ohif/extension-cornerstone": "3.9.0-beta.105",
@@ -100,7 +100,8 @@
"react-router-dom": "^6.8.1",
"react-shepherd": "6.1.1",
"shepherd.js": "13.0.3",
"url-loader": "^4.1.1"
"url-loader": "^4.1.1",
"zustand": "4.5.5"
},
"devDependencies": {
"@babel/plugin-proposal-private-methods": "^7.18.6",
-6
View File
@@ -1,6 +0,0 @@
/*
# Ensure the examples are cross-origin isolated so that
# we can use SharedArrayBuffer
# See https://developer.mozilla.org/en-US/docs/Web/API/crossOriginIsolated
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
+3 -3
View File
@@ -427,14 +427,14 @@ window.config = {
title: 'Jumping to Measurements in the Panel',
text: 'Click the measurement in the measurement panel to jump to it.',
attachTo: {
element: '[data-cy="measurement-item"]',
element: '[data-cy="data-row"]',
on: 'left-start',
},
advanceOn: {
selector: '[data-cy="measurement-item"]',
selector: '[data-cy="data-row"]',
event: 'click',
},
beforeShowPromise: () => waitForElement('[data-cy="measurement-item"]'),
beforeShowPromise: () => waitForElement('[data-cy="data-row"]'),
},
{
id: 'changeLayout',
@@ -17,7 +17,6 @@ window.config = {
showCPUFallbackMessage: true,
showLoadingIndicator: true,
useNorm16Texture: true,
useSharedArrayBuffer: 'AUTO',
maxNumRequests: {
interaction: 100,
thumbnail: 75,
@@ -2,10 +2,6 @@
window.config = {
routerBasename: '/ohif-viewer/',
showStudyList: true,
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
extensions: [],
modes: [],
// below flag is for performance reasons, but it might not work for all servers
@@ -2,10 +2,6 @@
window.config = {
routerBasename: '/',
showStudyList: true,
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
extensions: [],
modes: [],
// below flag is for performance reasons, but it might not work for all servers
@@ -2,10 +2,6 @@
window.config = {
routerBasename: '/',
showStudyList: true,
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
extensions: [],
modes: [],
// below flag is for performance reasons, but it might not work for all servers
-4
View File
@@ -1,10 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
enableGoogleCloudAdapter: false,
// below flag is for performance reasons, but it might not work for all servers
showWarningMessageForCrossOrigin: true,
@@ -1,10 +1,6 @@
/** @type {AppTypes.Config} */
window.config = {
routerBasename: '/',
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
showStudyList: true,
extensions: [],
modes: [],
@@ -3,10 +3,6 @@ window.config = {
routerBasename: '/',
extensions: [],
modes: [],
customizationService: {
dicomUploadComponent:
'@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent',
},
showStudyList: true,
maxNumberOfWebWorkers: 3,
showLoadingIndicator: true,
+3 -3
View File
@@ -383,14 +383,14 @@ window.config = {
title: 'Jumping to Measurements in the Panel',
text: 'Click the measurement in the measurement panel to jump to it.',
attachTo: {
element: '[data-cy="measurement-item"]',
element: '[data-cy="data-row"]',
on: 'left-start',
},
advanceOn: {
selector: '[data-cy="measurement-item"]',
selector: '[data-cy="data-row"]',
event: 'click',
},
beforeShowPromise: () => waitForElement('[data-cy="measurement-item"]'),
beforeShowPromise: () => waitForElement('[data-cy="data-row"]'),
},
{
id: 'changeLayout',
+13 -7
View File
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
import i18n from '@ohif/i18n';
import { I18nextProvider } from 'react-i18next';
import { BrowserRouter } from 'react-router-dom';
import Compose from './routes/Mode/Compose';
import {
ExtensionManager,
@@ -16,7 +17,6 @@ import {
DialogProvider,
Modal,
ModalProvider,
SnackbarProvider,
ThemeWrapper,
ViewportDialogProvider,
ViewportGridProvider,
@@ -24,7 +24,11 @@ import {
UserAuthenticationProvider,
ToolboxProvider,
} from '@ohif/ui';
import { ThemeWrapper as ThemeWrapperNext } from '@ohif/ui-next';
import {
ThemeWrapper as ThemeWrapperNext,
NotificationProvider,
TooltipProvider,
} from '@ohif/ui-next';
// Viewer Project
// TODO: Should this influence study list?
import { AppConfigProvider } from '@state';
@@ -88,17 +92,19 @@ function App({
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
const max3DTextureSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE);
appConfigState.max3DTextureSize = max3DTextureSize;
if (gl) {
const max3DTextureSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE);
appConfigState.max3DTextureSize = max3DTextureSize;
}
const {
uiDialogService,
uiModalService,
uiNotificationService,
uiViewportDialogService,
viewportGridService,
cineService,
userAuthenticationService,
uiNotificationService,
customizationService,
} = servicesManager.services;
@@ -112,8 +118,8 @@ function App({
[ViewportGridProvider, { service: viewportGridService }],
[ViewportDialogProvider, { service: uiViewportDialogService }],
[CineProvider, { service: cineService }],
// [NotificationProvider, { service: uiNotificationService }],
[SnackbarProvider, { service: uiNotificationService }],
[NotificationProvider, { service: uiNotificationService }],
[TooltipProvider],
[DialogProvider, { service: uiDialogService }],
[ModalProvider, { service: uiModalService, modal: Modal }],
[ShepherdJourneyProvider],
-2
View File
@@ -9,7 +9,6 @@ import {
UIDialogService,
UIViewportDialogService,
MeasurementService,
StateSyncService,
DisplaySetService,
ToolbarService,
ViewportGridService,
@@ -73,7 +72,6 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
UserAuthenticationService.REGISTRATION,
PanelService.REGISTRATION,
WorkflowStepsService.REGISTRATION,
StateSyncService.REGISTRATION,
[StudyPrefetcherService.REGISTRATION, appConfig.studyPrefetcher],
]);
+3 -8
View File
@@ -23,13 +23,8 @@ function ViewerViewportGrid(props: withAppTypes) {
});
const layoutHash = useRef(null);
const {
displaySetService,
measurementService,
hangingProtocolService,
cornerstoneViewportService,
uiNotificationService,
} = servicesManager.services;
const { displaySetService, measurementService, hangingProtocolService, uiNotificationService } =
servicesManager.services;
const generateLayoutHash = () => `${numCols}-${numRows}`;
@@ -129,7 +124,7 @@ function ViewerViewportGrid(props: withAppTypes) {
title: 'Drag and Drop',
message:
'The selected display sets could not be added to the viewport due to a mismatch in the Hanging Protocol rules.',
type: 'info',
type: 'error',
duration: 3000,
});
}
+1 -16
View File
@@ -6,7 +6,7 @@ import { Icon } from '@ohif/ui';
function Debug() {
return (
<div style={{ width: '100%', height: '100%' }}>
<div className="flex h-screen w-screen items-center justify-center ">
<div className="flex h-screen w-screen items-center justify-center">
<div className="bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md">
<img
className="mx-auto block h-14"
@@ -24,21 +24,6 @@ function Debug() {
}
className="h-5 w-5"
/>
{!window.crossOriginIsolated && (
<div className="text-md flex-1 text-white">
We use SharedArrayBuffer to render volume data (e.g., MPR). If you are seeing
this message, it means that your browser has not enabled COOP/COEP. Please see
the following link for more information:{' '}
<a
href="https://web.dev/coop-coep/"
target="_blank"
rel="noopener noreferrer"
className="text-primary-active"
>
Learn More
</a>
</div>
)}
</div>
</div>
</div>
+64 -54
View File
@@ -1,6 +1,6 @@
import React, { useState, useEffect, useMemo } from 'react';
import classnames from 'classnames';
import PropTypes, { object } from 'prop-types';
import PropTypes from 'prop-types';
import { Link, useNavigate } from 'react-router-dom';
import moment from 'moment';
import qs from 'query-string';
@@ -20,7 +20,6 @@ import {
StudyListPagination,
StudyListFilter,
TooltipClipboard,
Header,
useModal,
AboutModal,
UserPreferences,
@@ -31,10 +30,12 @@ import {
ButtonEnums,
} from '@ohif/ui';
import { Header } from '@ohif/ui-next';
import { Types } from '@ohif/ui';
import i18n from '@ohif/i18n';
import { Onboarding } from '@ohif/ui-next';
import { Onboarding, ScrollArea } from '@ohif/ui-next';
const PatientInfoVisibility = Types.PatientInfoVisibility;
@@ -497,29 +498,32 @@ function WorkList({
}
const { customizationService } = servicesManager.services;
const { component: dicomUploadComponent } =
customizationService.get('dicomUploadComponent') ?? {};
const { component: DicomUploadComponent } =
customizationService.getCustomization('dicomUploadComponent') || {};
const uploadProps =
dicomUploadComponent && dataSource.getConfig()?.dicomUploadEnabled
DicomUploadComponent && dataSource.getConfig()?.dicomUploadEnabled
? {
title: 'Upload files',
closeButton: true,
shouldCloseOnEsc: false,
shouldCloseOnOverlayClick: false,
content: dicomUploadComponent.bind(null, {
dataSource,
onComplete: () => {
hide();
onRefresh();
},
onStarted: () => {
show({
...uploadProps,
// when upload starts, hide the default close button as closing the dialogue must be handled by the upload dialogue itself
closeButton: false,
});
},
}),
content: () => (
<DicomUploadComponent
dataSource={dataSource}
onComplete={() => {
hide();
onRefresh();
}}
onStarted={() => {
show({
...uploadProps,
// when upload starts, hide the default close button as closing the dialogue must be handled by the upload dialogue itself
closeButton: false,
});
}}
/>
),
}
: undefined;
@@ -537,45 +541,51 @@ function WorkList({
/>
<Onboarding />
<InvestigationalUseDialog dialogConfiguration={appConfig?.investigationalUseDialog} />
<div className="ohif-scrollbar ohif-scrollbar-stable-gutter flex grow flex-col overflow-y-auto sm:px-5">
<StudyListFilter
numOfStudies={pageNumber * resultsPerPage > 100 ? 101 : numOfStudies}
filtersMeta={filtersMeta}
filterValues={{ ...filterValues, ...defaultSortValues }}
onChange={setFilterValues}
clearFilters={() => setFilterValues(defaultFilterValues)}
isFiltering={isFiltering(filterValues, defaultFilterValues)}
onUploadClick={uploadProps ? () => show(uploadProps) : undefined}
getDataSourceConfigurationComponent={
dataSourceConfigurationComponent ? () => dataSourceConfigurationComponent() : undefined
}
/>
{hasStudies ? (
<div className="flex flex-col overflow-y-auto">
<ScrollArea>
<div className="flex grow flex-col">
<StudyListTable
tableDataSource={tableDataSource.slice(offset, offsetAndTake)}
numOfStudies={numOfStudies}
querying={querying}
<StudyListFilter
numOfStudies={pageNumber * resultsPerPage > 100 ? 101 : numOfStudies}
filtersMeta={filtersMeta}
filterValues={{ ...filterValues, ...defaultSortValues }}
onChange={setFilterValues}
clearFilters={() => setFilterValues(defaultFilterValues)}
isFiltering={isFiltering(filterValues, defaultFilterValues)}
onUploadClick={uploadProps ? () => show(uploadProps) : undefined}
getDataSourceConfigurationComponent={
dataSourceConfigurationComponent
? () => dataSourceConfigurationComponent()
: undefined
}
/>
<div className="grow">
<StudyListPagination
onChangePage={onPageNumberChange}
onChangePerPage={onResultsPerPageChange}
currentPage={pageNumber}
perPage={resultsPerPage}
</div>
{hasStudies ? (
<div className="flex grow flex-col">
<StudyListTable
tableDataSource={tableDataSource.slice(offset, offsetAndTake)}
numOfStudies={numOfStudies}
querying={querying}
filtersMeta={filtersMeta}
/>
<div className="grow">
<StudyListPagination
onChangePage={onPageNumberChange}
onChangePerPage={onResultsPerPageChange}
currentPage={pageNumber}
perPage={resultsPerPage}
/>
</div>
</div>
</div>
) : (
<div className="flex flex-col items-center justify-center pt-48">
{appConfig.showLoadingIndicator && isLoadingData ? (
<LoadingIndicatorProgress className={'h-full w-full bg-black'} />
) : (
<EmptyStudies />
)}
</div>
)}
) : (
<div className="flex flex-col items-center justify-center pt-48">
{appConfig.showLoadingIndicator && isLoadingData ? (
<LoadingIndicatorProgress className={'h-full w-full bg-black'} />
) : (
<EmptyStudies />
)}
</div>
)}
</ScrollArea>
</div>
</div>
);
+2 -5
View File
@@ -1,6 +1,6 @@
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import { ErrorBoundary } from '@ohif/ui';
import { ErrorBoundary } from '@ohif/ui-next';
// Route Components
import DataSourceWrapper from './DataSourceWrapper';
@@ -120,10 +120,7 @@ const createRoutes = ({
function RouteWithErrorBoundary({ route, ...rest }) {
// eslint-disable-next-line react/jsx-props-no-spreading
return (
<ErrorBoundary
context={`Route ${route.path}`}
fallbackRoute="/"
>
<ErrorBoundary context={`Route ${route.path}`}>
<route.children
{...rest}
{...route.props}
@@ -44,7 +44,7 @@ const initUserManager = (oidc, routerBasename) => {
post_logout_redirect_uri: _makeAbsoluteIfNecessary(post_logout_redirect_uri, baseUri),
});
const client = firstOpenIdClient.useAuthorizationCodeFlow ? NextClient : LegacyClient
const client = firstOpenIdClient.response_type === 'code' ? NextClient : LegacyClient;
return client(openIdConnectConfiguration);
};
+10 -10
View File
@@ -39,16 +39,16 @@ module.exports = {
mono: ['Menlo', 'Monaco', 'Consolas', '"Liberation Mono"', '"Courier New"', 'monospace'],
},
fontSize: {
xs: '0.65rem',
sm: '0.75rem',
base: '0.8125rem',
lg: '0.9275rem',
xl: '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
'4xl': '2.25rem',
'5xl': '3rem',
'6xl': '4rem',
xxs: '0.6875rem', // 11px
xs: '0.75rem', // 12px
sm: '0.8125rem', // 13px
base: '0.875rem', // 14px
lg: '1rem', // 16px
xl: '1.125rem', // 18px
'2xl': '1.25rem', // 20px
'3xl': '1.375rem', // 22px
'4xl': '1.5rem', // 24px
'5xl': '1.875rem', // 30px
},
},
};
+4
View File
@@ -2,3 +2,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
min-height: 0 !important;
}