Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab23feefbb | ||
|
|
4c079044f6 | ||
|
|
81fcfc7370 | ||
|
|
6ec6446787 | ||
|
|
4b5a43641a | ||
|
|
2fb0b01fe2 | ||
|
|
c0c3ab307d |
No files matched your search
@@ -269,7 +269,12 @@ jobs:
|
||||
paths: .
|
||||
|
||||
DOCS_PUBLISH:
|
||||
<<: *defaults
|
||||
docker:
|
||||
# Gitbook fails due to graceful-fs updates above this node version :-(
|
||||
- image: circleci/node:12.9.1
|
||||
environment:
|
||||
TERM: xterm # Enable colors in term
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
@@ -390,7 +395,7 @@ workflows:
|
||||
# Update hub.docker.org
|
||||
- cypress/run:
|
||||
name: 'Generate Percy Snapshots'
|
||||
executor: cypress/browsers-chrome76
|
||||
executor: chrome-and-pacs
|
||||
browser: chrome
|
||||
pre-steps:
|
||||
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
||||
@@ -467,7 +472,7 @@ workflows:
|
||||
# and record a Cypress dashboard test run
|
||||
- cypress/run:
|
||||
name: 'Generate Percy Snapshots'
|
||||
executor: cypress/browsers-chrome76
|
||||
executor: chrome-and-pacs
|
||||
browser: chrome
|
||||
pre-steps:
|
||||
- run: 'rm -rf ~/.yarn && npm i -g yarn && yarn -v && yarn global
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.0.4...@ohif/extension-dicom-tag-browser@0.0.5) (2020-12-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.0.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.0.3...@ohif/extension-dicom-tag-browser@0.0.4) (2020-10-07)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-tag-browser",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"description": "OHIF extension for checking DICOM headers.",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -247,10 +247,11 @@ function getRows(metadata, depth = 0) {
|
||||
sequenceAsArray.forEach(item => {
|
||||
const sequenceRows = getRows(item, depth + 1);
|
||||
|
||||
// Sort the sequence group.
|
||||
_sortTagList(sequenceRows);
|
||||
|
||||
sequence.values.push(sequenceRows);
|
||||
if (sequenceRows.length) {
|
||||
// Sort the sequence group.
|
||||
_sortTagList(sequenceRows);
|
||||
sequence.values.push(sequenceRows);
|
||||
}
|
||||
});
|
||||
|
||||
continue;
|
||||
@@ -276,13 +277,12 @@ function getRows(metadata, depth = 0) {
|
||||
} else if (value.Alphabetic) {
|
||||
value = value.Alphabetic;
|
||||
} else {
|
||||
console.error('Unrecognised Value for element:');
|
||||
console.error(value);
|
||||
console.warn(`Unrecognised Value: ${value} for ${keyword}:`);
|
||||
console.warn(value);
|
||||
value = ' ';
|
||||
}
|
||||
} else {
|
||||
console.error('Unrecognised Value for element:');
|
||||
console.error(value);
|
||||
console.warn(`Unrecognised Value: ${value} for ${keyword}:`);
|
||||
value = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.9.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.8.0...@ohif/extension-vtk@1.9.0) (2020-12-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add error boundary and retry logic for network failures during dynamic imports ([#2145](https://github.com/OHIF/Viewers/issues/2145)) ([4c07904](https://github.com/OHIF/Viewers/commit/4c079044f6ae2381c6054d8d77414100152d1d19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.8.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.7.16...@ohif/extension-vtk@1.8.0) (2020-11-30)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-vtk",
|
||||
"version": "1.8.0",
|
||||
"version": "1.9.0",
|
||||
"description": "OHIF extension for VTK.js",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -54,7 +54,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohif/core": "^2.10.7",
|
||||
"@ohif/ui": "^1.5.7",
|
||||
"@ohif/ui": "^1.6.0",
|
||||
"cornerstone-tools": "^4.20.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* We use this component to leverage "Code Splitting"
|
||||
*
|
||||
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default function asyncComponent(importComponent) {
|
||||
class AsyncComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
component: null,
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
// Add dynamically loaded component to state
|
||||
const { default: component } = await importComponent();
|
||||
|
||||
this.setState({
|
||||
component: component,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const C = this.state.component;
|
||||
|
||||
// Render the loaded component, or null
|
||||
return C ? <C {...this.props} /> : null;
|
||||
}
|
||||
}
|
||||
|
||||
return AsyncComponent;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import asyncComponent from './asyncComponent.js';
|
||||
import { asyncComponent, retryImport } from '@ohif/ui';
|
||||
|
||||
import commandsModule from './commandsModule.js';
|
||||
import toolbarModule from './toolbarModule.js';
|
||||
import withCommandsManager from './withCommandsManager.js';
|
||||
@@ -8,7 +9,7 @@ import { version } from '../package.json';
|
||||
// import loadLocales from './loadLocales';
|
||||
|
||||
const OHIFVTKViewport = asyncComponent(() =>
|
||||
import(/* webpackChunkName: "OHIFVTKViewport" */ './OHIFVTKViewport.js')
|
||||
retryImport(() => import(/* webpackChunkName: "OHIFVTKViewport" */ './OHIFVTKViewport.js'))
|
||||
);
|
||||
|
||||
const vtkExtension = {
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.6.0](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.5.7...@ohif/ui@1.6.0) (2020-12-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add error boundary and retry logic for network failures during dynamic imports ([#2145](https://github.com/OHIF/Viewers/issues/2145)) ([4c07904](https://github.com/OHIF/Viewers/commit/4c079044f6ae2381c6054d8d77414100152d1d19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.5.7](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.5.6...@ohif/ui@1.5.7) (2020-11-02)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/ui",
|
||||
"version": "1.5.7",
|
||||
"version": "1.6.0",
|
||||
"description": "A set of React components for Medical Imaging Viewers",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.ErrorPage {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
color: var(--active-color);
|
||||
}
|
||||
|
||||
.ErrorPage .error-container {
|
||||
margin: 10px;
|
||||
width: 50%;
|
||||
height: 25%;
|
||||
overflow: scroll;
|
||||
border-radius: 15px;
|
||||
border-color: var(--active-color);
|
||||
border: 1px solid;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.ErrorPage .retry-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Icon } from '@ohif/ui';
|
||||
|
||||
import './ErrorPage.css';
|
||||
|
||||
const ErrorPage = ({ error, title, description, onRetry }) => {
|
||||
return (
|
||||
<div className="ErrorPage">
|
||||
{title && <h3>{title}</h3>}
|
||||
<p>{description}</p>
|
||||
<Icon
|
||||
className="retry-icon"
|
||||
name="rotate-right"
|
||||
width="25px"
|
||||
height="25px"
|
||||
onClick={onRetry}
|
||||
/>
|
||||
{error && (
|
||||
<div className="error-container">
|
||||
<pre>{error.message}</pre>
|
||||
<pre>{error.stack}</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ErrorPage.propTypes = {
|
||||
error: PropTypes.object,
|
||||
title: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
onRetry: PropTypes.func
|
||||
};
|
||||
|
||||
ErrorPage.defaultProps = {
|
||||
description: 'Oh snap, something went wrong, please try reloading',
|
||||
onRetry: () => window.location.reload()
|
||||
};
|
||||
|
||||
export default ErrorPage;
|
||||
@@ -0,0 +1,2 @@
|
||||
import ErrorPage from './ErrorPage';
|
||||
export default ErrorPage;
|
||||
@@ -16,6 +16,7 @@ import { SelectTree } from './selectTree';
|
||||
import { SimpleDialog } from './simpleDialog';
|
||||
import { OHIFModal } from './ohifModal';
|
||||
import { ContextMenu } from './contextMenu';
|
||||
import ErrorPage from './errorPage';
|
||||
import {
|
||||
PageToolbar,
|
||||
StudyList,
|
||||
@@ -58,4 +59,5 @@ export {
|
||||
Tooltip,
|
||||
AboutContent,
|
||||
OHIFModal,
|
||||
ErrorPage
|
||||
};
|
||||
@@ -29,7 +29,8 @@ import {
|
||||
Tooltip,
|
||||
AboutContent,
|
||||
OHIFModal,
|
||||
ErrorBoundary
|
||||
ErrorBoundary,
|
||||
ErrorPage
|
||||
} from './components';
|
||||
import { useDebounce, useMedia } from './hooks';
|
||||
|
||||
@@ -53,6 +54,7 @@ import { ScrollableArea } from './ScrollableArea/ScrollableArea.js';
|
||||
import Toolbar from './viewer/Toolbar.js';
|
||||
import ToolbarButton from './viewer/ToolbarButton.js';
|
||||
import ViewerbaseDragDropContext from './utils/viewerbaseDragDropContext.js';
|
||||
import { asyncComponent, retryImport } from './utils/asyncComponent';
|
||||
import {
|
||||
SnackbarProvider,
|
||||
useSnackbarContext,
|
||||
@@ -112,7 +114,6 @@ export {
|
||||
ToolbarSection,
|
||||
Tooltip,
|
||||
AboutContent,
|
||||
ViewerbaseDragDropContext,
|
||||
SnackbarProvider,
|
||||
useSnackbarContext,
|
||||
withSnackbar,
|
||||
@@ -125,7 +126,12 @@ export {
|
||||
withDialog,
|
||||
useDialog,
|
||||
ErrorBoundary,
|
||||
ErrorPage,
|
||||
// Hooks
|
||||
useDebounce,
|
||||
useMedia,
|
||||
// Utils
|
||||
ViewerbaseDragDropContext,
|
||||
asyncComponent,
|
||||
retryImport
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ErrorPage } from '@ohif/ui';
|
||||
|
||||
export const retryImport = (fn, retriesLeft = 5, interval = 1000) =>
|
||||
new Promise((resolve, reject) => {
|
||||
fn().then(resolve).catch((error) => {
|
||||
setTimeout(() => {
|
||||
if (retriesLeft === 1) {
|
||||
/* reject('maximum retries exceeded'); */
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Passing on "reject" is the important part */
|
||||
retry(fn, retriesLeft - 1, interval).then(resolve, reject);
|
||||
}, interval);
|
||||
});
|
||||
});
|
||||
|
||||
const onError = (error, setState) => setState({ component: ErrorPage });
|
||||
|
||||
/**
|
||||
* We use this function to lazy load the import of a component to leverage 'Code Splitting'
|
||||
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||
*/
|
||||
const asyncComponent = (importComponent, options = { onError }) => props => {
|
||||
const [state, setState] = useState({ component: null });
|
||||
|
||||
const isFunction = item => typeof item === 'function';
|
||||
const isChunkError = error => error.toString().indexOf('ChunkLoadError') > -1;
|
||||
|
||||
useEffect(() => {
|
||||
const addDynamicallyLoadedComponentToState = async () => {
|
||||
try {
|
||||
const { default: component } = await importComponent();
|
||||
setState({ component });
|
||||
if (options.onLoaded && isFunction(options.onLoaded)) {
|
||||
options.onLoaded(component);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[AsyncComponent] Failed to import chunk:', error);
|
||||
|
||||
if (options.onError && isFunction(options.onError)) {
|
||||
options.onError(error, setState);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isChunkError(error)) {
|
||||
console.error('[AsyncComponent] Reloading due to chunk error');
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
addDynamicallyLoadedComponentToState();
|
||||
}, []);
|
||||
|
||||
const Component = state.component;
|
||||
return Component ? <Component {...props} /> : null;
|
||||
};
|
||||
|
||||
export default asyncComponent;
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as asyncComponent } from './asyncComponent';
|
||||
export { retryImport } from './asyncComponent';
|
||||
@@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [4.6.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.29...@ohif/viewer@4.6.0) (2020-12-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add error boundary and retry logic for network failures during dynamic imports ([#2145](https://github.com/OHIF/Viewers/issues/2145)) ([4c07904](https://github.com/OHIF/Viewers/commit/4c079044f6ae2381c6054d8d77414100152d1d19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.5.29](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.28...@ohif/viewer@4.5.29) (2020-12-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/viewer",
|
||||
"version": "4.5.29",
|
||||
"version": "4.6.0",
|
||||
"description": "OHIF Viewer",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
@@ -58,9 +58,9 @@
|
||||
"@ohif/extension-dicom-rt": "^0.4.9",
|
||||
"@ohif/extension-dicom-segmentation": "^0.4.7",
|
||||
"@ohif/extension-lesion-tracker": "^0.2.1",
|
||||
"@ohif/extension-vtk": "^1.8.0",
|
||||
"@ohif/extension-vtk": "^1.9.0",
|
||||
"@ohif/i18n": "^0.53.0",
|
||||
"@ohif/ui": "^1.5.7",
|
||||
"@ohif/ui": "^1.6.0",
|
||||
"@tanem/react-nprogress": "^1.1.25",
|
||||
"classnames": "^2.2.6",
|
||||
"core-js": "^3.2.1",
|
||||
|
||||
@@ -5,9 +5,8 @@ import { Route, Switch } from 'react-router-dom';
|
||||
import { NProgress } from '@tanem/react-nprogress';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
import { connect } from 'react-redux';
|
||||
import { ViewerbaseDragDropContext, ErrorBoundary } from '@ohif/ui';
|
||||
import { ViewerbaseDragDropContext, ErrorBoundary, asyncComponent, retryImport } from '@ohif/ui';
|
||||
import { SignoutCallbackComponent } from 'redux-oidc';
|
||||
import asyncComponent from './components/AsyncComponent.js';
|
||||
import * as RoutesUtil from './routes/routesUtil';
|
||||
|
||||
import NotFound from './routes/NotFound.js';
|
||||
@@ -18,7 +17,7 @@ import './theme-tide.css';
|
||||
// Contexts
|
||||
import AppContext from './context/AppContext';
|
||||
const CallbackPage = asyncComponent(() =>
|
||||
import(/* webpackChunkName: "CallbackPage" */ './routes/CallbackPage.js')
|
||||
retryImport(() => import(/* webpackChunkName: "CallbackPage" */ './routes/CallbackPage.js'))
|
||||
);
|
||||
|
||||
class OHIFStandaloneViewer extends Component {
|
||||
@@ -203,10 +202,10 @@ class OHIFStandaloneViewer extends Component {
|
||||
{match === null ? (
|
||||
<></>
|
||||
) : (
|
||||
<ErrorBoundary context={match.url}>
|
||||
<Component match={match} location={this.props.location} />
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
<ErrorBoundary context={match.url}>
|
||||
<Component match={match} location={this.props.location} />
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
</CSSTransition>
|
||||
)}
|
||||
</Route>
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* We use this component to leverage "Code Splitting"
|
||||
*
|
||||
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default function asyncComponent(importComponent) {
|
||||
class AsyncComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
component: null,
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
// Add dynamically loaded component to state
|
||||
const { default: component } = await importComponent();
|
||||
|
||||
this.setState({
|
||||
component: component,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const C = this.state.component;
|
||||
|
||||
// Render the loaded component, or null
|
||||
return C ? <C {...this.props} /> : null;
|
||||
}
|
||||
}
|
||||
|
||||
return AsyncComponent;
|
||||
}
|
||||
@@ -1,32 +1,32 @@
|
||||
import asyncComponent from '../components/AsyncComponent.js';
|
||||
|
||||
import { asyncComponent, retryImport } from '@ohif/ui';
|
||||
import OHIF from '@ohif/core';
|
||||
|
||||
const { urlUtil: UrlUtil } = OHIF.utils;
|
||||
|
||||
// Dynamic Import Routes (CodeSplitting)
|
||||
const IHEInvokeImageDisplay = asyncComponent(() =>
|
||||
import(
|
||||
/* webpackChunkName: "IHEInvokeImageDisplay" */ './IHEInvokeImageDisplay.js'
|
||||
retryImport(() =>
|
||||
import(/* webpackChunkName: "IHEInvokeImageDisplay" */ './IHEInvokeImageDisplay.js')
|
||||
)
|
||||
);
|
||||
const ViewerRouting = asyncComponent(() =>
|
||||
import(/* webpackChunkName: "ViewerRouting" */ './ViewerRouting.js')
|
||||
retryImport(() => import(/* webpackChunkName: "ViewerRouting" */ './ViewerRouting.js'))
|
||||
);
|
||||
|
||||
const StudyListRouting = asyncComponent(() =>
|
||||
import(
|
||||
retryImport(() => import(
|
||||
/* webpackChunkName: "StudyListRouting" */ '../studylist/StudyListRouting.js'
|
||||
)
|
||||
))
|
||||
);
|
||||
const StandaloneRouting = asyncComponent(() =>
|
||||
import(
|
||||
retryImport(() => import(
|
||||
/* webpackChunkName: "ConnectedStandaloneRouting" */ '../connectedComponents/ConnectedStandaloneRouting.js'
|
||||
)
|
||||
))
|
||||
);
|
||||
const ViewerLocalFileData = asyncComponent(() =>
|
||||
import(
|
||||
retryImport(() => import(
|
||||
/* webpackChunkName: "ViewerLocalFileData" */ '../connectedComponents/ViewerLocalFileData.js'
|
||||
)
|
||||
))
|
||||
);
|
||||
|
||||
const reload = () => window.location.reload();
|
||||
|
||||
Reference in new issue
Block a user