diff options
author | Ismail Cherri <ismail.cherri@sonarsource.com> | 2024-12-09 16:13:46 +0100 |
---|---|---|
committer | Steve Marion <steve.marion@sonarsource.com> | 2024-12-18 11:13:21 +0100 |
commit | cb1d3ed779a9057f0235c5331842f2d0d57a89cd (patch) | |
tree | 5bc4333343f030c1f8548f4335fe87a84eb4a978 /server/sonar-web/src/main/js/app | |
parent | 580d16d64bc1465a30704adc0be6dd8f1aabd24e (diff) | |
download | sonarqube-cb1d3ed779a9057f0235c5331842f2d0d57a89cd.tar.gz sonarqube-cb1d3ed779a9057f0235c5331842f2d0d57a89cd.zip |
SONAR-23896 Improve MQR tour
Diffstat (limited to 'server/sonar-web/src/main/js/app')
-rw-r--r-- | server/sonar-web/src/main/js/app/components/ModeTour.tsx | 30 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/app/components/__tests__/ModeTour-test.tsx | 11 |
2 files changed, 34 insertions, 7 deletions
diff --git a/server/sonar-web/src/main/js/app/components/ModeTour.tsx b/server/sonar-web/src/main/js/app/components/ModeTour.tsx index c8aa12cba4f..faed47193d3 100644 --- a/server/sonar-web/src/main/js/app/components/ModeTour.tsx +++ b/server/sonar-web/src/main/js/app/components/ModeTour.tsx @@ -111,6 +111,18 @@ export default function ModeTour() { return () => document.removeEventListener(CustomEvents.RunTourMode, listener); }, []); + useEffect(() => { + const listener = () => { + // dismiss tour if help menu is closed and user has not completed all steps + if (step >= MAX_STEPS) { + dismissTour(); + } + }; + document.addEventListener(CustomEvents.HelpMenuClosed, listener); + + return () => document.removeEventListener(CustomEvents.HelpMenuClosed, listener); + }, [dismissTour, step]); + const isAdmin = currentUser.permissions?.global.includes(Permissions.Admin); const isAdminOrQGAdmin = isAdmin || currentUser.permissions?.global.includes(Permissions.QualityGateAdmin); @@ -151,7 +163,6 @@ export default function ModeTour() { title: intl.formatMessage({ id: 'mode_tour.step5.title' }), content: null, placement: 'left', - hideFooter: true, }, ]; @@ -174,10 +185,12 @@ export default function ModeTour() { <Image alt={intl.formatMessage({ id: `mode_tour.step${step}.img_alt` })} className="sw-w-full sw-mb-4" - src={`/images/mode-tour/step${step}.png`} + src={`/images/mode-tour/step${isStandardMode && step === 4 ? step + '_se' : step}.png`} /> {intl.formatMessage( - { id: `mode_tour.step${step}.description` }, + { + id: `mode_tour.step${step}.description`, + }, { mode: intl.formatMessage({ id: `settings.mode.${isStandardMode ? 'standard' : 'mqr'}.name`, @@ -219,12 +232,19 @@ export default function ModeTour() { steps={steps} run={step > maxModalSteps} continuous - disableOverlay={false} + disableOverlay showProgress={step !== 5} stepIndex={step - maxModalSteps - 1} nextLabel={intl.formatMessage({ id: 'next' })} + closeLabel={intl.formatMessage({ id: 'got_it' })} + backLabel="" stepXofYLabel={(x: number) => - intl.formatMessage({ id: 'guiding.step_x_of_y' }, { 0: x + maxModalSteps, 1: MAX_STEPS }) + x + maxModalSteps <= MAX_STEPS + ? intl.formatMessage( + { id: 'guiding.step_x_of_y' }, + { 0: x + maxModalSteps, 1: MAX_STEPS }, + ) + : '' } /> </> diff --git a/server/sonar-web/src/main/js/app/components/__tests__/ModeTour-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/ModeTour-test.tsx index a1135f4bea4..a5767acc77a 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/ModeTour-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/ModeTour-test.tsx @@ -41,6 +41,7 @@ const ui = { close: byRole('button', { name: 'modal.close' }), skip: byRole('button', { name: 'skip' }), letsgo: byRole('button', { name: 'lets_go' }), + gotit: byRole('button', { name: 'got_it' }), help: byRole('button', { name: 'help' }), guidePopup: byRole('alertdialog'), tourTrigger: byRole('menuitem', { name: 'mode_tour.name' }), @@ -92,6 +93,7 @@ it('renders the tour for admin', async () => { expect(ui.guidePopup.query()).not.toHaveTextContent('guiding.step_x_of_y'); expect(ui.next.query()).not.toBeInTheDocument(); expect(ui.skip.get()).toBeInTheDocument(); + expect(ui.gotit.get()).toBeInTheDocument(); await user.click(ui.skip.get()); expect(ui.tourTrigger.query()).not.toBeInTheDocument(); @@ -140,7 +142,8 @@ it('renders the tour for gateadmins', async () => { expect(ui.guidePopup.query()).not.toHaveTextContent('guiding.step_x_of_y'); expect(ui.next.query()).not.toBeInTheDocument(); expect(ui.skip.get()).toBeInTheDocument(); - await user.click(ui.skip.get()); + expect(ui.gotit.get()).toBeInTheDocument(); + await user.click(ui.gotit.get()); expect(ui.tourTrigger.query()).not.toBeInTheDocument(); expect(ui.dialog.query()).not.toBeInTheDocument(); @@ -175,7 +178,11 @@ it('should highlight the replay button on closing the dialog', async () => { expect(ui.tourTrigger.get()).toBeInTheDocument(); expect(await ui.guidePopup.find()).toBeInTheDocument(); expect(ui.skip.get()).toBeInTheDocument(); - await user.click(ui.skip.get()); + expect(ui.gotit.get()).toBeInTheDocument(); + // Closing the help menu dismisses the tour as well + await user.click(ui.help.get()); + + expect(ui.guidePopup.query()).not.toBeInTheDocument(); }); it('should not render the tour for regular users', async () => { |