From: Stas Vilchik Date: Thu, 19 Jul 2018 13:04:53 +0000 (+0200) Subject: SONAR-11015 Allow to add links for SonarQube global spaces (#531) X-Git-Tag: 7.5~729 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7b1ee59a8b7ffb30e2ed21c1eacf83bc5cff8f43;p=sonarqube.git SONAR-11015 Allow to add links for SonarQube global spaces (#531) --- diff --git a/server/sonar-docs/src/pages/analysis/index.md b/server/sonar-docs/src/pages/analysis/index.md index 8ddcdcd12d9..066993ae887 100644 --- a/server/sonar-docs/src/pages/analysis/index.md +++ b/server/sonar-docs/src/pages/analysis/index.md @@ -29,7 +29,7 @@ SonarQube can perform analysis on 20+ different languages. The outcome of this a * A dynamic analysis of code can be performed on certain languages. ## Will _all_ files be analyzed? -By default, only files that are recognized by a language analyzer are loaded into the project during analysis. For example if your SonarQube instance had only SonarJava SonarJS on board, all .java and .js files would be loaded, but .xml files would be ignored. However, it is possible to import all text files in a project by setting **Settings > Exclusions > Files > Import unknown files** to true. +By default, only files that are recognized by a language analyzer are loaded into the project during analysis. For example if your SonarQube instance had only SonarJava SonarJS on board, all .java and .js files would be loaded, but .xml files would be ignored. However, it is possible to import all text files in a project by setting [**Settings > Exclusions > Files > Import unknown files**](/#sonarqube-admin#/admin/settings?category=exclusions) to true. ## What happens during analysis? During analysis, data is requested from the server, the files provided to the analysis are analyzed, and the resulting data is sent back to the server at the end in the form of a report, which is then analyzed asynchronously server-side. diff --git a/server/sonar-docs/src/pages/quality-profiles.md b/server/sonar-docs/src/pages/quality-profiles.md index c6c746dbe09..1e9c03e95e6 100644 --- a/server/sonar-docs/src/pages/quality-profiles.md +++ b/server/sonar-docs/src/pages/quality-profiles.md @@ -12,7 +12,7 @@ Ideally, all projects will be measured with the same profile for any given langu * You want to ensure stronger requirements on some of your applications (internal frameworks for example). * Etc. -Which is why you can define as many quality profiles as you wish even though it is recommended to have as few Quality Profiles as possible to ensure consistency across the projects in your company. To manage quality profiles, go to **Quality Profiles** (top bar), where you'll find profiles grouped by language. +Which is why you can define as many quality profiles as you wish even though it is recommended to have as few Quality Profiles as possible to ensure consistency across the projects in your company. To manage quality profiles, go to [**Quality Profiles**](/#sonarqube#/profiles)**Quality Profiles** page of your organization, where you'll find profiles grouped by language. Each language plugin comes with a predefined, built-in profile (usually called "Sonar way") so that you can get started very quickly with SonarQube analyses. This is why as soon as you install a new language plugin, at least one quality profile will be available for you. Each language must have a default profile (marked with the Default tag). Projects that are not explicitly associated with a specific profile will be analyzed using the language's default profile. diff --git a/server/sonar-web/src/main/js/components/docs/DocLink.tsx b/server/sonar-web/src/main/js/components/docs/DocLink.tsx index 5a0eb5de4b8..f091b342294 100644 --- a/server/sonar-web/src/main/js/components/docs/DocLink.tsx +++ b/server/sonar-web/src/main/js/components/docs/DocLink.tsx @@ -20,6 +20,7 @@ import * as React from 'react'; import { Link } from 'react-router'; import DetachIcon from '../icons-components/DetachIcon'; +import { isSonarCloud } from '../../helpers/system'; interface OwnProps { customProps?: { @@ -30,8 +31,14 @@ interface OwnProps { type Props = OwnProps & React.AnchorHTMLAttributes; const SONARCLOUD_LINK = '/#sonarcloud#/'; +const SONARQUBE_LINK = '/#sonarqube#/'; +const SONARQUBE_ADMIN_LINK = '/#sonarqube-admin#/'; export default class DocLink extends React.PureComponent { + static contextTypes = { + canAdmin: () => null + }; + handleClickOnAnchor = (event: React.MouseEvent) => { const { customProps, href = '#' } = this.props; if (customProps && customProps.onAnchorClick) { @@ -50,15 +57,24 @@ export default class DocLink extends React.PureComponent { } if (href && href.startsWith('/')) { - let url = `/documentation/${href.substr(1)}`; if (href.startsWith(SONARCLOUD_LINK)) { - url = `/${href.substr(SONARCLOUD_LINK.length)}`; + return {children}; + } else if (href.startsWith(SONARQUBE_LINK)) { + return {children}; + } else if (href.startsWith(SONARQUBE_ADMIN_LINK)) { + return ( + + {children} + + ); + } else { + const url = '/documentation' + href; + return ( + + {children} + + ); } - return ( - - {children} - - ); } return ( @@ -74,3 +90,54 @@ export default class DocLink extends React.PureComponent { ); } } + +interface SonarCloudLinkProps { + children: React.ReactNode; + url: string; +} + +function SonarCloudLink({ children, url }: SonarCloudLinkProps) { + if (!isSonarCloud()) { + return <>{children}; + } else { + const to = `/${url.substr(SONARCLOUD_LINK.length)}`; + return {children}; + } +} + +interface SonarQubeLinkProps { + children: React.ReactNode; + url: string; +} + +function SonarQubeLink({ children, url }: SonarQubeLinkProps) { + if (isSonarCloud()) { + return <>{children}; + } else { + const to = `/${url.substr(SONARQUBE_LINK.length)}`; + return ( + + {children} + + ); + } +} + +interface SonarQubeAdminLinkProps { + canAdmin: boolean; + children: React.ReactNode; + url: string; +} + +function SonarQubeAdminLink({ canAdmin, children, url }: SonarQubeAdminLinkProps) { + if (isSonarCloud() || !canAdmin) { + return <>{children}; + } else { + const to = `/${url.substr(SONARQUBE_ADMIN_LINK.length)}`; + return ( + + {children} + + ); + } +} diff --git a/server/sonar-web/src/main/js/components/docs/__tests__/DocLink-test.tsx b/server/sonar-web/src/main/js/components/docs/__tests__/DocLink-test.tsx index 4b394343c35..54871ff53f3 100644 --- a/server/sonar-web/src/main/js/components/docs/__tests__/DocLink-test.tsx +++ b/server/sonar-web/src/main/js/components/docs/__tests__/DocLink-test.tsx @@ -20,19 +20,66 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import DocLink from '../DocLink'; +import { isSonarCloud } from '../../../helpers/system'; + +jest.mock('../../../helpers/system', () => ({ + isSonarCloud: jest.fn(() => false) +})); it('should render simple link', () => { - expect(shallow()).toMatchSnapshot(); + expect(shallow(link text)).toMatchSnapshot(); }); it('should render documentation link', () => { - expect(shallow()).toMatchSnapshot(); + expect(shallow(link text)).toMatchSnapshot(); +}); + +it('should render sonarcloud link on sonarcloud', () => { + (isSonarCloud as jest.Mock).mockImplementationOnce(() => true); + const wrapper = shallow(link text); + expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('SonarCloudLink').dive()).toMatchSnapshot(); +}); + +it('should not render sonarcloud link on sonarcloud', () => { + (isSonarCloud as jest.Mock).mockImplementationOnce(() => false); + const wrapper = shallow(link text); + expect(wrapper.find('SonarCloudLink').dive()).toMatchSnapshot(); +}); + +it('should render sonarqube link on sonarqube', () => { + const wrapper = shallow(link text); + expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('SonarQubeLink').dive()).toMatchSnapshot(); +}); + +it('should not render sonarqube link on sonarcloud', () => { + (isSonarCloud as jest.Mock).mockImplementationOnce(() => true); + const wrapper = shallow(link text); + expect(wrapper.find('SonarQubeLink').dive()).toMatchSnapshot(); +}); + +it('should render sonarqube admin link on sonarqube for admin', () => { + const wrapper = shallow(link text, { + context: { canAdmin: true } + }); + expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('SonarQubeAdminLink').dive()).toMatchSnapshot(); +}); + +it('should not render sonarqube admin link on sonarqube for non-admin', () => { + const wrapper = shallow(link text); + expect(wrapper.find('SonarQubeAdminLink').dive()).toMatchSnapshot(); }); -it('should render sonarcloud link', () => { - expect(shallow()).toMatchSnapshot(); +it('should not render sonarqube admin link on sonarcloud', () => { + (isSonarCloud as jest.Mock).mockImplementationOnce(() => true); + const wrapper = shallow(link text, { + context: { canAdmin: true } + }); + expect(wrapper.find('SonarQubeAdminLink').dive()).toMatchSnapshot(); }); it.skip('should render documentation anchor', () => { - expect(shallow()).toMatchSnapshot(); + expect(shallow(link text)).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocLink-test.tsx.snap b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocLink-test.tsx.snap index 4d443347a2e..04cabb55055 100644 --- a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocLink-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocLink-test.tsx.snap @@ -1,11 +1,37 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`should not render sonarcloud link on sonarcloud 1`] = ` + + link text + +`; + +exports[`should not render sonarqube admin link on sonarcloud 1`] = ` + + link text + +`; + +exports[`should not render sonarqube admin link on sonarqube for non-admin 1`] = ` + + link text + +`; + +exports[`should not render sonarqube link on sonarcloud 1`] = ` + + link text + +`; + exports[`should render documentation link 1`] = ` +> + link text + `; exports[`should render simple link 1`] = ` @@ -14,7 +40,9 @@ exports[`should render simple link 1`] = ` href="http://sample.com" rel="noopener noreferrer" target="_blank" - /> + > + link text + `; -exports[`should render sonarcloud link 1`] = ` +exports[`should render sonarcloud link on sonarcloud 1`] = ` + + link text + +`; + +exports[`should render sonarcloud link on sonarcloud 2`] = ` + + link text + +`; + +exports[`should render sonarqube admin link on sonarqube for admin 1`] = ` + + link text + +`; + +exports[`should render sonarqube admin link on sonarqube for admin 2`] = ` + + link text + +`; + +exports[`should render sonarqube link on sonarqube 1`] = ` + + link text + +`; + +exports[`should render sonarqube link on sonarqube 2`] = ` +> + link text + `;