diff options
17 files changed, 144 insertions, 146 deletions
diff --git a/server/sonar-web/src/main/js/api/project-badges.ts b/server/sonar-web/src/main/js/api/project-badges.ts new file mode 100644 index 00000000000..692b8d793c0 --- /dev/null +++ b/server/sonar-web/src/main/js/api/project-badges.ts @@ -0,0 +1,27 @@ +/* + * 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 throwGlobalError from '../app/utils/throwGlobalError'; +import { getJSON } from '../helpers/request'; + +export function getProjectBadgesToken(project: string) { + return getJSON('/api/project_badges/token', { project }) + .then(({ token }) => token) + .catch(throwGlobalError); +} diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformation.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformation.tsx index 578bd2225cd..0b2072f2d11 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformation.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformation.tsx @@ -90,7 +90,6 @@ export class ProjectInformation extends React.PureComponent<Props, State> { isLoggedIn(currentUser) && component.qualifier === ComponentQualifier.Project; const canUseBadges = metrics !== undefined && - component.visibility !== 'private' && (component.qualifier === ComponentQualifier.Application || component.qualifier === ComponentQualifier.Project); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformation-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformation-test.tsx index 856efeeb83c..059fbcba520 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformation-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformation-test.tsx @@ -22,6 +22,8 @@ import * as React from 'react'; import { mockComponent } from '../../../../../../helpers/mocks/component'; import { mockCurrentUser, mockLoggedInUser, mockMetric } from '../../../../../../helpers/testMocks'; import { waitAndUpdate } from '../../../../../../helpers/testUtils'; +import { ComponentQualifier } from '../../../../../../types/component'; +import ProjectBadges from '../badges/ProjectBadges'; import { ProjectInformation } from '../ProjectInformation'; import { ProjectInformationPages } from '../ProjectInformationPages'; @@ -53,6 +55,17 @@ it('should handle page change', async () => { expect(wrapper.state().page).toBe(ProjectInformationPages.badges); }); +it('should display badge', () => { + const wrapper = shallowRender({ + component: mockComponent({ qualifier: ComponentQualifier.Project }) + }); + + expect(wrapper.find(ProjectBadges).type).toBeDefined(); + + wrapper.setProps({ component: mockComponent({ qualifier: ComponentQualifier.Application }) }); + expect(wrapper.find(ProjectBadges).type).toBeDefined(); +}); + function shallowRender(props: Partial<ProjectInformation['props']> = {}) { return shallow<ProjectInformation>( <ProjectInformation diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap index 19177eb6608..fe5bdc421ce 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap @@ -203,7 +203,7 @@ exports[`should render correctly: private 1`] = ` <Fragment> <Memo(ProjectInformationRenderer) canConfigureNotifications={false} - canUseBadges={false} + canUseBadges={true} component={ Object { "breadcrumbs": Array [], @@ -230,5 +230,24 @@ exports[`should render correctly: private 1`] = ` onComponentChange={[MockFunction]} onPageChange={[Function]} /> + <InfoDrawerPage + displayed={false} + onPageChange={[Function]} + > + <ProjectBadges + metrics={ + Object { + "coverage": Object { + "id": "coverage", + "key": "coverage", + "name": "Coverage", + "type": "PERCENT", + }, + } + } + project="my-project" + qualifier="TRK" + /> + </InfoDrawerPage> </Fragment> `; diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/BadgeParams.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/BadgeParams.tsx index 4aa6edc257e..92a8e74dbb2 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/BadgeParams.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/BadgeParams.tsx @@ -22,7 +22,7 @@ import * as React from 'react'; import { fetchWebApi } from '../../../../../../api/web-api'; import Select from '../../../../../../components/controls/Select'; import { getLocalizedMetricName, translate } from '../../../../../../helpers/l10n'; -import { BadgeColors, BadgeFormats, BadgeOptions, BadgeType } from './utils'; +import { BadgeFormats, BadgeOptions, BadgeType } from './utils'; interface Props { className?: string; @@ -90,10 +90,6 @@ export default class BadgeParams extends React.PureComponent<Props> { }); }; - handleColorChange = ({ value }: { value: BadgeColors }) => { - this.props.updateOptions({ color: value }); - }; - handleFormatChange = ({ value }: { value: BadgeFormats }) => { this.props.updateOptions({ format: value }); }; @@ -103,24 +99,7 @@ export default class BadgeParams extends React.PureComponent<Props> { }; renderBadgeType = (type: BadgeType, options: BadgeOptions) => { - if (type === BadgeType.marketing) { - return ( - <> - <label className="spacer-right" htmlFor="badge-color"> - {translate('color')}: - </label> - <Select - className="input-medium" - clearable={false} - name="badge-color" - onChange={this.handleColorChange} - options={this.getColorOptions()} - searchable={false} - value={options.color} - /> - </> - ); - } else if (type === BadgeType.measure) { + if (type === BadgeType.measure) { return ( <> <label className="spacer-right" htmlFor="badge-metric"> diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/ProjectBadges.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/ProjectBadges.tsx index f57119b9512..73bdf3fb9a1 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/ProjectBadges.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/ProjectBadges.tsx @@ -18,7 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { getProjectBadgesToken } from '../../../../../../api/project-badges'; import CodeSnippet from '../../../../../../components/common/CodeSnippet'; +import { Alert } from '../../../../../../components/ui/Alert'; import { getBranchLikeQuery } from '../../../../../../helpers/branch-like'; import { translate } from '../../../../../../helpers/l10n'; import { BranchLike } from '../../../../../../types/branch-like'; @@ -36,16 +38,36 @@ interface Props { } interface State { + token: string; selectedType: BadgeType; badgeOptions: BadgeOptions; } export default class ProjectBadges extends React.PureComponent<Props, State> { + mounted = false; state: State = { + token: '', selectedType: BadgeType.measure, - badgeOptions: { color: 'white', metric: MetricKey.alert_status } + badgeOptions: { metric: MetricKey.alert_status } }; + componentDidMount() { + this.mounted = true; + this.fetchToken(); + } + + componentWillUnmount() { + this.mounted = false; + } + + async fetchToken() { + const { project } = this.props; + const token = await getProjectBadgesToken(project); + if (this.mounted) { + this.setState({ token }); + } + } + handleSelectBadge = (selectedType: BadgeType) => { this.setState({ selectedType }); }; @@ -56,7 +78,7 @@ export default class ProjectBadges extends React.PureComponent<Props, State> { render() { const { branchLike, project, qualifier } = this.props; - const { selectedType, badgeOptions } = this.state; + const { selectedType, badgeOptions, token } = this.state; const fullBadgeOptions = { project, ...badgeOptions, ...getBranchLikeQuery(branchLike) }; return ( @@ -67,7 +89,7 @@ export default class ProjectBadges extends React.PureComponent<Props, State> { onClick={this.handleSelectBadge} selected={BadgeType.measure === selectedType} type={BadgeType.measure} - url={getBadgeUrl(BadgeType.measure, fullBadgeOptions)} + url={getBadgeUrl(BadgeType.measure, fullBadgeOptions, token)} /> <p className="huge-spacer-bottom spacer-top"> {translate('overview.badges', BadgeType.measure, 'description', qualifier)} @@ -76,7 +98,7 @@ export default class ProjectBadges extends React.PureComponent<Props, State> { onClick={this.handleSelectBadge} selected={BadgeType.qualityGate === selectedType} type={BadgeType.qualityGate} - url={getBadgeUrl(BadgeType.qualityGate, fullBadgeOptions)} + url={getBadgeUrl(BadgeType.qualityGate, fullBadgeOptions, token)} /> <p className="huge-spacer-bottom spacer-top"> {translate('overview.badges', BadgeType.qualityGate, 'description', qualifier)} @@ -88,7 +110,11 @@ export default class ProjectBadges extends React.PureComponent<Props, State> { type={selectedType} updateOptions={this.handleUpdateOptions} /> - <CodeSnippet isOneLine={true} snippet={getBadgeSnippet(selectedType, fullBadgeOptions)} /> + <Alert variant="warning">{translate('overview.badges.leak_warning')}</Alert> + <CodeSnippet + isOneLine={true} + snippet={getBadgeSnippet(selectedType, fullBadgeOptions, token)} + /> </div> ); } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeButton-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeButton-test.tsx index 221e8c9dbd2..124d1cc72eb 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeButton-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeButton-test.tsx @@ -33,7 +33,7 @@ it('should return the badge type on click', () => { const onClick = jest.fn(); const wrapper = getWrapper({ onClick }); click(wrapper.find('Button')); - expect(onClick).toHaveBeenCalledWith(BadgeType.marketing); + expect(onClick).toHaveBeenCalledWith(BadgeType.qualityGate); }); function getWrapper(props = {}) { @@ -41,7 +41,7 @@ function getWrapper(props = {}) { <BadgeButton onClick={jest.fn()} selected={false} - type={BadgeType.marketing} + type={BadgeType.qualityGate} url="http://foo.bar" {...props} /> diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeParams-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeParams-test.tsx index cf133f22256..696ec84f04f 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeParams-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/BadgeParams-test.tsx @@ -42,14 +42,6 @@ const METRICS = { coverage: { key: 'coverage', name: 'Coverage' } as T.Metric }; -it('should display marketing badge params', () => { - const updateOptions = jest.fn(); - const wrapper = getWrapper({ updateOptions }); - expect(wrapper).toMatchSnapshot(); - (wrapper.instance() as BadgeParams).handleColorChange({ value: 'black' }); - expect(updateOptions).toHaveBeenCalledWith({ color: 'black' }); -}); - it('should display measure badge params', () => { const updateOptions = jest.fn(); const wrapper = getWrapper({ updateOptions, type: BadgeType.measure }); @@ -70,8 +62,8 @@ function getWrapper(props = {}) { return shallow( <BadgeParams metrics={METRICS} - options={{ color: 'white', metric: 'alert_status' }} - type={BadgeType.marketing} + options={{ metric: 'alert_status' }} + type={BadgeType.measure} updateOptions={jest.fn()} {...props} /> diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/ProjectBadges-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/ProjectBadges-test.tsx index 4f1c3680392..8b0868d437c 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/ProjectBadges-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/ProjectBadges-test.tsx @@ -21,6 +21,7 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockBranch } from '../../../../../../../helpers/mocks/branch-like'; import { mockMetric } from '../../../../../../../helpers/testMocks'; +import { waitAndUpdate } from '../../../../../../../helpers/testUtils'; import { Location } from '../../../../../../../helpers/urls'; import { MetricKey } from '../../../../../../../types/metrics'; import ProjectBadges from '../ProjectBadges'; @@ -31,8 +32,14 @@ jest.mock('../../../../../../../helpers/urls', () => ({ getProjectUrl: () => ({ pathname: '/dashboard' } as Location) })); -it('should display correctly', () => { - expect(shallowRender()).toMatchSnapshot(); +jest.mock('../../../../../../../api/project-badges', () => ({ + getProjectBadgesToken: jest.fn().mockResolvedValue('foo') +})); + +it('should display correctly', async () => { + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + expect(wrapper).toMatchSnapshot(); }); function shallowRender(overrides = {}) { diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeButton-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeButton-test.tsx.snap index c1ea1a7eb50..b30b2a01152 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeButton-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeButton-test.tsx.snap @@ -6,7 +6,7 @@ exports[`should display correctly 1`] = ` onClick={[Function]} > <img - alt="overview.badges.marketing.alt" + alt="overview.badges.quality_gate.alt" src="http://foo.bar" width="128px" /> @@ -19,7 +19,7 @@ exports[`should display correctly 2`] = ` onClick={[Function]} > <img - alt="overview.badges.marketing.alt" + alt="overview.badges.quality_gate.alt" src="http://foo.bar" width="128px" /> diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeParams-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeParams-test.tsx.snap index b6b76f5f6a3..704be60fbcc 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeParams-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/BadgeParams-test.tsx.snap @@ -1,68 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should display marketing badge params 1`] = ` -<div> - <label - className="spacer-right" - htmlFor="badge-color" - > - color - : - </label> - <Select - className="input-medium" - clearable={false} - name="badge-color" - onChange={[Function]} - options={ - Array [ - Object { - "label": "overview.badges.options.colors.white", - "value": "white", - }, - Object { - "label": "overview.badges.options.colors.black", - "value": "black", - }, - Object { - "label": "overview.badges.options.colors.orange", - "value": "orange", - }, - ] - } - searchable={false} - value="white" - /> - <label - className="spacer-right spacer-top" - htmlFor="badge-format" - > - format - : - </label> - <Select - className="input-medium" - clearable={false} - name="badge-format" - onChange={[Function]} - options={ - Array [ - Object { - "label": "overview.badges.options.formats.md", - "value": "md", - }, - Object { - "label": "overview.badges.options.formats.url", - "value": "url", - }, - ] - } - searchable={false} - value="md" - /> -</div> -`; - exports[`should display measure badge params 1`] = ` <div> <label diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/ProjectBadges-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/ProjectBadges-test.tsx.snap index c48fa415a2e..4c7f8b850db 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/ProjectBadges-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/__snapshots__/ProjectBadges-test.tsx.snap @@ -16,7 +16,7 @@ exports[`should display correctly 1`] = ` onClick={[Function]} selected={true} type="measure" - url="host/api/project_badges/measure?branch=branch-6.7&project=foo&metric=alert_status" + url="host/api/project_badges/measure?branch=branch-6.7&project=foo&metric=alert_status&token=foo" /> <p className="huge-spacer-bottom spacer-top" @@ -27,7 +27,7 @@ exports[`should display correctly 1`] = ` onClick={[Function]} selected={false} type="quality_gate" - url="host/api/project_badges/quality_gate?branch=branch-6.7&project=foo" + url="host/api/project_badges/quality_gate?branch=branch-6.7&project=foo&token=foo" /> <p className="huge-spacer-bottom spacer-top" @@ -54,16 +54,20 @@ exports[`should display correctly 1`] = ` } options={ Object { - "color": "white", "metric": "alert_status", } } type="measure" updateOptions={[Function]} /> + <Alert + variant="warning" + > + overview.badges.leak_warning + </Alert> <CodeSnippet isOneLine={true} - snippet="[](/dashboard)" + snippet="[](/dashboard)" /> </div> `; diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/utils-test.ts b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/utils-test.ts index 263fb541de5..6b250af7b69 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/utils-test.ts +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/utils-test.ts @@ -29,44 +29,40 @@ jest.mock('../../../../../../../helpers/urls', () => ({ const options: BadgeOptions = { branch: 'master', - color: 'white', metric: 'alert_status', project: 'foo' }; describe('#getBadgeUrl', () => { - it('should generate correct marketing badge links', () => { - expect(getBadgeUrl(BadgeType.marketing, options)).toBe( - 'host/images/project_badges/sonarcloud-white.svg' - ); - expect(getBadgeUrl(BadgeType.marketing, { ...options, color: 'orange' })).toBe( - 'host/images/project_badges/sonarcloud-orange.svg' - ); - }); - it('should generate correct quality gate badge links', () => { - expect(getBadgeUrl(BadgeType.qualityGate, options)).toBe( - 'host/api/project_badges/quality_gate?branch=master&project=foo' + expect(getBadgeUrl(BadgeType.qualityGate, options, 'foo')).toBe( + 'host/api/project_badges/quality_gate?branch=master&project=foo&token=foo' ); }); it('should generate correct measures badge links', () => { - expect(getBadgeUrl(BadgeType.measure, options)).toBe( - 'host/api/project_badges/measure?branch=master&project=foo&metric=alert_status' + expect(getBadgeUrl(BadgeType.measure, options, 'foo')).toBe( + 'host/api/project_badges/measure?branch=master&project=foo&metric=alert_status&token=foo' ); }); it('should ignore undefined parameters', () => { - expect(getBadgeUrl(BadgeType.measure, { color: 'white', metric: 'alert_status' })).toBe( - 'host/api/project_badges/measure?metric=alert_status' + expect(getBadgeUrl(BadgeType.measure, { metric: 'alert_status' }, 'foo')).toBe( + 'host/api/project_badges/measure?metric=alert_status&token=foo' + ); + }); + + it('should force metric parameters', () => { + expect(getBadgeUrl(BadgeType.measure, {}, 'foo')).toBe( + 'host/api/project_badges/measure?metric=alert_status&token=foo' ); }); }); describe('#getBadgeSnippet', () => { it('should generate a correct markdown image', () => { - expect(getBadgeSnippet(BadgeType.marketing, { ...options, format: 'md' })).toBe( - '[](host/dashboard?id=foo&branch=master)' + expect(getBadgeSnippet(BadgeType.measure, { ...options, format: 'md' }, 'foo')).toBe( + '[](host/dashboard?id=foo&branch=master)' ); }); }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/utils.ts b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/utils.ts index f4d4a8a7233..71917389227 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/utils.ts +++ b/server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/utils.ts @@ -26,7 +26,6 @@ export type BadgeFormats = 'md' | 'url'; export interface BadgeOptions { branch?: string; - color?: BadgeColors; format?: BadgeFormats; project?: string; metric?: string; @@ -35,12 +34,11 @@ export interface BadgeOptions { export enum BadgeType { measure = 'measure', - qualityGate = 'quality_gate', - marketing = 'marketing' + qualityGate = 'quality_gate' } -export function getBadgeSnippet(type: BadgeType, options: BadgeOptions) { - const url = getBadgeUrl(type, options); +export function getBadgeSnippet(type: BadgeType, options: BadgeOptions, token: string) { + const url = getBadgeUrl(type, options, token); const { branch, format = 'md', metric = 'alert_status', project } = options; if (format === 'url') { @@ -50,9 +48,6 @@ export function getBadgeSnippet(type: BadgeType, options: BadgeOptions) { let projectUrl; switch (type) { - case BadgeType.marketing: - label = 'SonarCloud'; - break; case BadgeType.measure: label = getLocalizedMetricName({ key: metric }); break; @@ -73,19 +68,18 @@ export function getBadgeSnippet(type: BadgeType, options: BadgeOptions) { export function getBadgeUrl( type: BadgeType, - { branch, project, color = 'white', metric = 'alert_status', pullRequest }: BadgeOptions + { branch, project, metric = 'alert_status', pullRequest }: BadgeOptions, + token: string ) { switch (type) { - case BadgeType.marketing: - return `${getHostUrl()}/images/project_badges/sonarcloud-${color}.svg`; case BadgeType.qualityGate: return `${getHostUrl()}/api/project_badges/quality_gate?${new URLSearchParams( - omitNil({ branch, project, pullRequest }) + omitNil({ branch, project, pullRequest, token }) ).toString()}`; case BadgeType.measure: default: return `${getHostUrl()}/api/project_badges/measure?${new URLSearchParams( - omitNil({ branch, project, metric, pullRequest }) + omitNil({ branch, project, metric, pullRequest, token }) ).toString()}`; } } diff --git a/server/sonar-web/src/main/js/components/common/CodeSnippet.tsx b/server/sonar-web/src/main/js/components/common/CodeSnippet.tsx index 910cbbd877a..80ab7ff4baa 100644 --- a/server/sonar-web/src/main/js/components/common/CodeSnippet.tsx +++ b/server/sonar-web/src/main/js/components/common/CodeSnippet.tsx @@ -42,7 +42,8 @@ export default function CodeSnippet(props: CodeSnippetProps) { return ( <div className={classNames('code-snippet spacer-top spacer-bottom display-flex-row', {})}> - <pre className="flex-1" ref={snippetRef}> + {/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */} + <pre className="flex-1" ref={snippetRef} tabIndex={0}> {finalSnippet} </pre> {!noCopy && <ClipboardButton copyValue={finalSnippet} />} diff --git a/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/CodeSnippet-test.tsx.snap b/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/CodeSnippet-test.tsx.snap index f1901c905d0..f0a986e706d 100644 --- a/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/CodeSnippet-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/CodeSnippet-test.tsx.snap @@ -6,6 +6,7 @@ exports[`renders correctly: array snippet 1`] = ` > <pre className="flex-1" + tabIndex={0} > foo \\ bar @@ -23,6 +24,7 @@ exports[`renders correctly: default 1`] = ` > <pre className="flex-1" + tabIndex={0} > foo bar @@ -40,6 +42,7 @@ exports[`renders correctly: no copy 1`] = ` > <pre className="flex-1" + tabIndex={0} > foo bar @@ -53,6 +56,7 @@ exports[`renders correctly: single line with array snippet 1`] = ` > <pre className="flex-1" + tabIndex={0} > foo bar </pre> 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 145b388204f..423495025c3 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3169,7 +3169,7 @@ overview.badges.quality_gate.description=Displays the current quality gate statu overview.badges.quality_gate.description.APP=Displays the current quality gate status of your application. overview.badges.quality_gate.description.TRK=Displays the current quality gate status of your project. overview.badges.quality_gate.description.VW=Displays the current quality gate status of your portfolio. - +overview.badges.leak_warning=Project badges can expose your security rating and other measures. Only use project badges in trusted environments. #------------------------------------------------------------------------------ # |