diff options
author | Guillaume Peoc'h <guillaume.peoch@sonarsource.com> | 2022-01-14 16:01:53 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-01-20 20:02:44 +0000 |
commit | 2d8e328da235ecd46b6eb7bc486d1d937c2060c1 (patch) | |
tree | 9a0d9dea63ccc905e1e85b5a9a0ad35b64585705 /server/sonar-web | |
parent | ba3f291e93f36f55ea22a60a47d229e0a60c4ea5 (diff) | |
download | sonarqube-2d8e328da235ecd46b6eb7bc486d1d937c2060c1.tar.gz sonarqube-2d8e328da235ecd46b6eb7bc486d1d937c2060c1.zip |
SONAR-15882 Add warning in Portfolios Project
Diffstat (limited to 'server/sonar-web')
7 files changed, 134 insertions, 6 deletions
diff --git a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx index 50869e78662..3f1d6d48ce7 100644 --- a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import styled from '@emotion/styled'; import classNames from 'classnames'; import { Location } from 'history'; import { debounce, intersection } from 'lodash'; @@ -26,13 +27,16 @@ import { connect } from 'react-redux'; import { InjectedRouter } from 'react-router'; import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget'; import Suggestions from '../../../app/components/embed-docs-modal/Suggestions'; +import HelpTooltip from '../../../components/controls/HelpTooltip'; import ListFooter from '../../../components/controls/ListFooter'; +import { Alert } from '../../../components/ui/Alert'; import { isPullRequest, isSameBranchLike } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { getCodeUrl, getProjectUrl } from '../../../helpers/urls'; import { fetchBranchStatus, fetchMetrics } from '../../../store/rootActions'; import { getMetrics } from '../../../store/rootReducer'; import { BranchLike } from '../../../types/branch-like'; +import { isPortfolioLike } from '../../../types/component'; import { addComponent, addComponentBreadcrumbs, clearBucket } from '../bucket'; import '../code.css'; import { @@ -264,6 +268,7 @@ export class CodeApp extends React.Component<Props, State> { searchResults, sourceViewer } = this.state; + const { canBrowseAllChildProjects, qualifier } = component; const showSearch = searchResults !== undefined; @@ -291,6 +296,16 @@ export class CodeApp extends React.Component<Props, State> { return ( <div className="page page-limited"> + {!canBrowseAllChildProjects && isPortfolioLike(qualifier) && ( + <StyledAlert variant="warning"> + {translate('component_measures.not_all_measures_are_shown')} + <HelpTooltip + className="spacer-left" + ariaLabel={translate('component_measures.not_all_measures_are_shown.help')} + overlay={translate('component_measures.not_all_measures_are_shown.help')} + /> + </StyledAlert> + )} <Suggestions suggestions="code" /> <Helmet defer={false} @@ -381,6 +396,10 @@ export class CodeApp extends React.Component<Props, State> { ); } } +const StyledAlert = styled(Alert)` + display: inline-flex; + margin-bottom: 15px; +`; const mapStateToProps = (state: any): StateToProps => ({ metrics: getMetrics(state) diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/CodeApp-test.tsx b/server/sonar-web/src/main/js/apps/code/components/__tests__/CodeApp-test.tsx index 0aab5241e01..6e1460fa9c0 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/CodeApp-test.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/CodeApp-test.tsx @@ -58,7 +58,13 @@ it.each([ [ComponentQualifier.Portfolio], [ComponentQualifier.SubPortfolio] ])('should render correclty when no sub component for %s', async qualifier => { - const component = { breadcrumbs: [], name: 'foo', key: 'foo', qualifier }; + const component = { + breadcrumbs: [], + name: 'foo', + key: 'foo', + qualifier, + canBrowseAllChildProjects: true + }; (retrieveComponent as jest.Mock<any>).mockResolvedValueOnce({ breadcrumbs: [], component, @@ -186,7 +192,10 @@ it('should correcly display new/overall measure for portfolio', async () => { }); const wrapper = shallowRender({ - component: mockComponent({ qualifier: ComponentQualifier.Portfolio }), + component: mockComponent({ + qualifier: ComponentQualifier.Portfolio, + canBrowseAllChildProjects: true + }), metrics }); await waitAndUpdate(wrapper); @@ -216,6 +225,39 @@ it('should handle select correctly', () => { }); }); +it('should render a warning message when user does not have access to all projects whithin a Portfolio', async () => { + const wrapper = shallowRender({ + component: mockComponent({ + qualifier: ComponentQualifier.Portfolio, + canBrowseAllChildProjects: false + }) + }); + await waitAndUpdate(wrapper); + expect(wrapper).toMatchSnapshot('Project page with warning'); +}); + +it.each([ + [ComponentQualifier.Portfolio, true, false], + [ComponentQualifier.Project, false, false], + [ComponentQualifier.Portfolio, false, true] +])( + 'should not render a warning message', + async ( + componentQualifier: ComponentQualifier, + canBrowseAllChildProjects: boolean, + alertIsVisible: boolean + ) => { + const wrapper = shallowRender({ + component: mockComponent({ + qualifier: componentQualifier, + canBrowseAllChildProjects + }) + }); + await waitAndUpdate(wrapper); + expect(wrapper.find('Styled(Alert)').exists()).toBe(alertIsVisible); + } +); + function shallowRender(props: Partial<CodeApp['props']> = {}) { return shallow<CodeApp>( <CodeApp diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/CodeApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/CodeApp-test.tsx.snap index b45c7534519..ad7f2051d1c 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/CodeApp-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/CodeApp-test.tsx.snap @@ -61,6 +61,7 @@ Object { "onSelect": [Function], "rootComponent": Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "my-project", "name": "MyProject", "qualifier": "VW", @@ -144,6 +145,7 @@ Object { "onSelect": [Function], "rootComponent": Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "my-project", "name": "MyProject", "qualifier": "VW", @@ -166,6 +168,47 @@ Object { } `; +exports[`should render a warning message when user does not have access to all projects whithin a Portfolio: Project page with warning 1`] = ` +<div + className="page page-limited" +> + <Styled(Alert) + variant="warning" + > + component_measures.not_all_measures_are_shown + <HelpTooltip + ariaLabel="component_measures.not_all_measures_are_shown.help" + className="spacer-left" + overlay="component_measures.not_all_measures_are_shown.help" + /> + </Styled(Alert)> + <Suggestions + suggestions="code" + /> + <Helmet + defer={false} + encodeSpecialCharacters={true} + title="projects.page" + /> + <A11ySkipTarget + anchor="code_main" + /> + <div + className="code-components" + > + <div + className="display-flex-center display-flex-column no-file" + > + <span + className="h1 text-muted" + > + code_viewer.no_source_code_displayed_due_to_empty_analysis.VW + </span> + </div> + </div> +</div> +`; + exports[`should render correclty when no sub component for APP 1`] = ` <div className="page page-limited" @@ -216,6 +259,7 @@ exports[`should render correclty when no sub component for APP: no search 1`] = component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "APP", @@ -240,6 +284,7 @@ exports[`should render correclty when no sub component for APP: no search 1`] = rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "APP", @@ -270,6 +315,7 @@ exports[`should render correclty when no sub component for APP: with sub compone component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "APP", @@ -290,6 +336,7 @@ exports[`should render correclty when no sub component for APP: with sub compone baseComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "APP", @@ -338,6 +385,7 @@ exports[`should render correclty when no sub component for APP: with sub compone rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "APP", @@ -404,6 +452,7 @@ exports[`should render correclty when no sub component for SVW: no search 1`] = component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "SVW", @@ -428,6 +477,7 @@ exports[`should render correclty when no sub component for SVW: no search 1`] = rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "SVW", @@ -458,6 +508,7 @@ exports[`should render correclty when no sub component for SVW: with sub compone component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "SVW", @@ -478,6 +529,7 @@ exports[`should render correclty when no sub component for SVW: with sub compone baseComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "SVW", @@ -516,6 +568,7 @@ exports[`should render correclty when no sub component for SVW: with sub compone rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "SVW", @@ -582,6 +635,7 @@ exports[`should render correclty when no sub component for TRK: no search 1`] = component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "TRK", @@ -606,6 +660,7 @@ exports[`should render correclty when no sub component for TRK: no search 1`] = rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "TRK", @@ -636,6 +691,7 @@ exports[`should render correclty when no sub component for TRK: with sub compone component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "TRK", @@ -656,6 +712,7 @@ exports[`should render correclty when no sub component for TRK: with sub compone baseComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "TRK", @@ -704,6 +761,7 @@ exports[`should render correclty when no sub component for TRK: with sub compone rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "TRK", @@ -770,6 +828,7 @@ exports[`should render correclty when no sub component for VW: no search 1`] = ` component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "VW", @@ -794,6 +853,7 @@ exports[`should render correclty when no sub component for VW: no search 1`] = ` rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "VW", @@ -824,6 +884,7 @@ exports[`should render correclty when no sub component for VW: with sub componen component={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "VW", @@ -844,6 +905,7 @@ exports[`should render correclty when no sub component for VW: with sub componen baseComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "VW", @@ -882,6 +944,7 @@ exports[`should render correclty when no sub component for VW: with sub componen rootComponent={ Object { "breadcrumbs": Array [], + "canBrowseAllChildProjects": true, "key": "foo", "name": "foo", "qualifier": "VW", diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx index 931289e8965..003a23da05b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.tsx @@ -305,7 +305,9 @@ export class App extends React.PureComponent<Props, State> { <div className="layout-page-side" style={{ top }}> <div className="layout-page-side-inner"> {!canBrowseAllChildProjects && isPortfolioLike(qualifier) && ( - <Alert className="big-spacer-top big-spacer-right" variant="warning"> + <Alert + className="big-spacer-top big-spacer-right big-spacer-left" + variant="warning"> {translate('component_measures.not_all_measures_are_shown')} <HelpTooltip className="spacer-left" diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap index a702f6768c7..14b96b76b6c 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap @@ -69,7 +69,7 @@ exports[`should render a warning message when user does not have access to all p className="layout-page-side-inner" > <Alert - className="big-spacer-top big-spacer-right" + className="big-spacer-top big-spacer-right big-spacer-left" variant="warning" > component_measures.not_all_measures_are_shown diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx index 3dd1302ee4d..8c9a0b0c73e 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx @@ -959,7 +959,9 @@ export default class App extends React.PureComponent<Props, State> { style={{ top }}> <div className="layout-page-side-inner"> {!canBrowseAllChildProjects && isPortfolioLike(qualifier) && ( - <Alert className="big-spacer-top big-spacer-right" variant="warning"> + <Alert + className="big-spacer-top big-spacer-right big-spacer-left" + variant="warning"> {translate('issues.not_all_issue_show')} <HelpTooltip className="spacer-left" diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap index 6ea8ad74e5b..99ba1657dab 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap @@ -37,7 +37,7 @@ exports[`should show warnning when not all projects are accessible 1`] = ` className="layout-page-side-inner" > <Alert - className="big-spacer-top big-spacer-right" + className="big-spacer-top big-spacer-right big-spacer-left" variant="warning" > issues.not_all_issue_show |