diff options
Diffstat (limited to 'server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx')
-rw-r--r-- | server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx b/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx index e1194406c2e..6021e0ec732 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx @@ -25,30 +25,38 @@ import { PageContentFontWrapper, } from 'design-system'; import * as React from 'react'; +import { useState } from 'react'; import A11ySkipTarget from '~sonar-aligned/components/a11y/A11ySkipTarget'; import { useLocation, useRouter } from '~sonar-aligned/components/hoc/withRouter'; import { isPortfolioLike } from '~sonar-aligned/helpers/component'; import { ComponentQualifier } from '~sonar-aligned/types/component'; +import { CurrentUserContext } from '../../../app/components/current-user/CurrentUserContext'; import AnalysisMissingInfoMessage from '../../../components/shared/AnalysisMissingInfoMessage'; import { parseDate } from '../../../helpers/dates'; +import { translate } from '../../../helpers/l10n'; import { areCCTMeasuresComputed, isDiffMetric } from '../../../helpers/measures'; import { CodeScope } from '../../../helpers/urls'; +import { useDismissNoticeMutation } from '../../../queries/users'; import { ApplicationPeriod } from '../../../types/application'; import { Branch } from '../../../types/branch-like'; import { Analysis, GraphType, MeasureHistory } from '../../../types/project-activity'; import { QualityGateStatus } from '../../../types/quality-gates'; import { Component, MeasureEnhanced, Metric, Period, QualityGate } from '../../../types/types'; +import { NoticeType } from '../../../types/users'; import { AnalysisStatus } from '../components/AnalysisStatus'; import LastAnalysisLabel from '../components/LastAnalysisLabel'; import ActivityPanel from './ActivityPanel'; import BranchMetaTopBar from './BranchMetaTopBar'; +import CaycPromotionGuide from './CaycPromotionGuide'; import FirstAnalysisNextStepsNotif from './FirstAnalysisNextStepsNotif'; import MeasuresPanelNoNewCode from './MeasuresPanelNoNewCode'; import NewCodeMeasuresPanel from './NewCodeMeasuresPanel'; import NoCodeWarning from './NoCodeWarning'; import OverallCodeMeasuresPanel from './OverallCodeMeasuresPanel'; +import PromotedSection from './PromotedSection'; import QualityGatePanel from './QualityGatePanel'; import { QualityGateStatusTitle } from './QualityGateStatusTitle'; +import ReplayTourGuide from './ReplayTour'; import SonarLintPromotion from './SonarLintPromotion'; import { TabsPanel } from './TabsPanel'; @@ -96,6 +104,18 @@ export default function BranchOverviewRenderer(props: BranchOverviewRendererProp const { query } = useLocation(); const router = useRouter(); + const { currentUser } = React.useContext(CurrentUserContext); + + const { mutateAsync: dismissNotice } = useDismissNoticeMutation(); + + const [startTour, setStartTour] = useState(false); + const [tourCompleted, setTourCompleted] = useState(false); + const [showReplay, setShowReplay] = useState(false); + const [dismissedTour, setDismissedTour] = useState( + currentUser.isLoggedIn && + !!currentUser.dismissedNotices[NoticeType.ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE], + ); + const tab = query.codeScope === CodeScope.Overall ? CodeScope.Overall : CodeScope.New; const leakPeriod = component.qualifier === ComponentQualifier.Application ? appLeak : period; const isNewCodeTab = tab === CodeScope.New; @@ -126,6 +146,33 @@ export default function BranchOverviewRenderer(props: BranchOverviewRendererProp /> ); + const dismissPromotedSection = () => { + dismissNotice(NoticeType.ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE); + + setDismissedTour(true); + setShowReplay(true); + }; + + const closeTour = (action: string) => { + setStartTour(false); + if (action === 'skip' && !dismissedTour) { + dismissPromotedSection(); + } + + if (action === 'close' && !dismissedTour) { + dismissPromotedSection(); + setTourCompleted(true); + } + }; + + const startTourGuide = () => { + if (!isNewCodeTab) { + selectTab(CodeScope.New); + } + setShowReplay(false); + setStartTour(true); + }; + return ( <> <FirstAnalysisNextStepsNotif @@ -135,6 +182,14 @@ export default function BranchOverviewRenderer(props: BranchOverviewRendererProp /> <LargeCenteredLayout> <PageContentFontWrapper> + <CaycPromotionGuide closeTour={closeTour} run={startTour} /> + {showReplay && ( + <ReplayTourGuide + closeTour={() => setShowReplay(false)} + run={showReplay} + tourCompleted={tourCompleted} + /> + )} <div className="overview sw-my-6 sw-body-sm"> <A11ySkipTarget anchor="overview_main" /> @@ -144,7 +199,27 @@ export default function BranchOverviewRenderer(props: BranchOverviewRendererProp <div> {branch && ( <> - <BranchMetaTopBar branch={branch} component={component} measures={measures} /> + {currentUser.isLoggedIn && ( + <PromotedSection + content={translate('overview.promoted_section.content')} + dismissed={dismissedTour ?? false} + onDismiss={dismissPromotedSection} + onPrimaryButtonClick={startTourGuide} + primaryButtonLabel={translate('overview.promoted_section.button_primary')} + secondaryButtonLabel={translate( + 'overview.promoted_section.button_secondary', + )} + title={translate('overview.promoted_section.title')} + /> + )} + + <BranchMetaTopBar + branch={branch} + component={component} + measures={measures} + showTakeTheTourButton={dismissedTour && currentUser.isLoggedIn} + startTour={startTourGuide} + /> <BasicSeparator /> </> )} |