@@ -237,6 +237,7 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender | |||
baseUrl={baseUrl} | |||
component={component} | |||
currentUser={currentUser} | |||
willRefreshAutomatically={willRefreshAutomatically} | |||
/> | |||
)} | |||
</> |
@@ -21,10 +21,11 @@ import * as React from 'react'; | |||
import { Button } from 'sonar-ui-common/components/controls/buttons'; | |||
import { translate } from 'sonar-ui-common/helpers/l10n'; | |||
import { AlmKeys } from '../../../types/alm-settings'; | |||
import AllSetStep from '../components/AllSetStep'; | |||
import FinishButton from '../components/FinishButton'; | |||
import Step from '../components/Step'; | |||
import BranchAnalysisStepContent from './BranchAnalysisStepContent'; | |||
import ExtensionInstallationStepContent from './ExtensionInstallationStepContent'; | |||
import SaveAndRunStepContent from './SaveAndRunStepContent'; | |||
import ServiceEndpointStepContent from './ServiceEndpointStepContent'; | |||
export interface AzurePipelinesTutorialProps { | |||
@@ -32,13 +33,14 @@ export interface AzurePipelinesTutorialProps { | |||
baseUrl: string; | |||
component: T.Component; | |||
currentUser: T.LoggedInUser; | |||
willRefreshAutomatically?: boolean; | |||
} | |||
export enum Steps { | |||
ExtensionInstallation, | |||
ServiceEndpoint, | |||
BranchAnalysis, | |||
SaveAndRun | |||
AllSet | |||
} | |||
interface Step { | |||
@@ -48,7 +50,7 @@ interface Step { | |||
} | |||
export default function AzurePipelinesTutorial(props: AzurePipelinesTutorialProps) { | |||
const { alm, baseUrl, component, currentUser } = props; | |||
const { alm, baseUrl, component, currentUser, willRefreshAutomatically } = props; | |||
const [currentStep, setCurrentStep] = React.useState(Steps.ExtensionInstallation); | |||
const [isCurrentStepValid, setIsCurrentStepValid] = React.useState(false); | |||
@@ -74,8 +76,7 @@ export default function AzurePipelinesTutorial(props: AzurePipelinesTutorialProp | |||
/> | |||
), | |||
checkValidity: true | |||
}, | |||
{ step: Steps.SaveAndRun, content: <SaveAndRunStepContent alm={alm} /> } | |||
} | |||
]; | |||
const switchCurrentStep = (step: Steps) => { | |||
@@ -83,8 +84,7 @@ export default function AzurePipelinesTutorial(props: AzurePipelinesTutorialProp | |||
setIsCurrentStepValid(false); | |||
}; | |||
const canContinue = (step: Step, i: number) => | |||
i < steps.length - 1 && (!step.checkValidity || isCurrentStepValid); | |||
const canContinue = (step: Step) => !step.checkValidity || isCurrentStepValid; | |||
return ( | |||
<> | |||
@@ -107,17 +107,26 @@ export default function AzurePipelinesTutorial(props: AzurePipelinesTutorialProp | |||
renderForm={() => ( | |||
<div className="boxed-group-inner"> | |||
<div>{step.content}</div> | |||
{canContinue(step, i) && ( | |||
<Button | |||
className="big-spacer-top spacer-bottom" | |||
onClick={() => switchCurrentStep(step.step + 1)}> | |||
{translate('continue')} | |||
</Button> | |||
)} | |||
{canContinue(step) && | |||
(step.step === Steps.BranchAnalysis ? ( | |||
<FinishButton onClick={() => switchCurrentStep(step.step + 1)} /> | |||
) : ( | |||
<Button | |||
className="big-spacer-top spacer-bottom" | |||
onClick={() => switchCurrentStep(step.step + 1)}> | |||
{translate('continue')} | |||
</Button> | |||
))} | |||
</div> | |||
)} | |||
/> | |||
))} | |||
<AllSetStep | |||
alm={alm || AlmKeys.Azure} | |||
stepNumber={4} | |||
open={currentStep === Steps.AllSet} | |||
willRefreshAutomatically={willRefreshAutomatically} | |||
/> | |||
</> | |||
); | |||
} |
@@ -1,86 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2021 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { AlmKeys } from '../../../types/alm-settings'; | |||
import { withAppState } from '../../hoc/withAppState'; | |||
export interface SaveAndRunStepContentProps { | |||
alm?: AlmKeys; | |||
appState: T.AppState; | |||
} | |||
export function SaveAndRunStepContent(props: SaveAndRunStepContentProps) { | |||
const { | |||
alm, | |||
appState: { branchesEnabled } | |||
} = props; | |||
return ( | |||
<> | |||
<div className="display-flex-row big-spacer-bottom"> | |||
<div> | |||
<img | |||
alt="" // Should be ignored by screen readers | |||
className="big-spacer-right" | |||
width={30} | |||
src={`${getBaseUrl()}/images/tutorials/commit.svg`} | |||
/> | |||
</div> | |||
<div> | |||
<p className="little-spacer-bottom"> | |||
<strong> | |||
{translate('onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit')} | |||
</strong> | |||
</p> | |||
<p> | |||
{translate('onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit.why')}{' '} | |||
{branchesEnabled && | |||
alm && | |||
translateWithParameters( | |||
'onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit.pr_deco', | |||
translate('alm', alm) | |||
)} | |||
</p> | |||
</div> | |||
</div> | |||
<div className="display-flex-row"> | |||
<div> | |||
<img | |||
alt="" // Should be ignored by screen readers | |||
className="big-spacer-right" | |||
width={30} | |||
src={`${getBaseUrl()}/images/tutorials/refresh.svg`} | |||
/> | |||
</div> | |||
<div> | |||
<p className="little-spacer-bottom"> | |||
<strong> | |||
{translate('onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh')} | |||
</strong> | |||
</p> | |||
<p>{translate('onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh.why')}</p> | |||
</div> | |||
</div> | |||
</> | |||
); | |||
} | |||
export default withAppState(SaveAndRunStepContent); |
@@ -28,18 +28,10 @@ import AzurePipelinesTutorial, { AzurePipelinesTutorialProps } from '../AzurePip | |||
it('should render correctly', () => { | |||
const wrapper = shallowRender(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect( | |||
wrapper | |||
.find(Step) | |||
.first() | |||
.dive() | |||
).toMatchSnapshot('first-step-wrapper'); | |||
expect( | |||
wrapper | |||
.find(Step) | |||
.last() | |||
.dive() | |||
).toMatchSnapshot('last-step-wrapper'); | |||
wrapper.find(Step).forEach(step => { | |||
expect(step.dive()).toMatchSnapshot(); | |||
}); | |||
}); | |||
it('should display the next step when one is finished', () => { | |||
@@ -97,6 +89,7 @@ function shallowRender(props: Partial<AzurePipelinesTutorialProps> = {}) { | |||
baseUrl="http://localhost:9000" | |||
component={mockComponent()} | |||
currentUser={mockLoggedInUser()} | |||
willRefreshAutomatically={true} | |||
{...props} | |||
/> | |||
); |
@@ -1,37 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2021 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { mockAppState } from '../../../../helpers/testMocks'; | |||
import { AlmKeys } from '../../../../types/alm-settings'; | |||
import { SaveAndRunStepContent, SaveAndRunStepContentProps } from '../SaveAndRunStepContent'; | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot('default'); | |||
expect( | |||
shallowRender({ alm: AlmKeys.Azure, appState: mockAppState({ branchesEnabled: true }) }) | |||
).toMatchSnapshot('with branches and alm info'); | |||
}); | |||
function shallowRender(props: Partial<SaveAndRunStepContentProps> = {}) { | |||
return shallow<SaveAndRunStepContentProps>( | |||
<SaveAndRunStepContent appState={mockAppState()} {...props} /> | |||
); | |||
} |
@@ -38,19 +38,16 @@ exports[`should render correctly 1`] = ` | |||
stepNumber={3} | |||
stepTitle="onboarding.tutorial.with.azure_pipelines.BranchAnalysis.title" | |||
/> | |||
<Step | |||
finished={false} | |||
key="3" | |||
onOpen={[Function]} | |||
<AllSetStep | |||
alm="azure" | |||
open={false} | |||
renderForm={[Function]} | |||
stepNumber={4} | |||
stepTitle="onboarding.tutorial.with.azure_pipelines.SaveAndRun.title" | |||
willRefreshAutomatically={true} | |||
/> | |||
</Fragment> | |||
`; | |||
exports[`should render correctly: first-step-wrapper 1`] = ` | |||
exports[`should render correctly 2`] = ` | |||
<div | |||
className="boxed-group onboarding-step is-open" | |||
> | |||
@@ -86,20 +83,92 @@ exports[`should render correctly: first-step-wrapper 1`] = ` | |||
</div> | |||
`; | |||
exports[`should render correctly: last-step-wrapper 1`] = ` | |||
exports[`should render correctly 3`] = ` | |||
<div | |||
className="boxed-group onboarding-step" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
2 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.tutorial.with.azure_pipelines.ServiceEndpoint.title | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
/> | |||
<div | |||
className="hidden" | |||
> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div> | |||
<ServiceEndpointStepContent | |||
baseUrl="http://localhost:9000" | |||
component={ | |||
Object { | |||
"breadcrumbs": Array [], | |||
"key": "my-project", | |||
"name": "MyProject", | |||
"qualifier": "TRK", | |||
"qualityGate": Object { | |||
"isDefault": true, | |||
"key": "30", | |||
"name": "Sonar way", | |||
}, | |||
"qualityProfiles": Array [ | |||
Object { | |||
"deleted": false, | |||
"key": "my-qp", | |||
"language": "ts", | |||
"name": "Sonar way", | |||
}, | |||
], | |||
"tags": Array [], | |||
} | |||
} | |||
currentUser={ | |||
Object { | |||
"groups": Array [], | |||
"isLoggedIn": true, | |||
"login": "luke", | |||
"name": "Skywalker", | |||
"scmAccounts": Array [], | |||
} | |||
} | |||
/> | |||
</div> | |||
<Button | |||
className="big-spacer-top spacer-bottom" | |||
onClick={[Function]} | |||
> | |||
continue | |||
</Button> | |||
</div> | |||
</div> | |||
</div> | |||
`; | |||
exports[`should render correctly 4`] = ` | |||
<div | |||
className="boxed-group onboarding-step" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
4 | |||
3 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.title | |||
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.title | |||
</h2> | |||
</div> | |||
<div | |||
@@ -112,7 +181,31 @@ exports[`should render correctly: last-step-wrapper 1`] = ` | |||
className="boxed-group-inner" | |||
> | |||
<div> | |||
<Connect(withAppState(SaveAndRunStepContent)) /> | |||
<Connect(BranchAnalysisStepContent) | |||
component={ | |||
Object { | |||
"breadcrumbs": Array [], | |||
"key": "my-project", | |||
"name": "MyProject", | |||
"qualifier": "TRK", | |||
"qualityGate": Object { | |||
"isDefault": true, | |||
"key": "30", | |||
"name": "Sonar way", | |||
}, | |||
"qualityProfiles": Array [ | |||
Object { | |||
"deleted": false, | |||
"key": "my-qp", | |||
"language": "ts", | |||
"name": "Sonar way", | |||
}, | |||
], | |||
"tags": Array [], | |||
} | |||
} | |||
onStepValidationChange={[Function]} | |||
/> | |||
</div> | |||
</div> | |||
</div> |
@@ -1,110 +0,0 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should render correctly: default 1`] = ` | |||
<Fragment> | |||
<div | |||
className="display-flex-row big-spacer-bottom" | |||
> | |||
<div> | |||
<img | |||
alt="" | |||
className="big-spacer-right" | |||
src="/images/tutorials/commit.svg" | |||
width={30} | |||
/> | |||
</div> | |||
<div> | |||
<p | |||
className="little-spacer-bottom" | |||
> | |||
<strong> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit | |||
</strong> | |||
</p> | |||
<p> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit.why | |||
</p> | |||
</div> | |||
</div> | |||
<div | |||
className="display-flex-row" | |||
> | |||
<div> | |||
<img | |||
alt="" | |||
className="big-spacer-right" | |||
src="/images/tutorials/refresh.svg" | |||
width={30} | |||
/> | |||
</div> | |||
<div> | |||
<p | |||
className="little-spacer-bottom" | |||
> | |||
<strong> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh | |||
</strong> | |||
</p> | |||
<p> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh.why | |||
</p> | |||
</div> | |||
</div> | |||
</Fragment> | |||
`; | |||
exports[`should render correctly: with branches and alm info 1`] = ` | |||
<Fragment> | |||
<div | |||
className="display-flex-row big-spacer-bottom" | |||
> | |||
<div> | |||
<img | |||
alt="" | |||
className="big-spacer-right" | |||
src="/images/tutorials/commit.svg" | |||
width={30} | |||
/> | |||
</div> | |||
<div> | |||
<p | |||
className="little-spacer-bottom" | |||
> | |||
<strong> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit | |||
</strong> | |||
</p> | |||
<p> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit.why | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit.pr_deco.alm.azure | |||
</p> | |||
</div> | |||
</div> | |||
<div | |||
className="display-flex-row" | |||
> | |||
<div> | |||
<img | |||
alt="" | |||
className="big-spacer-right" | |||
src="/images/tutorials/refresh.svg" | |||
width={30} | |||
/> | |||
</div> | |||
<div> | |||
<p | |||
className="little-spacer-bottom" | |||
> | |||
<strong> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh | |||
</strong> | |||
</p> | |||
<p> | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh.why | |||
</p> | |||
</div> | |||
</div> | |||
</Fragment> | |||
`; |
@@ -3900,15 +3900,6 @@ onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.no | |||
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.continous_integration.no_branches.sentence.continuous_integration=Enable continuous integration | |||
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection=To make sure your Pull Requests are analyzed automatically and aren't merged when they're failing their quality gate, check out the {link}. | |||
onboarding.tutorial.with.azure_pipelines.BranchAnalysis.branch_protection.link=documentation | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.title=Save and run your pipeline | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit=Save your pipeline and push your code to start the analysis | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit.why=Each new push you make on your branches will trigger a new analysis in SonarQube. | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.commit.pr_deco=We will decorate Pull Requests directly on {0} for you. | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh=This page will then refresh with your analysis results | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.refresh.why=If this page doesn't refresh after a while, please double-check your pipeline configuration. | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.then={what} Checkout our {link} to make sure SonarQube analyze and decorate all of your Pull Requests | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.then.what=Then what? | |||
onboarding.tutorial.with.azure_pipelines.SaveAndRun.then.link=Azure integration documentation | |||
#------------------------------------------------------------------------------ | |||
# | |||
# BRANCHES |