From 8f2fde029e993cedf209a9fd7bd50f39dba34a79 Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Wed, 12 Jul 2023 15:55:28 +0200 Subject: [PATCH] SONAR-19904 New UI for Other/local analysis tutorials --- .../src/components/CodeSnippet.tsx | 5 +- .../src/components/TutorialStep.tsx | 13 +- .../components/__tests__/CodeSnippet-test.tsx | 2 +- .../__snapshots__/CodeSnippet-test.tsx.snap | 8 +- .../__tests__/TutorialSelection-it.tsx | 2 +- .../__tests__/AzurePipelinesTutorial-it.tsx | 34 ++-- .../tutorials/components/CompilationInfo.tsx | 66 ++++--- .../components/GradleBuildSelection.tsx | 6 +- .../tutorials/components/InlineSnippet.tsx | 28 +++ .../components/ProjectTokenScopeInfo.tsx | 18 +- .../tutorials/components/RenderOptions.tsx | 10 +- .../components/tutorials/components/Step.css | 104 ---------- .../components/tutorials/components/Step.tsx | 49 +++-- .../tutorials/other/BuildToolForm.tsx | 10 +- .../tutorials/other/DoneNextSteps.tsx | 64 ++++--- .../tutorials/other/OtherTutorial.tsx | 14 +- .../tutorials/other/ProjectAnalysisStep.tsx | 36 ++-- .../components/tutorials/other/TokenStep.tsx | 179 ++++++++++-------- .../other/__tests__/OtherTutorial-it.tsx | 46 +++-- .../tutorials/other/commands/DotNetCore.tsx | 21 +- .../other/commands/DotNetExecute.tsx | 29 ++- .../other/commands/DotNetFramework.tsx | 18 +- .../other/commands/DownloadBuildWrapper.tsx | 26 ++- .../other/commands/DownloadScanner.tsx | 71 ++++--- .../other/commands/ExecBuildWrapper.tsx | 22 ++- .../tutorials/other/commands/ExecScanner.tsx | 20 +- .../tutorials/other/commands/JavaGradle.tsx | 61 +++--- .../tutorials/other/commands/JavaMaven.tsx | 20 +- .../js/components/tutorials/test-utils.ts | 32 ++-- server/sonar-web/src/main/js/helpers/docs.ts | 10 +- .../resources/org/sonar/l10n/core.properties | 4 +- 31 files changed, 541 insertions(+), 487 deletions(-) create mode 100644 server/sonar-web/src/main/js/components/tutorials/components/InlineSnippet.tsx delete mode 100644 server/sonar-web/src/main/js/components/tutorials/components/Step.css diff --git a/server/sonar-web/design-system/src/components/CodeSnippet.tsx b/server/sonar-web/design-system/src/components/CodeSnippet.tsx index 25a184d0803..4e8b57066d9 100644 --- a/server/sonar-web/design-system/src/components/CodeSnippet.tsx +++ b/server/sonar-web/design-system/src/components/CodeSnippet.tsx @@ -57,8 +57,11 @@ export function CodeSnippet(props: Props) { return ( - {props.title} - {props.children} + + {title} + {children} ); } @@ -61,9 +62,9 @@ const Title = styled.h2` color: ${themeColor('pageTitle')}; `; -const Step = styled.li` +const Step = styled.li<{ stepNumber?: number }>` list-style: none; - counter-increment: li; + counter-increment: li ${(props) => props.stepNumber}; ${tw`sw-mt-10`} diff --git a/server/sonar-web/design-system/src/components/__tests__/CodeSnippet-test.tsx b/server/sonar-web/design-system/src/components/__tests__/CodeSnippet-test.tsx index 87bca8a7bdc..8b0aad26b4c 100644 --- a/server/sonar-web/design-system/src/components/__tests__/CodeSnippet-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/CodeSnippet-test.tsx @@ -33,7 +33,7 @@ it('should show full size when multiline with no editting', () => { it('should show reduced size when single line with no editting', () => { const { container } = setupWithProps({ isOneLine: true, snippet: 'foobar' }); const copyButton = screen.getByRole('button', { name: 'Copy' }); - expect(copyButton).toHaveStyle('top: 1.5rem'); + expect(copyButton).toHaveStyle('top: 1rem'); expect(container).toMatchSnapshot(); }); diff --git a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/CodeSnippet-test.tsx.snap b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/CodeSnippet-test.tsx.snap index d857ec0c8cb..797de70738c 100644 --- a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/CodeSnippet-test.tsx.snap +++ b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/CodeSnippet-test.tsx.snap @@ -168,7 +168,7 @@ exports[`should show full size when multiline with no editting 1`] = `
+
)}
@@ -371,10 +395,12 @@ export default class TokenStep extends React.PureComponent { } return ( -
- - {selection === 'generate' && tokenName && `${tokenName}: `} - {token} +
+ + + {selection === TokenUse.GENERATE && tokenName && `${tokenName}: `} + {token} +
); }; @@ -393,3 +419,8 @@ export default class TokenStep extends React.PureComponent { ); } } + +// We need to pass 'htmlFor' to the label, but +// using 'as' doesn't dynamically change the allowed props +// https://github.com/emotion-js/emotion/issues/2266 +const HighlightLabel = Highlight.withComponent('label'); diff --git a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx index e0cc60ca784..9a95eb678aa 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/__tests__/OtherTutorial-it.tsx @@ -102,54 +102,62 @@ it('can choose build tools and copy provided settings', async () => { // Maven await user.click(ui.mavenBuildButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('maven: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('maven: execute scanner'); // Gradle await user.click(ui.gradleBuildButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('gradle: sonarqube plugin'); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('gradle: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('gradle: sonarqube plugin'); + expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('gradle: execute scanner'); // Dotnet - Core await user.click(ui.dotnetBuildButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('dotnet core: install scanner globally'); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('dotnet core: execute command 1'); - expect(getCopyToClipboardValue(2)).toMatchSnapshot('dotnet core: execute command 2'); - expect(getCopyToClipboardValue(3)).toMatchSnapshot('dotnet core: execute command 3'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot( + 'dotnet core: install scanner globally' + ); + expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('dotnet core: execute command 1'); + expect(getCopyToClipboardValue(2, 'Copy')).toMatchSnapshot('dotnet core: execute command 2'); + expect(getCopyToClipboardValue(3, 'Copy')).toMatchSnapshot('dotnet core: execute command 3'); // Dotnet - Framework await user.click(ui.dotnetFrameworkButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('dotnet framework: execute command 1'); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('dotnet framework: execute command 2'); - expect(getCopyToClipboardValue(2)).toMatchSnapshot('dotnet framework: execute command 3'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('dotnet framework: execute command 1'); + expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('dotnet framework: execute command 2'); + expect(getCopyToClipboardValue(2, 'Copy')).toMatchSnapshot('dotnet framework: execute command 3'); // C Family - Linux await user.click(ui.cFamilyBuildButton.get()); await user.click(ui.linuxButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('cfamily linux: execute build wrapper'); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('cfamily linux: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot( + 'cfamily linux: execute build wrapper' + ); + expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('cfamily linux: execute scanner'); // C Family - Windows await user.click(ui.windowsButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('cfamily windows: execute build wrapper'); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('cfamily windows: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot( + 'cfamily windows: execute build wrapper' + ); + expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('cfamily windows: execute scanner'); // C Family - MacOS await user.click(ui.macosButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('cfamily macos: execute build wrapper'); - expect(getCopyToClipboardValue(1)).toMatchSnapshot('cfamily macos: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot( + 'cfamily macos: execute build wrapper' + ); + expect(getCopyToClipboardValue(1, 'Copy')).toMatchSnapshot('cfamily macos: execute scanner'); // Other - Linux await user.click(ui.otherBuildButton.get()); await user.click(ui.linuxButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('other linux: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('other linux: execute scanner'); // Other - Windows await user.click(ui.windowsButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('other windows: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('other windows: execute scanner'); // Other - MacOS await user.click(ui.macosButton.get()); - expect(getCopyToClipboardValue()).toMatchSnapshot('other macos: execute scanner'); + expect(getCopyToClipboardValue(0, 'Copy')).toMatchSnapshot('other macos: execute scanner'); }); function renderOtherTutorial({ diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetCore.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetCore.tsx index ef3fae9e943..16a472f38f5 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetCore.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetCore.tsx @@ -17,10 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CodeSnippet, FlagMessage, SubHeading } from 'design-system'; import * as React from 'react'; import { translate } from '../../../../helpers/l10n'; -import CodeSnippet from '../../../common/CodeSnippet'; -import { Alert } from '../../../ui/Alert'; import { DotNetProps } from './DotNet'; import DotNetExecute from './DotNetExecute'; @@ -35,16 +34,18 @@ export default function DotNetCore(props: DotNetProps) { return (
-

+ {translate('onboarding.analysis.dotnetcore.global')} -

-

- {translate('onboarding.analysis.dotnetcore.global.text')} -

- - + +

{translate('onboarding.analysis.dotnetcore.global.text')}

+ + {translate('onboarding.analysis.dotnetcore.global.text.path')} -
+
); diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetExecute.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetExecute.tsx index 05b55dc4a29..ab3b502e917 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetExecute.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetExecute.tsx @@ -17,12 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CodeSnippet, Link, SubHeading } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; +import { useDocUrl } from '../../../../helpers/docs'; import { translate } from '../../../../helpers/l10n'; import { Component } from '../../../../types/types'; -import CodeSnippet from '../../../common/CodeSnippet'; -import DocLink from '../../../common/DocLink'; import InstanceMessage from '../../../common/InstanceMessage'; import DoneNextSteps from '../DoneNextSteps'; @@ -32,27 +32,36 @@ export interface DotNetExecuteProps { } export default function DotNetExecute({ commands, component }: DotNetExecuteProps) { + const docUrl = useDocUrl(); + return ( <> -

+ {translate('onboarding.analysis.sq_scanner.execute')} -

+ - {(transformedMessage) =>

{transformedMessage}

} + {(transformedMessage) =>

{transformedMessage}

}
- {commands.map((command, index) => ( - + {commands.map((command) => ( + ))} -

+

+ {translate('onboarding.analysis.msbuild.docs_link')} - + ), }} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetFramework.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetFramework.tsx index 55362bb46e3..7213d4c48b8 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetFramework.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/DotNetFramework.tsx @@ -17,16 +17,20 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Link, SubHeading } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; +import { useDocUrl } from '../../../../helpers/docs'; import { translate } from '../../../../helpers/l10n'; -import DocLink from '../../../common/DocLink'; +import { InlineSnippet } from '../../components/InlineSnippet'; import { DotNetProps } from './DotNet'; import DotNetExecute from './DotNetExecute'; export default function DotNetFramework(props: DotNetProps) { const { baseUrl, component, token } = props; + const docUrl = useDocUrl(); + const commands = [ `SonarScanner.MSBuild.exe begin /k:"${component.key}" /d:sonar.host.url="${baseUrl}" /d:sonar.token="${token}"`, 'MsBuild.exe /t:Rebuild', @@ -36,19 +40,19 @@ export default function DotNetFramework(props: DotNetProps) { return (

-

+ {translate('onboarding.analysis.msbuild.header')} -

-

+ +

%PATH%, + code: , link: ( - + {translate('onboarding.analysis.msbuild.docs_link')} - + ), }} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadBuildWrapper.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadBuildWrapper.tsx index 99d60311843..5c3afc37204 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadBuildWrapper.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadBuildWrapper.tsx @@ -17,11 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CodeSnippet, DownloadButton, SubHeading } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { translate } from '../../../../helpers/l10n'; import { getBaseUrl } from '../../../../helpers/system'; -import CodeSnippet from '../../../common/CodeSnippet'; +import { InlineSnippet } from '../../components/InlineSnippet'; import { OSs } from '../../types'; export interface DownloadBuildWrapperProps { @@ -39,33 +40,38 @@ const FILENAMES: { [x in OSs]: string } = { export default function DownloadBuildWrapper(props: DownloadBuildWrapperProps) { const { os, isLocal, baseUrl } = props; return ( -

-

{translate('onboarding.analysis.build_wrapper.header', os)}

+
+ + {translate('onboarding.analysis.build_wrapper.header', os)} + {isLocal ? ( <> -

+

{os === 'win' ? '%PATH%' : 'PATH'}, + env_var: , }} />

-

- + {translate('download_verb')} - +

) : ( - + )}
); diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadScanner.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadScanner.tsx index 482ee6e9bce..93c8f98af14 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadScanner.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/DownloadScanner.tsx @@ -17,12 +17,19 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { + ClipboardIconButton, + CodeSnippet, + Link, + NumberedList, + NumberedListItem, + SubHeading, +} from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; +import { useDocUrl } from '../../../../helpers/docs'; import { translate } from '../../../../helpers/l10n'; -import CodeSnippet from '../../../common/CodeSnippet'; -import DocLink from '../../../common/DocLink'; -import { ClipboardButton } from '../../../controls/clipboard'; +import { InlineSnippet } from '../../components/InlineSnippet'; import { OSs } from '../../types'; export interface DownloadScannerProps { @@ -34,43 +41,57 @@ export interface DownloadScannerProps { export default function DownloadScanner(props: DownloadScannerProps) { const { os, isLocal, token } = props; + const docUrl = useDocUrl(); + return ( -
-

{translate('onboarding.analysis.sq_scanner.header', os)}

+
+ + {translate('onboarding.analysis.sq_scanner.header', os)} + {isLocal ? ( -

+

bin, - env_var: {os === OSs.Windows ? '%PATH%' : 'PATH'}, + dir: , + env_var: , link: ( - + {translate('onboarding.analysis.sq_scanner.docs_link')} - + ), }} />

) : ( <> - -

+ ${getRemoteDownloadSnippet(os)}`} + /> + {translate('onboarding.analysis.sq_scanner.sonar_token_env.header')} -

-
    -
  • - {translate('onboarding.analysis.sq_scanner.sonar_token_env.var_name')}:{' '} - SONAR_TOKEN - -
  • -
  • - {translate('onboarding.analysis.sq_scanner.sonar_token_env.var_value')}:{' '} - {token} - -
  • -
+ + + + + {translate('onboarding.analysis.sq_scanner.sonar_token_env.var_name')}: + + + + + + + {translate('onboarding.analysis.sq_scanner.sonar_token_env.var_value')}: + + + + + )}
diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecBuildWrapper.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecBuildWrapper.tsx index 70d33a301af..4be52b10896 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecBuildWrapper.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecBuildWrapper.tsx @@ -17,11 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CodeSnippet, Link, SubHeading } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; +import { useDocUrl } from '../../../../helpers/docs'; import { translate } from '../../../../helpers/l10n'; -import CodeSnippet from '../../../common/CodeSnippet'; -import DocLink from '../../../common/DocLink'; import { OSs } from '../../types'; export interface ExecBuildWrapperProps { @@ -37,28 +37,30 @@ const executables: { [x in OSs]: string } = { export default function ExecBuildWrapper(props: ExecBuildWrapperProps) { const { os } = props; + const docUrl = useDocUrl(); + return ( <> -

+ {translate('onboarding.analysis.build_wrapper.execute')} -

-

- {translate('onboarding.analysis.build_wrapper.execute_text')} -

+ +

{translate('onboarding.analysis.build_wrapper.execute_text')}

-

+

+ {translate('onboarding.analysis.build_wrapper.docs_link')} - + ), }} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecScanner.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecScanner.tsx index b37c57abbb9..4303283a67c 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecScanner.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/ExecScanner.tsx @@ -17,12 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CodeSnippet, Link, SubHeading } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; +import { useDocUrl } from '../../../../helpers/docs'; import { translate } from '../../../../helpers/l10n'; import { Component } from '../../../../types/types'; -import CodeSnippet from '../../../common/CodeSnippet'; -import DocLink from '../../../common/DocLink'; import InstanceMessage from '../../../common/InstanceMessage'; import { OSs } from '../../types'; import { quote } from '../../utils'; @@ -40,6 +40,8 @@ export interface ExecScannerProps { export default function ExecScanner(props: ExecScannerProps) { const { baseUrl, os, isLocal, component, token, cfamily } = props; + const docUrl = useDocUrl(); + const q = quote(os); const command = [ os === OSs.Windows ? 'sonar-scanner.bat' : 'sonar-scanner', @@ -52,22 +54,22 @@ export default function ExecScanner(props: ExecScannerProps) { return (

-

+ {translate('onboarding.analysis.sq_scanner.execute')} -

+ - {(transformedMessage) =>

{transformedMessage}

} + {(transformedMessage) =>

{transformedMessage}

}
- -

+ +

+ {translate('onboarding.analysis.sq_scanner.docs_link')} - + ), }} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx index d4d21baa62b..bc21ba6098b 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaGradle.tsx @@ -17,15 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CodeSnippet, Link, Note, SubHeading } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { GRADLE_SCANNER_VERSION } from '../../../../helpers/constants'; +import { useDocUrl } from '../../../../helpers/docs'; import { translate } from '../../../../helpers/l10n'; import { Component } from '../../../../types/types'; -import CodeSnippet from '../../../common/CodeSnippet'; -import DocLink from '../../../common/DocLink'; import InstanceMessage from '../../../common/InstanceMessage'; import GradleBuildSelection from '../../components/GradleBuildSelection'; +import { InlineSnippet } from '../../components/InlineSnippet'; import { GradleBuildDSL } from '../../types'; import DoneNextSteps from '../DoneNextSteps'; @@ -36,17 +37,25 @@ export interface JavaGradleProps { } const config = { - [GradleBuildDSL.Groovy]: `plugins { + [GradleBuildDSL.Groovy]: { + lang: 'groovy', + snippet: `plugins { id "org.sonarqube" version "${GRADLE_SCANNER_VERSION}" }`, - [GradleBuildDSL.Kotlin]: `plugins { + }, + [GradleBuildDSL.Kotlin]: { + lang: 'kts', + snippet: `plugins { id("org.sonarqube") version "${GRADLE_SCANNER_VERSION}" }`, + }, }; export default function JavaGradle(props: JavaGradleProps) { const { baseUrl, component, token } = props; + const docUrl = useDocUrl(); + const command = [ './gradlew sonar', `-Dsonar.projectKey=${component.key}`, @@ -57,53 +66,59 @@ export default function JavaGradle(props: JavaGradleProps) { return (

-

{translate('onboarding.analysis.java.gradle.header')}

+ + {translate('onboarding.analysis.java.gradle.header')} + {(transformedMessage) => ( -

+

org.sonarqube, - groovy: {GradleBuildDSL.Groovy}, - kotlin: {GradleBuildDSL.Kotlin}, + plugin_code: , + groovy: , + kotlin: , }} />

)}
- - {(build) => } + + {(build) => ( + + )} -

- +

+ + {translate('here')} - + ), }} /> - -

-

- {translate('onboarding.analysis.java.gradle.text.2')} +

- -

+

{translate('onboarding.analysis.java.gradle.text.2')}

+ +

+ {translate('onboarding.analysis.java.gradle.docs_link')} - + ), }} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaMaven.tsx b/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaMaven.tsx index aa4ce669b68..fc58bd1a242 100644 --- a/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaMaven.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/other/commands/JavaMaven.tsx @@ -17,12 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { CodeSnippet, Link, SubHeading } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; +import { useDocUrl } from '../../../../helpers/docs'; import { translate } from '../../../../helpers/l10n'; import { Component } from '../../../../types/types'; -import CodeSnippet from '../../../common/CodeSnippet'; -import DocLink from '../../../common/DocLink'; import InstanceMessage from '../../../common/InstanceMessage'; import DoneNextSteps from '../DoneNextSteps'; @@ -42,22 +42,26 @@ export default function JavaMaven(props: JavaMavenProps) { `-Dsonar.token=${token}`, ]; + const docUrl = useDocUrl(); + return (

-

{translate('onboarding.analysis.java.maven.header')}

-

+ + {translate('onboarding.analysis.java.maven.header')} + +

- -

+ +

+ {translate('onboarding.analysis.java.maven.docs_link')} - + ), }} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/test-utils.ts b/server/sonar-web/src/main/js/components/tutorials/test-utils.ts index 0ccebaa586a..760ee7d2d95 100644 --- a/server/sonar-web/src/main/js/components/tutorials/test-utils.ts +++ b/server/sonar-web/src/main/js/components/tutorials/test-utils.ts @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { screen } from '@testing-library/react'; -import { byRole, byText } from '../../helpers/testSelector'; +import { byLabelText, byRole, byText } from '../../helpers/testSelector'; import { BuildTools, GradleBuildDSL, OSs, TutorialModes } from './types'; const CI_TRANSLATE_MAP: Partial> = { @@ -67,30 +67,30 @@ export function getTutorialActionButtons() { export function getTutorialBuildButtons() { return { - describeBuildTitle: byRole('heading', { name: 'onboarding.build' }), - mavenBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Maven}` }), - gradleBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Gradle}` }), - gradleDSLButton: (name: GradleBuildDSL) => byRole('button', { name }), - dotnetBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.DotNet}` }), - cFamilyBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.CFamily}` }), - otherBuildButton: byRole('button', { name: `onboarding.build.${BuildTools.Other}` }), - windowsDotnetCoreButton: byRole('button', { + describeBuildTitle: byLabelText('onboarding.build'), + mavenBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.Maven}` }), + gradleBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.Gradle}` }), + gradleDSLButton: (name: GradleBuildDSL) => byRole('radio', { name }), + dotnetBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.DotNet}` }), + cFamilyBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.CFamily}` }), + otherBuildButton: byRole('radio', { name: `onboarding.build.${BuildTools.Other}` }), + windowsDotnetCoreButton: byRole('radio', { name: `onboarding.build.${BuildTools.DotNet}.win_core`, }), - windowsDotnetFrameworkButton: byRole('button', { + windowsDotnetFrameworkButton: byRole('radio', { name: `onboarding.build.${BuildTools.DotNet}.win_msbuild`, }), - linuxDotnetCoreButton: byRole('button', { + linuxDotnetCoreButton: byRole('radio', { name: `onboarding.build.${BuildTools.DotNet}.linux_core`, }), - dotnetCoreButton: byRole('button', { + dotnetCoreButton: byRole('radio', { name: `onboarding.build.${BuildTools.DotNet}.variant.dotnet_core`, }), - dotnetFrameworkButton: byRole('button', { + dotnetFrameworkButton: byRole('radio', { name: `onboarding.build.${BuildTools.DotNet}.variant.dotnet_framework`, }), - linuxButton: byRole('button', { name: `onboarding.build.other.os.${OSs.Linux}` }), - windowsButton: byRole('button', { name: `onboarding.build.other.os.${OSs.Windows}` }), - macosButton: byRole('button', { name: `onboarding.build.other.os.${OSs.MacOS}` }), + linuxButton: byRole('radio', { name: `onboarding.build.other.os.${OSs.Linux}` }), + windowsButton: byRole('radio', { name: `onboarding.build.other.os.${OSs.Windows}` }), + macosButton: byRole('radio', { name: `onboarding.build.other.os.${OSs.MacOS}` }), }; } diff --git a/server/sonar-web/src/main/js/helpers/docs.ts b/server/sonar-web/src/main/js/helpers/docs.ts index 1e106d55f24..50bf54b6dc4 100644 --- a/server/sonar-web/src/main/js/helpers/docs.ts +++ b/server/sonar-web/src/main/js/helpers/docs.ts @@ -29,8 +29,14 @@ export function getUrlForDoc(url: string, version: string, to: string) { : `${url}/${path}`; } -export function useDocUrl(to: string) { +export function useDocUrl(to: string): string; +export function useDocUrl(): (to: string) => string; +export function useDocUrl(to?: string) { const { version, documentationUrl } = React.useContext(AppStateContext); - return getUrlForDoc(documentationUrl, version, to); + if (to) { + return getUrlForDoc(documentationUrl, version, to); + } + + return (to: string) => getUrlForDoc(documentationUrl, version, to); } diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index c9245f0e66c..702f5af4095 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3817,7 +3817,7 @@ onboarding.alm.bitbucketcloud=Bitbucket Cloud onboarding.alm.gitlab=GitLab onboarding.project_analysis.header=Analyze your project -onboarding.project_analysis.description=We initialized your project on {instance}, now it's up to you to launch analyses! +onboarding.project_analysis.description=We initialized your project on SonarQube, now it's up to you to launch analyses! onboarding.project_analysis.guide_to_integrate_pipelines=follow the guide to integrating with Pipelines onboarding.create_project.setup_manually=Create a project @@ -3983,7 +3983,7 @@ onboarding.analysis.auto_refresh_after_analysis.done=Is my analysis done? onboarding.analysis.auto_refresh_after_analysis.auto_refresh=If your analysis is successful, this page will automatically refresh in a few moments. onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.admin=You can set up Pull Request Decoration under the project settings. To set up analysis with your favorite CI tool, see the tutorials. onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci=You can request from a project administrator to set up Pull Request Decoration. To set up analysis with your favorite CI tool, see the tutorials. -onboarding.analysis.auto_refresh_after_analysis.check_these_links=Check these useful links while you wait: {link_branches}, {link_pr_analysis}. +onboarding.analysis.auto_refresh_after_analysis.check_these_links=Check these useful links while you wait: onboarding.analysis.auto_refresh_after_analysis.check_these_links.pr_analysis=Pull Request Analysis onboarding.analysis.auto_refresh_after_analysis.check_these_links.branches=Branch Analysis -- 2.39.5