aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorGuillaume Peoc'h <guillaume.peoch@sonarsource.com>2022-01-14 16:01:53 +0100
committersonartech <sonartech@sonarsource.com>2022-01-20 20:02:44 +0000
commit2d8e328da235ecd46b6eb7bc486d1d937c2060c1 (patch)
tree9a0d9dea63ccc905e1e85b5a9a0ad35b64585705 /server/sonar-web
parentba3f291e93f36f55ea22a60a47d229e0a60c4ea5 (diff)
downloadsonarqube-2d8e328da235ecd46b6eb7bc486d1d937c2060c1.tar.gz
sonarqube-2d8e328da235ecd46b6eb7bc486d1d937c2060c1.zip
SONAR-15882 Add warning in Portfolios Project
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx19
-rw-r--r--server/sonar-web/src/main/js/apps/code/components/__tests__/CodeApp-test.tsx46
-rw-r--r--server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/CodeApp-test.tsx.snap63
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/App.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/component-measures/components/__tests__/__snapshots__/App-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap2
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