aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/overview/branches/BranchOverviewRenderer.tsx
diff options
context:
space:
mode:
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.tsx77
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 />
</>
)}