diff options
author | Philippe Perrin <philippe.perrin@sonarsource.com> | 2021-10-20 10:48:08 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-11-09 20:03:16 +0000 |
commit | e03b2bf40be7de4821cdf009c74dffc90b87757b (patch) | |
tree | 0348599747bae1b6e74b52d9efbc8f05013250aa /server/sonar-web/src/main/js/apps/code | |
parent | e8905886d0e77cc080022dff7e0df79e4823e5de (diff) | |
download | sonarqube-e03b2bf40be7de4821cdf009c74dffc90b87757b.tar.gz sonarqube-e03b2bf40be7de4821cdf009c74dffc90b87757b.zip |
SONAR-15498 Manual selection of project's branches for portfolio
Display portfolio's children branch information and group issues by project and branch
Diffstat (limited to 'server/sonar-web/src/main/js/apps/code')
7 files changed, 133 insertions, 60 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 9bb59ded960..271be298ac2 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 @@ -217,7 +217,7 @@ export class CodeApp extends React.PureComponent<Props, State> { const { branchLike, component: rootComponent } = this.props; if (component.refKey) { - this.props.router.push(getProjectUrl(component.refKey)); + this.props.router.push(getProjectUrl(component.refKey, component.branch)); } else { this.props.router.push(getCodeUrl(rootComponent.key, branchLike, component.key)); } diff --git a/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx b/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx index 495009f47c0..0d60199053d 100644 --- a/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/ComponentName.tsx @@ -26,14 +26,16 @@ import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { getProjectUrl } from '../../../helpers/urls'; import { BranchLike } from '../../../types/branch-like'; +import { ComponentQualifier } from '../../../types/component'; export function getTooltip(component: T.ComponentMeasure) { const isFile = component.qualifier === 'FIL' || component.qualifier === 'UTS'; + if (isFile && component.path) { return component.path + '\n\n' + component.key; - } else { - return component.name + '\n\n' + component.key; } + + return [component.name, component.key, component.branch].filter(s => !!s).join('\n\n'); } export function mostCommonPrefix(strings: string[]) { @@ -82,8 +84,12 @@ export default function ComponentName({ let inner = null; - if (component.refKey && component.qualifier !== 'SVW') { - const branch = rootComponent.qualifier === 'APP' ? component.branch : undefined; + if (component.refKey && component.qualifier !== ComponentQualifier.SubPortfolio) { + const branch = [ComponentQualifier.Application, ComponentQualifier.Portfolio].includes( + rootComponent.qualifier as ComponentQualifier + ) + ? component.branch + : undefined; inner = ( <Link className="link-with-icon" to={getProjectUrl(component.refKey, branch)}> <QualifierIcon qualifier={component.qualifier} /> <span>{name}</span> @@ -107,7 +113,14 @@ export default function ComponentName({ ); } - if (rootComponent.qualifier === 'APP') { + if ( + [ComponentQualifier.Application, ComponentQualifier.Portfolio].includes( + rootComponent.qualifier as ComponentQualifier + ) && + [ComponentQualifier.Application, ComponentQualifier.Project].includes( + component.qualifier as ComponentQualifier + ) + ) { return ( <span className="max-width-100 display-inline-flex-center"> <span className="text-ellipsis" title={getTooltip(component)}> diff --git a/server/sonar-web/src/main/js/apps/code/components/Components.tsx b/server/sonar-web/src/main/js/apps/code/components/Components.tsx index 5191e9d484a..a4ede240bac 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Components.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/Components.tsx @@ -17,9 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { intersection } from 'lodash'; +import { intersection, sortBy } from 'lodash'; import * as React from 'react'; import withKeyboardNavigation from '../../../components/hoc/withKeyboardNavigation'; +import { getComponentMeasureUniqueKey } from '../../../helpers/component'; import { BranchLike } from '../../../types/branch-like'; import { getCodeMetrics } from '../utils'; import Component from './Component'; @@ -82,18 +83,26 @@ export class Components extends React.PureComponent<Props> { )} {components.length ? ( - components.map((component, index, list) => ( + sortBy( + components, + c => c.qualifier, + c => c.name.toLowerCase(), + c => c.branch?.toLowerCase() + ).map((component, index, list) => ( <Component branchLike={branchLike} canBePinned={canBePinned} canBrowse={true} component={component} hasBaseComponent={baseComponent !== undefined} - key={component.key} + key={getComponentMeasureUniqueKey(component)} metrics={metrics} previous={index > 0 ? list[index - 1] : undefined} rootComponent={rootComponent} - selected={selected && component.key === selected.key} + selected={ + selected && + getComponentMeasureUniqueKey(component) === getComponentMeasureUniqueKey(selected) + } /> )) ) : ( diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx b/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx index 049c3ccc248..17d0976813f 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/ComponentName-test.tsx @@ -21,6 +21,7 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockMainBranch } from '../../../../helpers/mocks/branch-like'; import { mockComponentMeasure } from '../../../../helpers/mocks/component'; +import { ComponentQualifier } from '../../../../types/component'; import ComponentName, { getTooltip, mostCommonPrefix, Props } from '../ComponentName'; describe('#getTooltip', () => { @@ -79,7 +80,7 @@ describe('#ComponentName', () => { component: mockComponentMeasure(false, { branch: 'foo', refKey: 'src/main/ts/app', - qualifier: 'TRK' + qualifier: ComponentQualifier.Project }) }) ).toMatchSnapshot(); @@ -88,9 +89,19 @@ describe('#ComponentName', () => { component: mockComponentMeasure(false, { branch: 'foo', refKey: 'src/main/ts/app', - qualifier: 'TRK' + qualifier: ComponentQualifier.Project }), - rootComponent: mockComponentMeasure(false, { qualifier: 'APP' }) + rootComponent: mockComponentMeasure(false, { qualifier: ComponentQualifier.Application }) + }) + ).toMatchSnapshot(); + + expect( + shallowRender({ + component: mockComponentMeasure(false, { + refKey: 'src/main/ts/app', + qualifier: ComponentQualifier.Project + }), + rootComponent: mockComponentMeasure(false, { qualifier: ComponentQualifier.Portfolio }) }) ).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/Components-test.tsx b/server/sonar-web/src/main/js/apps/code/components/__tests__/Components-test.tsx index 8d2565f925a..82dbe8e22b8 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/Components-test.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/Components-test.tsx @@ -20,10 +20,16 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockBranch } from '../../../../helpers/mocks/branch-like'; +import { ComponentQualifier } from '../../../../types/component'; import { Components } from '../Components'; -const COMPONENT = { key: 'foo', name: 'Foo', qualifier: 'TRK' }; -const PORTFOLIO = { key: 'bar', name: 'Bar', qualifier: 'VW' }; +const COMPONENT = { + key: 'foo', + name: 'Foo', + qualifier: ComponentQualifier.Project, + branch: 'develop' +}; +const PORTFOLIO = { key: 'bar', name: 'Bar', qualifier: ComponentQualifier.Portfolio }; const METRICS = { coverage: { id: '1', key: 'coverage', type: 'PERCENT', name: 'Coverage' } }; const BRANCH = mockBranch({ name: 'feature' }); diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap index 8922328f440..fe5e63e44a1 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/ComponentName-test.tsx.snap @@ -115,59 +115,34 @@ foo:src/index.tsx" exports[`#ComponentName should render correctly for files 4`] = ` <span - className="max-width-100 display-inline-flex-center" -> - <span - className="text-ellipsis" - title="src/index.tsx + className="max-width-100 display-inline-block text-ellipsis" + title="src/index.tsx foo:src/index.tsx" - > - <span> - <QualifierIcon - qualifier="FIL" - /> - - index.tsx - </span> - </span> - <span - className="spacer-left badge flex-1" - > - branches.main_branch +> + <span> + <QualifierIcon + qualifier="FIL" + /> + + index.tsx </span> </span> `; exports[`#ComponentName should render correctly for files 5`] = ` <span - className="max-width-100 display-inline-flex-center" -> - <span - className="text-ellipsis" - title="src/index.tsx + className="max-width-100 display-inline-block text-ellipsis" + title="src/index.tsx foo:src/index.tsx" - > - <span> - <QualifierIcon - qualifier="FIL" - /> - - index.tsx - </span> - </span> - <span - className="text-ellipsis spacer-left" - > - <BranchIcon - className="little-spacer-right" +> + <span> + <QualifierIcon + qualifier="FIL" /> - <span - className="note" - > - foo - </span> + + index.tsx </span> </span> `; @@ -177,6 +152,8 @@ exports[`#ComponentName should render correctly for refs 1`] = ` className="max-width-100 display-inline-block text-ellipsis" title="Foo +foo + foo" > <Link @@ -212,6 +189,8 @@ exports[`#ComponentName should render correctly for refs 2`] = ` className="text-ellipsis" title="Foo +foo + foo" > <Link @@ -252,6 +231,47 @@ foo" </span> `; +exports[`#ComponentName should render correctly for refs 3`] = ` +<span + className="max-width-100 display-inline-flex-center" +> + <span + className="text-ellipsis" + title="Foo + +foo" + > + <Link + className="link-with-icon" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/dashboard", + "query": Object { + "branch": undefined, + "id": "src/main/ts/app", + }, + } + } + > + <QualifierIcon + qualifier="TRK" + /> + + <span> + Foo + </span> + </Link> + </span> + <span + className="spacer-left badge flex-1" + > + branches.main_branch + </span> +</span> +`; + exports[`#getTooltip should correctly format component information 1`] = ` "src/index.tsx diff --git a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Components-test.tsx.snap b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Components-test.tsx.snap index 3a2adbdcace..5ed9ee9a737 100644 --- a/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Components-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Components-test.tsx.snap @@ -7,6 +7,7 @@ exports[`renders correctly 1`] = ` <ComponentsHeader baseComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -20,6 +21,7 @@ exports[`renders correctly 1`] = ` } rootComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -31,6 +33,7 @@ exports[`renders correctly 1`] = ` canBePinned={true} component={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -50,6 +53,7 @@ exports[`renders correctly 1`] = ` } rootComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -79,13 +83,14 @@ exports[`renders correctly 1`] = ` canBrowse={true} component={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", } } hasBaseComponent={true} - key="foo" + key="foo/develop" metrics={ Array [ Object { @@ -98,6 +103,7 @@ exports[`renders correctly 1`] = ` } rootComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -127,16 +133,18 @@ exports[`renders correctly for a search 1`] = ` canBrowse={true} component={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", } } hasBaseComponent={false} - key="foo" + key="foo/develop" metrics={Array []} rootComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -164,6 +172,7 @@ exports[`renders correctly for leak 1`] = ` <ComponentsHeader baseComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -177,6 +186,7 @@ exports[`renders correctly for leak 1`] = ` } rootComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -196,6 +206,7 @@ exports[`renders correctly for leak 1`] = ` canBePinned={true} component={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -215,6 +226,7 @@ exports[`renders correctly for leak 1`] = ` } rootComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", @@ -252,13 +264,14 @@ exports[`renders correctly for leak 1`] = ` canBrowse={true} component={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", } } hasBaseComponent={true} - key="foo" + key="foo/develop" metrics={ Array [ Object { @@ -271,6 +284,7 @@ exports[`renders correctly for leak 1`] = ` } rootComponent={ Object { + "branch": "develop", "key": "foo", "name": "Foo", "qualifier": "TRK", |