aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-08-12 10:18:02 +0200
committerStas Vilchik <vilchiks@gmail.com>2016-08-12 10:24:11 +0200
commit5bcae889e71152a593781551b535d45eaa959c8e (patch)
tree6bd5f859e6888bea7212434d0e49167c84b8180a /server
parente03f75abae03373364a2f00797cc26e5126446d7 (diff)
downloadsonarqube-5bcae889e71152a593781551b535d45eaa959c8e.tar.gz
sonarqube-5bcae889e71152a593781551b535d45eaa959c8e.zip
SONAR-7919 handle errors and display success messages
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/apps/code/utils.js5
-rw-r--r--server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js56
-rw-r--r--server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js1
-rw-r--r--server/sonar-web/src/main/js/apps/project-admin/key/Key.js45
-rw-r--r--server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js10
-rw-r--r--server/sonar-web/src/main/js/apps/project-admin/key/utils.js25
-rw-r--r--server/sonar-web/src/main/js/apps/project-admin/key/views/UpdateKeyConfirmation.js9
-rw-r--r--server/sonar-web/src/main/js/components/store/globalMessages.js11
8 files changed, 122 insertions, 40 deletions
diff --git a/server/sonar-web/src/main/js/apps/code/utils.js b/server/sonar-web/src/main/js/apps/code/utils.js
index aaa5974a794..169f7175ac9 100644
--- a/server/sonar-web/src/main/js/apps/code/utils.js
+++ b/server/sonar-web/src/main/js/apps/code/utils.js
@@ -163,6 +163,11 @@ export function loadMoreChildren (componentKey, page) {
});
}
+/**
+ * Parse response of failed request
+ * @param {Error} error
+ * @returns {Promise}
+ */
export function parseError (error) {
const DEFAULT_MESSAGE = translate('default_error_message');
diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js
index 1624faddc3f..10524a81dcd 100644
--- a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js
+++ b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js
@@ -18,15 +18,25 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
+import { connect } from 'react-redux';
import BulkUpdateForm from './BulkUpdateForm';
import BulkUpdateResults from './BulkUpdateResults';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { bulkChangeKey } from '../../../api/components';
-import { getComponentUrl } from '../../../helpers/urls';
+import { parseError } from '../../code/utils';
+import {
+ addGlobalErrorMessage,
+ addGlobalSuccessMessage,
+ closeAllGlobalMessages
+} from '../../../components/store/globalMessages';
+import { reloadUpdateKeyPage } from './utils';
-export default class BulkUpdate extends React.Component {
+class BulkUpdate extends React.Component {
static propTypes = {
- component: React.PropTypes.object.isRequired
+ component: React.PropTypes.object.isRequired,
+ addGlobalErrorMessage: React.PropTypes.func.isRequired,
+ addGlobalSuccessMessage: React.PropTypes.func.isRequired,
+ closeAllGlobalMessages: React.PropTypes.func.isRequired
};
state = {
@@ -41,17 +51,20 @@ export default class BulkUpdate extends React.Component {
handleConfirm () {
this.setState({ updating: true });
-
+
const { component } = this.props;
const { replace, by } = this.state;
+
bulkChangeKey(component.key, replace, by).then(r => {
const result = r.keys.find(result => result.key === component.key);
const newComponentKey = result != null ? result.newKey : component.key;
- this.setState({
- updating: false,
- updated: true,
- newComponentKey
- });
+
+ this.props.addGlobalSuccessMessage(translate('update_key.key_updated'));
+ this.setState({ updating: false });
+ reloadUpdateKeyPage(newComponentKey);
+ }).catch(e => {
+ this.setState({ updating: false });
+ parseError(e).then(message => this.props.addGlobalErrorMessage(message));
});
}
@@ -59,6 +72,9 @@ export default class BulkUpdate extends React.Component {
const { component } = this.props;
bulkChangeKey(component.key, replace, by, true).then(r => {
this.setState({ results: r.keys, replace, by });
+ this.props.closeAllGlobalMessages();
+ }).catch(e => {
+ parseError(e).then(message => this.props.addGlobalErrorMessage(message));
});
}
@@ -70,20 +86,6 @@ export default class BulkUpdate extends React.Component {
);
}
- renderUpdated () {
- return (
- <div id="project-key-bulk-update">
- <div className="alert alert-success">
- {translate('update_key.key_updated')}
- {' '}
- <a href={getComponentUrl(this.state.newComponentKey)}>
- {translate('check_project')}
- </a>
- </div>
- </div>
- );
- }
-
render () {
const { component } = this.props;
const { updating, updated } = this.state;
@@ -125,3 +127,11 @@ export default class BulkUpdate extends React.Component {
);
}
}
+
+export default connect(
+ null, {
+ addGlobalErrorMessage,
+ addGlobalSuccessMessage,
+ closeAllGlobalMessages
+ }
+)(BulkUpdate);
diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js b/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js
index 6f7deacf0ed..e86404f8c16 100644
--- a/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js
+++ b/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js
@@ -20,7 +20,6 @@
import React from 'react';
import UpdateKeyForm from './UpdateKeyForm';
import QualifierIcon from '../../../components/shared/qualifier-icon';
-import { translate } from '../../../helpers/l10n';
export default class FineGrainedUpdate extends React.Component {
render () {
diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/Key.js b/server/sonar-web/src/main/js/apps/project-admin/key/Key.js
index 47b61bc3e6e..b7c7b307ef4 100644
--- a/server/sonar-web/src/main/js/apps/project-admin/key/Key.js
+++ b/server/sonar-web/src/main/js/apps/project-admin/key/Key.js
@@ -24,15 +24,26 @@ import Header from './Header';
import UpdateForm from './UpdateForm';
import BulkUpdate from './BulkUpdate';
import FineGrainedUpdate from './FineGrainedUpdate';
+import GlobalMessagesContainer from '../components/GlobalMessagesContainer';
import { getProjectModules } from '../store/rootReducer';
import { fetchProjectModules, changeKey } from '../store/actions';
import { translate } from '../../../helpers/l10n';
+import {
+ addGlobalErrorMessage,
+ closeAllGlobalMessages,
+ addGlobalSuccessMessage
+} from '../../../components/store/globalMessages';
+import { parseError } from '../../code/utils';
+import { reloadUpdateKeyPage } from './utils';
class Key extends React.Component {
static propTypes = {
component: React.PropTypes.object.isRequired,
fetchProjectModules: React.PropTypes.func.isRequired,
- changeKey: React.PropTypes.func.isRequired
+ changeKey: React.PropTypes.func.isRequired,
+ addGlobalErrorMessage: React.PropTypes.func.isRequired,
+ addGlobalSuccessMessage: React.PropTypes.func.isRequired,
+ closeAllGlobalMessages: React.PropTypes.func.isRequired
};
state = {
@@ -49,10 +60,13 @@ class Key extends React.Component {
handleChangeKey (key, newKey) {
return this.props.changeKey(key, newKey).then(() => {
+ this.props.addGlobalSuccessMessage(translate('update_key.key_updated'));
+
if (key === this.props.component.key) {
- window.location = window.baseUrl +
- '/project/key?id=' + encodeURIComponent(newKey);
+ reloadUpdateKeyPage(newKey);
}
+ }).catch(e => {
+ parseError(e).then(this.props.addGlobalErrorMessage);
});
}
@@ -60,6 +74,7 @@ class Key extends React.Component {
e.preventDefault();
e.target.blur();
this.setState({ tab });
+ this.props.closeAllGlobalMessages();
}
render () {
@@ -79,9 +94,12 @@ class Key extends React.Component {
)}
{noModules && (
- <UpdateForm
- component={component}
- onKeyChange={this.handleChangeKey.bind(this)}/>
+ <div>
+ <GlobalMessagesContainer/>
+ <UpdateForm
+ component={component}
+ onKeyChange={this.handleChangeKey.bind(this)}/>
+ </div>
)}
{hasModules && (
@@ -107,6 +125,8 @@ class Key extends React.Component {
</ul>
</div>
+ <GlobalMessagesContainer/>
+
{tab === 'bulk' && (
<BulkUpdate component={component}/>
)}
@@ -115,7 +135,9 @@ class Key extends React.Component {
<FineGrainedUpdate
component={component}
modules={modules}
- onKeyChange={this.handleChangeKey.bind(this)}/>
+ onKeyChange={this.handleChangeKey.bind(this)}
+ onSuccess={this.props.closeAllGlobalMessages}
+ onError={this.props.addGlobalErrorMessage}/>
)}
</div>
)}
@@ -129,6 +151,11 @@ const mapStateToProps = (state, ownProps) => ({
});
export default connect(
- mapStateToProps,
- { fetchProjectModules, changeKey }
+ mapStateToProps, {
+ fetchProjectModules,
+ changeKey,
+ addGlobalErrorMessage,
+ addGlobalSuccessMessage,
+ closeAllGlobalMessages
+ }
)(Key);
diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js b/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js
index 701d2070957..1031ad1ba6c 100644
--- a/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js
+++ b/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js
@@ -46,6 +46,11 @@ export default class UpdateForm extends React.Component {
this.setState({ newKey });
}
+ handleReset (e) {
+ e.preventDefault();
+ this.setState({ newKey: null });
+ }
+
render () {
const value = this.state.newKey != null ?
this.state.newKey :
@@ -69,6 +74,11 @@ export default class UpdateForm extends React.Component {
<button id="update-key-submit" disabled={!hasChanged}>
{translate('update_verb')}
</button>
+ {' '}
+ <button id="update-key-reset" disabled={!hasChanged}
+ onClick={this.handleReset.bind(this)}>
+ {translate('reset_verb')}
+ </button>
</div>
</form>
);
diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/utils.js b/server/sonar-web/src/main/js/apps/project-admin/key/utils.js
new file mode 100644
index 00000000000..a17481bed35
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/project-admin/key/utils.js
@@ -0,0 +1,25 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.
+ */
+export const reloadUpdateKeyPage = componentKey => {
+ setTimeout(() => {
+ window.location = window.baseUrl +
+ '/project/key?id=' + encodeURIComponent(componentKey);
+ }, 1000);
+};
diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/views/UpdateKeyConfirmation.js b/server/sonar-web/src/main/js/apps/project-admin/key/views/UpdateKeyConfirmation.js
index 9b1c4abd26e..4ece410093b 100644
--- a/server/sonar-web/src/main/js/apps/project-admin/key/views/UpdateKeyConfirmation.js
+++ b/server/sonar-web/src/main/js/apps/project-admin/key/views/UpdateKeyConfirmation.js
@@ -29,13 +29,8 @@ export default ModalForm.extend({
this.disableForm();
this.showSpinner();
- this.options.onChange(this.options.component.key, this.options.newKey)
- .then(() => this.destroy())
- .catch(e => {
- parseError(e).then(msg => this.showSingleError(msg));
- this.hideSpinner();
- this.enableForm();
- });
+ this.options.onChange(this.options.component.key, this.options.newKey);
+ this.destroy();
},
serializeData () {
diff --git a/server/sonar-web/src/main/js/components/store/globalMessages.js b/server/sonar-web/src/main/js/components/store/globalMessages.js
index b2860e09a22..038c74f0132 100644
--- a/server/sonar-web/src/main/js/components/store/globalMessages.js
+++ b/server/sonar-web/src/main/js/components/store/globalMessages.js
@@ -37,6 +37,13 @@ export const addGlobalErrorMessage = message =>
export const addGlobalSuccessMessage = message =>
addGlobalMessage(message, SUCCESS);
+const CLOSE_ALL_GLOBAL_MESSAGES = 'CLOSE_ALL_GLOBAL_MESSAGES';
+
+export const closeAllGlobalMessages = id => ({
+ type: CLOSE_ALL_GLOBAL_MESSAGES,
+ id
+});
+
/* Reducer */
const globalMessages = (state = [], action = {}) => {
if (action.type === ADD_GLOBAL_MESSAGE) {
@@ -47,6 +54,10 @@ const globalMessages = (state = [], action = {}) => {
}];
}
+ if (action.type === CLOSE_ALL_GLOBAL_MESSAGES) {
+ return [];
+ }
+
return state;
};