diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-08-14 16:43:17 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-08-21 20:21:02 +0200 |
commit | d4fa9a5eec91b3cc36a7ac6b0b1c0ff3359162d9 (patch) | |
tree | 20aefaf5d526b5a1dda744cf9297605d6c04beec /server/sonar-web | |
parent | 63055cd49b4053c4f99949f505f6ce1214cb4135 (diff) | |
download | sonarqube-d4fa9a5eec91b3cc36a7ac6b0b1c0ff3359162d9.tar.gz sonarqube-d4fa9a5eec91b3cc36a7ac6b0b1c0ff3359162d9.zip |
SONAR-10997 display the total effort on the issues page (#615)
Diffstat (limited to 'server/sonar-web')
9 files changed, 196 insertions, 3 deletions
diff --git a/server/sonar-web/src/main/js/api/issues.ts b/server/sonar-web/src/main/js/api/issues.ts index b49a6eddba9..202190af502 100644 --- a/server/sonar-web/src/main/js/api/issues.ts +++ b/server/sonar-web/src/main/js/api/issues.ts @@ -31,7 +31,7 @@ export interface IssueResponse { interface IssuesResponse { components?: { key: string; organization: string; name: string; uuid: string }[]; - debtTotal?: number; + effortTotal: number; facets: Array<{ property: string; values: { count: number; val: string }[]; diff --git a/server/sonar-web/src/main/js/apps/issues/components/App.tsx b/server/sonar-web/src/main/js/apps/issues/components/App.tsx index 067668fbd01..3d26c6b39fc 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/App.tsx @@ -87,6 +87,7 @@ import DeferredSpinner from '../../../components/common/DeferredSpinner'; interface FetchIssuesPromise { components: ReferencedComponent[]; + effortTotal: number; facets: RawFacet[]; issues: Issue[]; languages: ReferencedLanguage[]; @@ -111,6 +112,7 @@ interface Props { export interface State { bulkChange?: 'all' | 'selected'; checked: string[]; + effortTotal?: number; facets: { [facet: string]: Facet }; issues: Issue[]; lastChecked?: string; @@ -461,7 +463,7 @@ export default class App extends React.PureComponent<Props, State> { const prevQuery = this.props.location.query; this.setState({ checked: [], loading: true }); return this.fetchIssues({}, true).then( - ({ facets, issues, paging, ...other }) => { + ({ effortTotal, facets, issues, paging, ...other }) => { if (this.mounted && areQueriesEqual(prevQuery, this.props.location.query)) { const openIssue = this.getOpenIssue(this.props, issues); let selected: string | undefined = undefined; @@ -469,6 +471,7 @@ export default class App extends React.PureComponent<Props, State> { selected = openIssue ? openIssue.key : issues[0].key; } this.setState(state => ({ + effortTotal, facets: { ...state.facets, ...parseFacets(facets) }, loading: false, issues, @@ -1131,6 +1134,7 @@ export default class App extends React.PureComponent<Props, State> { !this.props.component && (!isSonarCloud() || this.props.myIssues) )} + effortTotal={this.state.effortTotal} onReload={this.handleReload} paging={paging} selectedIndex={selectedIndex} diff --git a/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx b/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx index 1850b50dbda..31eb0f06472 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx @@ -19,6 +19,7 @@ */ import * as React from 'react'; import IssuesCounter from './IssuesCounter'; +import TotalEffort from './TotalEffort'; import { HomePageType, Paging } from '../../../app/types'; import HomePageSelect from '../../../components/controls/HomePageSelect'; import ReloadButton from '../../../components/controls/ReloadButton'; @@ -27,6 +28,7 @@ import { isSonarCloud } from '../../../helpers/system'; interface Props { canSetHome: boolean; + effortTotal: number | undefined; onReload: () => void; paging: Paging | undefined; selectedIndex: number | undefined; @@ -52,7 +54,7 @@ export default class PageActions extends React.PureComponent<Props> { } render() { - const { paging, selectedIndex } = this.props; + const { effortTotal, paging, selectedIndex } = this.props; return ( <div className="pull-right"> @@ -63,6 +65,7 @@ export default class PageActions extends React.PureComponent<Props> { {paging != null && ( <IssuesCounter className="spacer-left" current={selectedIndex} total={paging.total} /> )} + {effortTotal !== undefined && <TotalEffort effort={effortTotal} />} </div> {this.props.canSetHome && ( diff --git a/server/sonar-web/src/main/js/apps/issues/components/TotalEffort.tsx b/server/sonar-web/src/main/js/apps/issues/components/TotalEffort.tsx new file mode 100644 index 00000000000..c6f4eed009b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/TotalEffort.tsx @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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 * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { translate } from '../../../helpers/l10n'; +import { formatMeasure } from '../../../helpers/measures'; + +export default function TotalEffort({ effort }: { effort: number }) { + return ( + <div className="display-inline-block bordered-left spacer-left"> + <div className="spacer-left"> + <FormattedMessage + defaultMessage={translate('issue.x_effort')} + id="issue.x_effort" + values={{ 0: <strong>{formatMeasure(effort, 'WORK_DUR')}</strong> }} + /> + </div> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx index bd16df2c7d1..2108d640fda 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx @@ -49,6 +49,7 @@ const PROPS = { fetchIssues: () => Promise.resolve({ components: [], + effortTotal: 1, facets, issues, languages: [], diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/PageActions-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/PageActions-test.tsx new file mode 100644 index 00000000000..581ef9add8a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/PageActions-test.tsx @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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 * as React from 'react'; +import { shallow } from 'enzyme'; +import PageActions from '../PageActions'; + +it('should render', () => { + expect( + shallow( + <PageActions + canSetHome={true} + effortTotal={125} + onReload={jest.fn()} + paging={{ pageIndex: 1, pageSize: 100, total: 12345 }} + selectedIndex={5} + /> + ) + ).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/TotalEffort-test.tsx b/server/sonar-web/src/main/js/apps/issues/components/__tests__/TotalEffort-test.tsx new file mode 100644 index 00000000000..2b4f8135784 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/TotalEffort-test.tsx @@ -0,0 +1,26 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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 * as React from 'react'; +import { shallow } from 'enzyme'; +import TotalEffort from '../TotalEffort'; + +it('should render', () => { + expect(shallow(<TotalEffort effort={125} />)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/PageActions-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/PageActions-test.tsx.snap new file mode 100644 index 00000000000..446f460ac6d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/PageActions-test.tsx.snap @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render 1`] = ` +<div + className="pull-right" +> + <span + className="note big-spacer-right" + > + <span + className="big-spacer-right" + > + <span + className="shortcut-button little-spacer-right" + > + ↑ + </span> + <span + className="shortcut-button little-spacer-right" + > + ↓ + </span> + issues.to_select_issues + </span> + <span> + <span + className="shortcut-button little-spacer-right" + > + ← + </span> + <span + className="shortcut-button little-spacer-right" + > + → + </span> + issues.to_navigate + </span> + </span> + <div + className="issues-page-actions" + > + <ReloadButton + onClick={[MockFunction]} + /> + <IssuesCounter + className="spacer-left" + current={5} + total={12345} + /> + <TotalEffort + effort={125} + /> + </div> + <Connect(HomePageSelect) + className="huge-spacer-left" + currentPage={ + Object { + "type": "ISSUES", + } + } + /> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/TotalEffort-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/TotalEffort-test.tsx.snap new file mode 100644 index 00000000000..791cfe582c2 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/TotalEffort-test.tsx.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render 1`] = ` +<div + className="display-inline-block bordered-left spacer-left" +> + <div + className="spacer-left" + > + <FormattedMessage + defaultMessage="issue.x_effort" + id="issue.x_effort" + values={ + Object { + "0": <strong> + work_duration.x_hours.2 work_duration.x_minutes.5 + </strong>, + } + } + /> + </div> +</div> +`; |