diff --git a/extensions/default/src/commandsModule.ts b/extensions/default/src/commandsModule.ts index 73b54b5dfd..172f00921c 100644 --- a/extensions/default/src/commandsModule.ts +++ b/extensions/default/src/commandsModule.ts @@ -11,6 +11,8 @@ import findViewportsByPosition, { } from './findViewportsByPosition'; import { ContextMenuProps } from './CustomizeableContextMenu/types'; +import { NavigateHistory } from './types/commandModuleTypes'; +import { history } from '@ohif/viewer'; 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() { const { activeViewportIndex, viewports } = viewportGridService.getState(); const activeViewportSpecificData = viewports[activeViewportIndex]; @@ -540,6 +564,11 @@ const commandsModule = ({ storeContexts: [], options: {}, }, + navigateHistory: { + commandFn: actions.navigateHistory, + storeContexts: [], + options: {}, + }, nextStage: { commandFn: actions.deltaStage, storeContexts: [], diff --git a/extensions/default/src/types/commandModuleTypes.tsx b/extensions/default/src/types/commandModuleTypes.tsx new file mode 100644 index 0000000000..d2cdde1345 --- /dev/null +++ b/extensions/default/src/types/commandModuleTypes.tsx @@ -0,0 +1,6 @@ +export type NavigateHistory = { + to: string; // the URL to navigate to + options?: { + replace?: boolean; // replace or add/push to history? + }; +}; diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx index 476e80a405..f73707220d 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx @@ -149,6 +149,10 @@ function TrackedMeasurementsContextProvider( activeViewport.displaySetInstanceUIDs[0] ); + if (!displaySet) { + return; + } + // If this is an SR produced by our SR SOPClassHandler, // and it hasn't been loaded yet, do that now so we // can check if it can be rehydrated or not. diff --git a/platform/docs/docs/platform/modes/routes.md b/platform/docs/docs/platform/modes/routes.md index 6e8647309d..36376a131f 100644 --- a/platform/docs/docs/platform/modes/routes.md +++ b/platform/docs/docs/platform/modes/routes.md @@ -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, + }, +``` diff --git a/platform/viewer/src/index.js b/platform/viewer/src/index.js index 49f47fa79c..6cec78ad22 100644 --- a/platform/viewer/src/index.js +++ b/platform/viewer/src/index.js @@ -5,6 +5,8 @@ import 'regenerator-runtime/runtime'; import App from './App'; import React from 'react'; import ReactDOM from 'react-dom'; +import { history } from './utils/history'; + /** * EXTENSIONS AND MODES * ================= @@ -34,3 +36,5 @@ loadDynamicImports().then(() => { ReactDOM.render(app, document.getElementById('root')); }); }); + +export { history }; diff --git a/platform/viewer/src/routes/Mode/Mode.tsx b/platform/viewer/src/routes/Mode/Mode.tsx index 7b06bf4459..7e7575bc0c 100644 --- a/platform/viewer/src/routes/Mode/Mode.tsx +++ b/platform/viewer/src/routes/Mode/Mode.tsx @@ -1,5 +1,5 @@ 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'; // TODO: DicomMetadataStore should be injected? import { DicomMetadataStore, ServicesManager, utils } from '@ohif/core'; @@ -8,6 +8,7 @@ import { useQuery, useSearchParams } from '@hooks'; import ViewportGrid from '@components/ViewportGrid'; import Compose from './Compose'; import getStudies from './studiesList'; +import { history } from '../../utils/history'; const { getSplitParam } = utils; @@ -105,6 +106,9 @@ export default function ModeRoute({ const locationRef = useRef(null); const isMounted = useRef(false); + // Expose the react router dom navigation. + history.navigate = useNavigate(); + if (location !== locationRef.current) { layoutTemplateData.current = null; locationRef.current = location; diff --git a/platform/viewer/src/utils/history.ts b/platform/viewer/src/utils/history.ts new file mode 100644 index 0000000000..57cdf7d35d --- /dev/null +++ b/platform/viewer/src/utils/history.ts @@ -0,0 +1,9 @@ +import { NavigateFunction } from 'react-router'; + +type History = { + navigate: NavigateFunction; +}; + +export const history: History = { + navigate: null, +};