Merge branch 'IbrahimCSAE-feat/interactive-onboarding-guides'
This commit is contained in:
commit
579a592812
20 files changed
+846
-4
No files matched your search
@@ -98,6 +98,8 @@
|
||||
"react-resize-detector": "^10.0.1",
|
||||
"react-router": "^6.23.1",
|
||||
"react-router-dom": "^6.8.1",
|
||||
"react-shepherd": "^6.1.1",
|
||||
"shepherd.js": "^13.0.3",
|
||||
"url-loader": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -291,4 +291,212 @@ window.config = {
|
||||
keys: ['9'],
|
||||
},
|
||||
],
|
||||
tours: [
|
||||
{
|
||||
id: 'basicViewerTour',
|
||||
route: '/viewer',
|
||||
steps: [
|
||||
{
|
||||
id: 'scroll',
|
||||
title: 'Scrolling Through Images',
|
||||
text: 'You can scroll through the images using the mouse wheel or scrollbar.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'top',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_WHEEL',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'zoom',
|
||||
title: 'Zooming In and Out',
|
||||
text: 'You can zoom the images using the right click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'pan',
|
||||
title: 'Panning the Image',
|
||||
text: 'You can pan the images using the middle click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'top',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'windowing',
|
||||
title: 'Adjusting Window Level',
|
||||
text: 'You can modify the window level using the left click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'length',
|
||||
title: 'Using the Measurement Tools',
|
||||
text: 'You can measure the length of a region using the Length tool.',
|
||||
attachTo: {
|
||||
element: '[data-cy="MeasurementTools-split-button-primary"]',
|
||||
on: 'bottom',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="MeasurementTools-split-button-primary"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () =>
|
||||
waitForElement('[data-cy="MeasurementTools-split-button-primary]'),
|
||||
},
|
||||
{
|
||||
id: 'drawAnnotation',
|
||||
title: 'Drawing Length Annotations',
|
||||
text: 'Use the length tool on the viewport to measure the length of a region.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'right',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: 'body',
|
||||
event: 'event::measurement_added',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'trackMeasurement',
|
||||
title: 'Tracking Measurements in the Panel',
|
||||
text: 'Click yes to track the measurements in the measurement panel.',
|
||||
attachTo: {
|
||||
element: '[data-cy="prompt-begin-tracking-yes-btn"]',
|
||||
on: 'bottom',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="prompt-begin-tracking-yes-btn"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="prompt-begin-tracking-yes-btn"]'),
|
||||
},
|
||||
{
|
||||
id: 'openMeasurementPanel',
|
||||
title: 'Opening the Measurements Panel',
|
||||
text: 'Click the measurements button to open the measurements panel.',
|
||||
attachTo: {
|
||||
element: '#trackedMeasurements-btn',
|
||||
on: 'left-start',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '#trackedMeasurements-btn',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('#trackedMeasurements-btn'),
|
||||
},
|
||||
{
|
||||
id: 'scrollAwayFromMeasurement',
|
||||
title: 'Scrolling Away from a Measurement',
|
||||
text: 'Scroll the images using the mouse wheel away from the measurement.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_WHEEL',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'jumpToMeasurement',
|
||||
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"]',
|
||||
on: 'left-start',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="measurement-item"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="measurement-item"]'),
|
||||
},
|
||||
{
|
||||
id: 'changeLayout',
|
||||
title: 'Changing Layout',
|
||||
text: 'You can change the layout of the viewer using the layout button.',
|
||||
attachTo: {
|
||||
element: '[data-cy="Layout"]',
|
||||
on: 'bottom',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="Layout"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="Layout"]'),
|
||||
},
|
||||
{
|
||||
id: 'selectLayout',
|
||||
title: 'Selecting the MPR Layout',
|
||||
text: 'Select the MPR layout to view the images in MPR mode.',
|
||||
attachTo: {
|
||||
element: '[data-cy="MPR"]',
|
||||
on: 'left-start',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="MPR"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="MPR"]'),
|
||||
},
|
||||
],
|
||||
tourOptions: {
|
||||
useModalOverlay: true,
|
||||
defaultStepOptions: {
|
||||
buttons: [
|
||||
{
|
||||
text: 'Skip all',
|
||||
action() {
|
||||
this.complete();
|
||||
},
|
||||
secondary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
function waitForElement(selector, maxAttempts = 20, interval = 25) {
|
||||
return new Promise(resolve => {
|
||||
let attempts = 0;
|
||||
|
||||
const checkForElement = setInterval(() => {
|
||||
const element = document.querySelector(selector);
|
||||
|
||||
if (element || attempts >= maxAttempts) {
|
||||
clearInterval(checkForElement);
|
||||
resolve();
|
||||
}
|
||||
|
||||
attempts++;
|
||||
}, interval);
|
||||
});
|
||||
}
|
||||
@@ -247,4 +247,212 @@ window.config = {
|
||||
keys: ['9'],
|
||||
},
|
||||
],
|
||||
tours: [
|
||||
{
|
||||
id: 'basicViewerTour',
|
||||
route: '/viewer',
|
||||
steps: [
|
||||
{
|
||||
id: 'scroll',
|
||||
title: 'Scrolling Through Images',
|
||||
text: 'You can scroll through the images using the mouse wheel or scrollbar.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'top',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_WHEEL',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'zoom',
|
||||
title: 'Zooming In and Out',
|
||||
text: 'You can zoom the images using the right click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'pan',
|
||||
title: 'Panning the Image',
|
||||
text: 'You can pan the images using the middle click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'top',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'windowing',
|
||||
title: 'Adjusting Window Level',
|
||||
text: 'You can modify the window level using the left click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'length',
|
||||
title: 'Using the Measurement Tools',
|
||||
text: 'You can measure the length of a region using the Length tool.',
|
||||
attachTo: {
|
||||
element: '[data-cy="MeasurementTools-split-button-primary"]',
|
||||
on: 'bottom',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="MeasurementTools-split-button-primary"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () =>
|
||||
waitForElement('[data-cy="MeasurementTools-split-button-primary]'),
|
||||
},
|
||||
{
|
||||
id: 'drawAnnotation',
|
||||
title: 'Drawing Length Annotations',
|
||||
text: 'Use the length tool on the viewport to measure the length of a region.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'right',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: 'body',
|
||||
event: 'event::measurement_added',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'trackMeasurement',
|
||||
title: 'Tracking Measurements in the Panel',
|
||||
text: 'Click yes to track the measurements in the measurement panel.',
|
||||
attachTo: {
|
||||
element: '[data-cy="prompt-begin-tracking-yes-btn"]',
|
||||
on: 'bottom',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="prompt-begin-tracking-yes-btn"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="prompt-begin-tracking-yes-btn"]'),
|
||||
},
|
||||
{
|
||||
id: 'openMeasurementPanel',
|
||||
title: 'Opening the Measurements Panel',
|
||||
text: 'Click the measurements button to open the measurements panel.',
|
||||
attachTo: {
|
||||
element: '#trackedMeasurements-btn',
|
||||
on: 'left-start',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '#trackedMeasurements-btn',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('#trackedMeasurements-btn'),
|
||||
},
|
||||
{
|
||||
id: 'scrollAwayFromMeasurement',
|
||||
title: 'Scrolling Away from a Measurement',
|
||||
text: 'Scroll the images using the mouse wheel away from the measurement.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_WHEEL',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('.viewport-element'),
|
||||
},
|
||||
{
|
||||
id: 'jumpToMeasurement',
|
||||
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"]',
|
||||
on: 'left-start',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="measurement-item"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="measurement-item"]'),
|
||||
},
|
||||
{
|
||||
id: 'changeLayout',
|
||||
title: 'Changing Layout',
|
||||
text: 'You can change the layout of the viewer using the layout button.',
|
||||
attachTo: {
|
||||
element: '[data-cy="Layout"]',
|
||||
on: 'bottom',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="Layout"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="Layout"]'),
|
||||
},
|
||||
{
|
||||
id: 'selectLayout',
|
||||
title: 'Selecting the MPR Layout',
|
||||
text: 'Select the MPR layout to view the images in MPR mode.',
|
||||
attachTo: {
|
||||
element: '[data-cy="MPR"]',
|
||||
on: 'left-start',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '[data-cy="MPR"]',
|
||||
event: 'click',
|
||||
},
|
||||
beforeShowPromise: () => waitForElement('[data-cy="MPR"]'),
|
||||
},
|
||||
],
|
||||
tourOptions: {
|
||||
useModalOverlay: true,
|
||||
defaultStepOptions: {
|
||||
buttons: [
|
||||
{
|
||||
text: 'Skip all',
|
||||
action() {
|
||||
this.complete();
|
||||
},
|
||||
secondary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
function waitForElement(selector, maxAttempts = 20, interval = 25) {
|
||||
return new Promise(resolve => {
|
||||
let attempts = 0;
|
||||
|
||||
const checkForElement = setInterval(() => {
|
||||
const element = document.querySelector(selector);
|
||||
|
||||
if (element || attempts >= maxAttempts) {
|
||||
clearInterval(checkForElement);
|
||||
resolve();
|
||||
}
|
||||
|
||||
attempts++;
|
||||
}, interval);
|
||||
});
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import { AppConfigProvider } from '@state';
|
||||
import createRoutes from './routes';
|
||||
import appInit from './appInit.js';
|
||||
import OpenIdConnectRoutes from './utils/OpenIdConnectRoutes';
|
||||
import { ShepherdJourneyProvider } from 'react-shepherd';
|
||||
|
||||
let commandsManager: CommandsManager,
|
||||
extensionManager: ExtensionManager,
|
||||
@@ -115,6 +116,7 @@ function App({
|
||||
[SnackbarProvider, { service: uiNotificationService }],
|
||||
[DialogProvider, { service: uiDialogService }],
|
||||
[ModalProvider, { service: uiModalService, modal: Modal }],
|
||||
[ShepherdJourneyProvider],
|
||||
];
|
||||
|
||||
// Loop through and register each of the service providers registered with the ServiceProvidersManager.
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
import { Types } from '@ohif/ui';
|
||||
|
||||
import i18n from '@ohif/i18n';
|
||||
import { Onboarding } from '@ohif/ui-next';
|
||||
|
||||
const PatientInfoVisibility = Types.PatientInfoVisibility;
|
||||
|
||||
@@ -411,7 +412,7 @@ function WorkList({
|
||||
disabled={!isValidMode}
|
||||
startIconTooltip={
|
||||
!isValidMode ? (
|
||||
<div className="font-inter flex w-[206px] whitespace-normal text-left text-xs font-normal text-white ">
|
||||
<div className="font-inter flex w-[206px] whitespace-normal text-left text-xs font-normal text-white">
|
||||
{invalidModeDescription}
|
||||
</div>
|
||||
) : null
|
||||
@@ -534,6 +535,7 @@ function WorkList({
|
||||
WhiteLabeling={appConfig.whiteLabeling}
|
||||
showPatientInfo={PatientInfoVisibility.DISABLED}
|
||||
/>
|
||||
<Onboarding />
|
||||
<InvestigationalUseDialog dialogConfiguration={appConfig?.investigationalUseDialog} />
|
||||
<div className="ohif-scrollbar ohif-scrollbar-stable-gutter flex grow flex-col overflow-y-auto sm:px-5">
|
||||
<StudyListFilter
|
||||
|
||||
Reference in new issue
Block a user