fix(Browser history): fixed NPE when navigating a study via browser history and history navigation is now available via the navigateHistory command (#3337)
* fix(Browser history): - fixed an NPE when navigating to a different study via the URL - exposed browser history navigation via a command * Added documentation for the navigateHistory command. Moved the history object from UI to viewer.
This commit is contained in:
parent
eea0ed487b
commit
51cb0519fc
@ -11,6 +11,8 @@ import findViewportsByPosition, {
|
|||||||
} from './findViewportsByPosition';
|
} from './findViewportsByPosition';
|
||||||
|
|
||||||
import { ContextMenuProps } from './CustomizeableContextMenu/types';
|
import { ContextMenuProps } from './CustomizeableContextMenu/types';
|
||||||
|
import { NavigateHistory } from './types/commandModuleTypes';
|
||||||
|
import { history } from '@ohif/viewer';
|
||||||
|
|
||||||
const { subscribeToNextViewportGridChange } = utils;
|
const { subscribeToNextViewportGridChange } = utils;
|
||||||
|
|
||||||
@ -480,6 +482,28 @@ const commandsModule = ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes the browser history navigation used by OHIF. This command can be used to either replace or
|
||||||
|
* push a new entry into the browser history. For example, the following will replace the current
|
||||||
|
* browser history entry with the specified relative URL which changes the study displayed to the
|
||||||
|
* study with study instance UID 1.2.3. Note that as a result of using `options.replace = true`, the
|
||||||
|
* page prior to invoking this command cannot be returned to via the browser back button.
|
||||||
|
*
|
||||||
|
* navigateHistory({
|
||||||
|
* to: 'viewer?StudyInstanceUIDs=1.2.3',
|
||||||
|
* options: { replace: true },
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* @param historyArgs - arguments for the history function;
|
||||||
|
* the `to` property is the URL;
|
||||||
|
* the `options.replace` is a boolean indicating if the current browser history entry
|
||||||
|
* should be replaced or a new entry pushed onto the history (stack); the default value
|
||||||
|
* for `replace` is false
|
||||||
|
*/
|
||||||
|
navigateHistory(historyArgs: NavigateHistory) {
|
||||||
|
history.navigate(historyArgs.to, historyArgs.options);
|
||||||
|
},
|
||||||
|
|
||||||
openDICOMTagViewer() {
|
openDICOMTagViewer() {
|
||||||
const { activeViewportIndex, viewports } = viewportGridService.getState();
|
const { activeViewportIndex, viewports } = viewportGridService.getState();
|
||||||
const activeViewportSpecificData = viewports[activeViewportIndex];
|
const activeViewportSpecificData = viewports[activeViewportIndex];
|
||||||
@ -540,6 +564,11 @@ const commandsModule = ({
|
|||||||
storeContexts: [],
|
storeContexts: [],
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
|
navigateHistory: {
|
||||||
|
commandFn: actions.navigateHistory,
|
||||||
|
storeContexts: [],
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
nextStage: {
|
nextStage: {
|
||||||
commandFn: actions.deltaStage,
|
commandFn: actions.deltaStage,
|
||||||
storeContexts: [],
|
storeContexts: [],
|
||||||
|
|||||||
6
extensions/default/src/types/commandModuleTypes.tsx
Normal file
6
extensions/default/src/types/commandModuleTypes.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export type NavigateHistory = {
|
||||||
|
to: string; // the URL to navigate to
|
||||||
|
options?: {
|
||||||
|
replace?: boolean; // replace or add/push to history?
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -149,6 +149,10 @@ function TrackedMeasurementsContextProvider(
|
|||||||
activeViewport.displaySetInstanceUIDs[0]
|
activeViewport.displaySetInstanceUIDs[0]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!displaySet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is an SR produced by our SR SOPClassHandler,
|
// If this is an SR produced by our SR SOPClassHandler,
|
||||||
// and it hasn't been loaded yet, do that now so we
|
// and it hasn't been loaded yet, do that now so we
|
||||||
// can check if it can be rehydrated or not.
|
// can check if it can be rehydrated or not.
|
||||||
|
|||||||
@ -313,3 +313,34 @@ function modeFactory() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> How can I navigate to (or show) a different study via the browser history/URL?
|
||||||
|
|
||||||
|
There is a command that does this: `navigateHistory`. It takes an object
|
||||||
|
argument with the `NavigateHistory` type:
|
||||||
|
|
||||||
|
```
|
||||||
|
export type NavigateHistory = {
|
||||||
|
to: string; // the URL to navigate to
|
||||||
|
options?: {
|
||||||
|
replace?: boolean; // replace or add/push to history?
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
For instance one could bind a hot key to this command to show a specific study
|
||||||
|
like this...
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
commandName: 'navigateHistory',
|
||||||
|
commandOptions: {
|
||||||
|
to:
|
||||||
|
'/viewer?StudyInstanceUIDs=1.2.3',
|
||||||
|
},
|
||||||
|
context: 'DEFAULT',
|
||||||
|
label: 'Nav Study',
|
||||||
|
keys: ['n'],
|
||||||
|
isEditable: true,
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import 'regenerator-runtime/runtime';
|
|||||||
import App from './App';
|
import App from './App';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import { history } from './utils/history';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EXTENSIONS AND MODES
|
* EXTENSIONS AND MODES
|
||||||
* =================
|
* =================
|
||||||
@ -34,3 +36,5 @@ loadDynamicImports().then(() => {
|
|||||||
ReactDOM.render(app, document.getElementById('root'));
|
ReactDOM.render(app, document.getElementById('root'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export { history };
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState, useRef } from 'react';
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
import { useParams, useLocation } from 'react-router';
|
import { useParams, useLocation, useNavigate } from 'react-router';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
// TODO: DicomMetadataStore should be injected?
|
// TODO: DicomMetadataStore should be injected?
|
||||||
import { DicomMetadataStore, ServicesManager, utils } from '@ohif/core';
|
import { DicomMetadataStore, ServicesManager, utils } from '@ohif/core';
|
||||||
@ -8,6 +8,7 @@ import { useQuery, useSearchParams } from '@hooks';
|
|||||||
import ViewportGrid from '@components/ViewportGrid';
|
import ViewportGrid from '@components/ViewportGrid';
|
||||||
import Compose from './Compose';
|
import Compose from './Compose';
|
||||||
import getStudies from './studiesList';
|
import getStudies from './studiesList';
|
||||||
|
import { history } from '../../utils/history';
|
||||||
|
|
||||||
const { getSplitParam } = utils;
|
const { getSplitParam } = utils;
|
||||||
|
|
||||||
@ -105,6 +106,9 @@ export default function ModeRoute({
|
|||||||
const locationRef = useRef(null);
|
const locationRef = useRef(null);
|
||||||
const isMounted = useRef(false);
|
const isMounted = useRef(false);
|
||||||
|
|
||||||
|
// Expose the react router dom navigation.
|
||||||
|
history.navigate = useNavigate();
|
||||||
|
|
||||||
if (location !== locationRef.current) {
|
if (location !== locationRef.current) {
|
||||||
layoutTemplateData.current = null;
|
layoutTemplateData.current = null;
|
||||||
locationRef.current = location;
|
locationRef.current = location;
|
||||||
|
|||||||
9
platform/viewer/src/utils/history.ts
Normal file
9
platform/viewer/src/utils/history.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { NavigateFunction } from 'react-router';
|
||||||
|
|
||||||
|
type History = {
|
||||||
|
navigate: NavigateFunction;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const history: History = {
|
||||||
|
navigate: null,
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user