aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-08-14 16:43:17 +0200
committerSonarTech <sonartech@sonarsource.com>2018-08-21 20:21:02 +0200
commitd4fa9a5eec91b3cc36a7ac6b0b1c0ff3359162d9 (patch)
tree20aefaf5d526b5a1dda744cf9297605d6c04beec /server/sonar-web
parent63055cd49b4053c4f99949f505f6ce1214cb4135 (diff)
downloadsonarqube-d4fa9a5eec91b3cc36a7ac6b0b1c0ff3359162d9.tar.gz
sonarqube-d4fa9a5eec91b3cc36a7ac6b0b1c0ff3359162d9.zip
SONAR-10997 display the total effort on the issues page (#615)
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/api/issues.ts2
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/App.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/TotalEffort.tsx37
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/App-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/PageActions-test.tsx36
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/TotalEffort-test.tsx26
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/PageActions-test.tsx.snap63
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/TotalEffort-test.tsx.snap23
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>
+`;