aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-08-16 12:39:05 +0200
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-08-17 16:42:34 +0200
commiteae2f0df4ef757c0c8fb92e49e808e5feace167b (patch)
tree15955463850ea50f510a944b02e3e5f9e0d4e8dc /server/sonar-web/src/main
parent8f016916eafb2052e472ba8eba78d0e7db4b5210 (diff)
downloadsonarqube-eae2f0df4ef757c0c8fb92e49e808e5feace167b.tar.gz
sonarqube-eae2f0df4ef757c0c8fb92e49e808e5feace167b.zip
SONAR-9605 Fix infinite spinner on issues page
Diffstat (limited to 'server/sonar-web/src/main')
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/App.js101
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/AppContainer.js11
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/PageActions.js10
-rw-r--r--server/sonar-web/src/main/js/apps/issues/styles.css4
6 files changed, 79 insertions, 54 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/components/App.js b/server/sonar-web/src/main/js/apps/issues/components/App.js
index 06746b240b0..56ef5e68d13 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/App.js
+++ b/server/sonar-web/src/main/js/apps/issues/components/App.js
@@ -67,7 +67,6 @@ export type Props = {
currentUser: CurrentUser,
fetchIssues: (query: RawQuery) => Promise<*>,
location: { pathname: string, query: RawQuery },
- onRequestFail: Error => void,
organization?: { key: string },
router: {
push: ({ pathname: string, query?: RawQuery }) => void,
@@ -381,27 +380,35 @@ export default class App extends React.PureComponent {
fetchFirstIssues() {
this.setState({ checked: [], loading: true });
- return this.fetchIssues({}, true).then(({ facets, issues, paging, ...other }) => {
- if (this.mounted) {
- const openIssue = this.getOpenIssue(this.props, issues);
- this.setState({
- facets: parseFacets(facets),
- loading: false,
- issues,
- openIssue,
- paging,
- referencedComponents: keyBy(other.components, 'uuid'),
- referencedLanguages: keyBy(other.languages, 'key'),
- referencedRules: keyBy(other.rules, 'key'),
- referencedUsers: keyBy(other.users, 'login'),
- selected:
- issues.length > 0 ? (openIssue != null ? openIssue.key : issues[0].key) : undefined,
- selectedFlowIndex: null,
- selectedLocationIndex: null
- });
+ return this.fetchIssues({}, true).then(
+ ({ facets, issues, paging, ...other }) => {
+ if (this.mounted) {
+ const openIssue = this.getOpenIssue(this.props, issues);
+ this.setState({
+ facets: parseFacets(facets),
+ loading: false,
+ issues,
+ openIssue,
+ paging,
+ referencedComponents: keyBy(other.components, 'uuid'),
+ referencedLanguages: keyBy(other.languages, 'key'),
+ referencedRules: keyBy(other.rules, 'key'),
+ referencedUsers: keyBy(other.users, 'login'),
+ selected:
+ issues.length > 0 ? (openIssue != null ? openIssue.key : issues[0].key) : undefined,
+ selectedFlowIndex: null,
+ selectedLocationIndex: null
+ });
+ }
+ return issues;
+ },
+ () => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ return Promise.reject();
}
- return issues;
- });
+ );
}
fetchIssuesPage = (p /*: number */) => {
@@ -433,15 +440,22 @@ export default class App extends React.PureComponent {
const p = paging.pageIndex + 1;
this.setState({ loading: true });
- this.fetchIssuesPage(p).then(response => {
- if (this.mounted) {
- this.setState(state => ({
- loading: false,
- issues: [...state.issues, ...response.issues],
- paging: response.paging
- }));
+ this.fetchIssuesPage(p).then(
+ response => {
+ if (this.mounted) {
+ this.setState(state => ({
+ loading: false,
+ issues: [...state.issues, ...response.issues],
+ paging: response.paging
+ }));
+ }
+ },
+ () => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
}
- });
+ );
};
fetchIssuesForComponent = (component /*: string */, from /*: number */, to /*: number */) => {
@@ -469,16 +483,24 @@ export default class App extends React.PureComponent {
}
this.setState({ loading: true });
- return this.fetchIssuesUntil(paging.pageIndex + 1, done).then(response => {
- const nextIssues = [...issues, ...response.issues];
-
- this.setState({
- issues: nextIssues,
- loading: false,
- paging: response.paging
- });
- return nextIssues.filter(isSameComponent);
- });
+ return this.fetchIssuesUntil(paging.pageIndex + 1, done).then(
+ response => {
+ const nextIssues = [...issues, ...response.issues];
+ if (this.mounted) {
+ this.setState({
+ issues: nextIssues,
+ loading: false,
+ paging: response.paging
+ });
+ }
+ return nextIssues.filter(isSameComponent);
+ },
+ () => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ }
+ );
};
fetchFacet = (facet /*: string */) => {
@@ -671,7 +693,6 @@ export default class App extends React.PureComponent {
fetchIssues={bulkChange === 'all' ? this.fetchIssues : this.getCheckedIssues}
onClose={this.closeBulkChange}
onDone={this.handleBulkChangeDone}
- onRequestFail={this.props.onRequestFail}
organization={this.props.organization}
/>}
</div>
diff --git a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js
index 9d1ab75594b..040f0c4718f 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js
+++ b/server/sonar-web/src/main/js/apps/issues/components/AppContainer.js
@@ -23,7 +23,7 @@ import { withRouter } from 'react-router';
/*:: import type { Dispatch } from 'redux'; */
import { uniq } from 'lodash';
import App from './App';
-import { onFail } from '../../../store/rootActions';
+import throwGlobalError from '../../../app/utils/throwGlobalError';
import { getComponent, getCurrentUser } from '../../../store/rootReducer';
import { getOrganizations } from '../../../api/organizations';
import { receiveOrganizations } from '../../../store/organizations/duck';
@@ -46,7 +46,7 @@ const fetchIssueOrganizations = issues => dispatch => {
const organizationKeys = uniq(issues.map(issue => issue.organization));
return getOrganizations(organizationKeys).then(
response => dispatch(receiveOrganizations(response.organizations)),
- onFail(dispatch)
+ throwGlobalError
);
};
@@ -59,11 +59,8 @@ const fetchIssues = (query /*: RawQuery */) => dispatch =>
return { ...response, issues: parsedIssues };
})
.then(response => dispatch(fetchIssueOrganizations(response.issues)).then(() => response))
- .catch(onFail(dispatch));
+ .catch(throwGlobalError);
-const onRequestFail = (error /*: Error */) => (dispatch /*: Dispatch<*> */) =>
- onFail(dispatch)(error);
-
-const mapDispatchToProps = { fetchIssues, onRequestFail };
+const mapDispatchToProps = { fetchIssues };
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(App));
diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js
index e5002e86251..a0ce352c35b 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js
+++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js
@@ -29,6 +29,7 @@ import MarkdownTips from '../../../components/common/MarkdownTips';
import SeverityHelper from '../../../components/shared/SeverityHelper';
import Avatar from '../../../components/ui/Avatar';
import IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
+import throwGlobalError from '../../../app/utils/throwGlobalError';
import { searchIssueTags, bulkChangeIssues } from '../../../api/issues';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { searchAssignees } from '../utils';
@@ -42,7 +43,6 @@ type Props = {|
fetchIssues: ({}) => Promise<*>,
onClose: () => void,
onDone: () => void,
- onRequestFail: Error => void,
organization?: { key: string }
|};
*/
@@ -200,7 +200,7 @@ export default class BulkChangeModal extends React.PureComponent {
},
(error /*: Error */) => {
this.setState({ submitting: false });
- this.props.onRequestFail(error);
+ throwGlobalError(error);
}
);
};
diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js b/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js
index 7d43bccc987..b44ed55d61a 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js
+++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.js
@@ -24,13 +24,14 @@ import { formatMeasure } from '../../../helpers/measures';
/*::
type Props = {
+ className? : string,
current: ?number,
total: number
};
*/
const IssuesCounter = (props /*: Props */) =>
- <span>
+ <span className={props.className}>
<strong>
{props.current != null &&
<span>
diff --git a/server/sonar-web/src/main/js/apps/issues/components/PageActions.js b/server/sonar-web/src/main/js/apps/issues/components/PageActions.js
index 64366643914..199a627d929 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/PageActions.js
+++ b/server/sonar-web/src/main/js/apps/issues/components/PageActions.js
@@ -19,6 +19,7 @@
*/
// @flow
import React from 'react';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
import IssuesCounter from './IssuesCounter';
import ReloadButton from './ReloadButton';
/*:: import type { Paging } from '../utils'; */
@@ -62,10 +63,11 @@ export default class PageActions extends React.PureComponent {
{this.renderShortcuts()}
<div className="issues-page-actions">
- {this.props.loading
- ? <i className="issues-main-header-spinner spinner spacer-right" />
- : <ReloadButton className="spacer-right" onClick={this.props.onReload} />}
- {paging != null && <IssuesCounter current={selectedIndex} total={paging.total} />}
+ <DeferredSpinner className="issues-main-header-spinner" loading={this.props.loading}>
+ <ReloadButton onClick={this.props.onReload} />
+ </DeferredSpinner>
+ {paging != null &&
+ <IssuesCounter className="spacer-left" current={selectedIndex} total={paging.total} />}
</div>
</div>
);
diff --git a/server/sonar-web/src/main/js/apps/issues/styles.css b/server/sonar-web/src/main/js/apps/issues/styles.css
index bb0f41ec65b..dee7d080b35 100644
--- a/server/sonar-web/src/main/js/apps/issues/styles.css
+++ b/server/sonar-web/src/main/js/apps/issues/styles.css
@@ -2,6 +2,10 @@
line-height: 24px;
}
+.issues-main-header-spinner {
+ margin-right: 2px;
+}
+
.concise-issues-list-header,
.concise-issues-list-header-inner {
}