mirror of
https://github.com/flarum/core.git
synced 2025-08-05 07:57:46 +02:00
Improve client XHR error handling
The default XHR error handler produce an alert which is appropriate to the response status code. It can be overridden per-request (by specifying the `errorHandler` option) so that the alert can be suppressed or displayed in a different position (e.g. inside a modal). ref #118
This commit is contained in:
@@ -163,5 +163,6 @@ export default class AvatarEditor extends Component {
|
||||
*/
|
||||
failure() {
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
}
|
||||
}
|
||||
|
@@ -83,16 +83,8 @@ export default class ChangeEmailModal extends Modal {
|
||||
|
||||
this.loading = true;
|
||||
|
||||
app.session.user.save({email: this.email()}).then(
|
||||
() => {
|
||||
this.loading = false;
|
||||
this.success = true;
|
||||
m.redraw();
|
||||
},
|
||||
response => {
|
||||
this.loading = false;
|
||||
this.handleErrors(response);
|
||||
}
|
||||
);
|
||||
app.session.user.save({email: this.email()}, {errorHandler: this.onerror.bind(this)})
|
||||
.then(() => this.success = true)
|
||||
.finally(this.loaded.bind(this));
|
||||
}
|
||||
}
|
||||
|
@@ -42,8 +42,8 @@ export default class ChangePasswordModal extends Modal {
|
||||
url: app.forum.attribute('apiUrl') + '/forgot',
|
||||
data: {email: app.session.user.email()}
|
||||
}).then(
|
||||
() => this.hide(),
|
||||
() => this.loading = false
|
||||
this.hide.bind(this),
|
||||
this.loaded.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -102,4 +102,12 @@ export default class ComposerBody extends Component {
|
||||
*/
|
||||
onsubmit() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop loading.
|
||||
*/
|
||||
loaded() {
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
}
|
||||
}
|
||||
|
@@ -109,11 +109,7 @@ export default class DiscussionComposer extends ComposerBody {
|
||||
app.cache.discussionList.addDiscussion(discussion);
|
||||
m.route(app.route.discussion(discussion));
|
||||
},
|
||||
response => {
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
app.alertErrors(response.errors);
|
||||
}
|
||||
this.loaded.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -128,7 +128,7 @@ export default class DiscussionPage extends Page {
|
||||
// component for the first time on page load, then any calls to m.redraw
|
||||
// will be ineffective and thus any configs (scroll code) will be run
|
||||
// before stuff is drawn to the page.
|
||||
setTimeout(this.show.bind(this, preloadedDiscussion));
|
||||
setTimeout(this.show.bind(this, preloadedDiscussion), 0);
|
||||
} else {
|
||||
const params = this.requestParams();
|
||||
|
||||
|
@@ -37,7 +37,7 @@ export default class EditPostComposer extends ComposerBody {
|
||||
|
||||
items.add('title', (
|
||||
<h3>
|
||||
{icon('pencil')}{' '}
|
||||
{icon('pencil')} {' '}
|
||||
<a href={app.route.discussion(post.discussion(), post.number())} config={m.route}>
|
||||
{app.trans('core.forum.composer_edit_post_link', {number: post.number(), discussion: post.discussion().title()})}
|
||||
</a>
|
||||
@@ -64,14 +64,8 @@ export default class EditPostComposer extends ComposerBody {
|
||||
const data = this.data();
|
||||
|
||||
this.props.post.save(data).then(
|
||||
() => {
|
||||
app.composer.hide();
|
||||
m.redraw();
|
||||
},
|
||||
() => {
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
}
|
||||
() => app.composer.hide(),
|
||||
this.loaded.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -102,11 +102,7 @@ export default class EditUserModal extends Modal {
|
||||
);
|
||||
}
|
||||
|
||||
onsubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.loading = true;
|
||||
|
||||
data() {
|
||||
const groups = Object.keys(this.groups)
|
||||
.filter(id => this.groups[id]())
|
||||
.map(id => app.store.getById('groups', id));
|
||||
@@ -121,12 +117,19 @@ export default class EditUserModal extends Modal {
|
||||
data.password = this.password();
|
||||
}
|
||||
|
||||
this.props.user.save(data).then(
|
||||
() => this.hide(),
|
||||
response => {
|
||||
return data;
|
||||
}
|
||||
|
||||
onsubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.loading = true;
|
||||
|
||||
this.props.user.save(this.data(), {errorHandler: this.onerror.bind(this)})
|
||||
.then(this.hide.bind(this))
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
this.handleErrors(response);
|
||||
}
|
||||
);
|
||||
m.redraw();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -85,24 +85,12 @@ export default class ForgotPasswordModal extends Modal {
|
||||
app.request({
|
||||
method: 'POST',
|
||||
url: app.forum.attribute('apiUrl') + '/forgot',
|
||||
data: {email: this.email()},
|
||||
handlers: {
|
||||
404: () => {
|
||||
this.alert = new Alert({type: 'warning', message: 'That email wasn\'t found in our database.'});
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
}).then(
|
||||
() => {
|
||||
this.loading = false;
|
||||
data: {email: this.email()}
|
||||
})
|
||||
.then(() => {
|
||||
this.success = true;
|
||||
this.alert = null;
|
||||
m.redraw();
|
||||
},
|
||||
response => {
|
||||
this.loading = false;
|
||||
this.handleErrors(response);
|
||||
}
|
||||
);
|
||||
})
|
||||
.finally(this.loaded.bind(this));
|
||||
}
|
||||
}
|
||||
|
@@ -124,25 +124,25 @@ export default class LogInModal extends Modal {
|
||||
const email = this.email();
|
||||
const password = this.password();
|
||||
|
||||
app.session.login(email, password).then(
|
||||
null,
|
||||
response => {
|
||||
this.loading = false;
|
||||
app.session.login(email, password, {errorHandler: this.onerror.bind(this)})
|
||||
.catch(this.loaded.bind(this));
|
||||
}
|
||||
|
||||
if (response && response.code === 'confirm_email') {
|
||||
this.alert = Alert.component({
|
||||
children: app.trans('core.forum.log_in_confirmation_required_message', {email: response.email})
|
||||
});
|
||||
} else {
|
||||
this.alert = Alert.component({
|
||||
type: 'error',
|
||||
children: app.trans('core.forum.log_in_invalid_login_message')
|
||||
});
|
||||
}
|
||||
onerror(error) {
|
||||
switch (error.status) {
|
||||
case 401:
|
||||
error.alert.props.children = app.trans('core.forum.log_in_confirmation_required_message', {email: error.response.emailConfirmationRequired});
|
||||
delete error.alert.props.type;
|
||||
break;
|
||||
|
||||
m.redraw();
|
||||
this.onready();
|
||||
}
|
||||
);
|
||||
case 404:
|
||||
error.alert.props.children = app.trans('core.forum.log_in_invalid_login_message');
|
||||
break;
|
||||
|
||||
default:
|
||||
// no default
|
||||
}
|
||||
|
||||
super.onerror(error);
|
||||
}
|
||||
}
|
||||
|
@@ -115,13 +115,12 @@ export default class NotificationList extends Component {
|
||||
this.loading = true;
|
||||
m.redraw();
|
||||
|
||||
app.store.find('notifications').then(notifications => {
|
||||
app.session.user.pushAttributes({newNotificationsCount: 0});
|
||||
app.cache.notifications = notifications.sort((a, b) => b.time() - a.time());
|
||||
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
});
|
||||
app.store.find('notifications')
|
||||
.then(notifications => {
|
||||
app.session.user.pushAttributes({newNotificationsCount: 0});
|
||||
app.cache.notifications = notifications.sort((a, b) => b.time() - a.time());
|
||||
})
|
||||
.finally(this.loaded.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -36,7 +36,8 @@ export default class ReplyComposer extends ComposerBody {
|
||||
|
||||
items.add('title', (
|
||||
<h3>
|
||||
{icon('reply')}{' '}<a href={app.route.discussion(discussion)} config={m.route}>{discussion.title()}</a>
|
||||
{icon('reply')} {' '}
|
||||
<a href={app.route.discussion(discussion)} config={m.route}>{discussion.title()}</a>
|
||||
</h3>
|
||||
));
|
||||
|
||||
@@ -93,11 +94,7 @@ export default class ReplyComposer extends ComposerBody {
|
||||
|
||||
app.composer.hide();
|
||||
},
|
||||
response => {
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
app.alertErrors(response.errors);
|
||||
}
|
||||
this.loaded.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -178,7 +178,8 @@ export default class SignUpModal extends Modal {
|
||||
app.request({
|
||||
url: app.forum.attribute('baseUrl') + '/register',
|
||||
method: 'POST',
|
||||
data
|
||||
data,
|
||||
errorHandler: this.onerror.bind(this)
|
||||
}).then(
|
||||
payload => {
|
||||
const user = app.store.pushPayload(payload);
|
||||
@@ -190,14 +191,10 @@ export default class SignUpModal extends Modal {
|
||||
window.location.reload();
|
||||
} else {
|
||||
this.welcomeUser = user;
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
this.loaded();
|
||||
}
|
||||
},
|
||||
response => {
|
||||
this.loading = false;
|
||||
this.handleErrors(response);
|
||||
}
|
||||
this.loaded.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -91,10 +91,7 @@ export default class UserBio extends Component {
|
||||
if (user.bio() !== value) {
|
||||
this.loading = true;
|
||||
|
||||
user.save({bio: value}).then(() => {
|
||||
this.loading = false;
|
||||
m.redraw();
|
||||
});
|
||||
user.save({bio: value}).finally(this.loaded.bind(this));
|
||||
}
|
||||
|
||||
this.editing = false;
|
||||
|
Reference in New Issue
Block a user