From e687b58091bcedb6f3a56d94030fa312e51830d5 Mon Sep 17 00:00:00 2001 From: taehoon Date: Thu, 21 Feb 2019 13:32:47 -0500 Subject: [PATCH 1/2] Show error message when visit profile page of invalid user --- src/components/user_profile/user_profile.js | 8 ++++++++ src/components/user_profile/user_profile.vue | 3 ++- src/i18n/en.json | 3 ++- src/modules/users.js | 2 +- src/services/api/api.service.js | 6 ++++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 37179ce1..44192e9a 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -4,6 +4,11 @@ import Timeline from '../timeline/timeline.vue' import FollowList from '../follow_list/follow_list.vue' const UserProfile = { + data () { + return { + error: false + } + }, created () { this.$store.commit('clearTimeline', { timeline: 'user' }) this.$store.commit('clearTimeline', { timeline: 'favorites' }) @@ -13,6 +18,9 @@ const UserProfile = { this.startFetchFavorites() if (!this.user.id) { this.$store.dispatch('fetchUser', this.fetchBy) + .catch(() => { + this.error = true + }) } }, destroyed () { diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 09fb93de..ccebe20b 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -55,7 +55,8 @@
- + {{ $t('user_profile.profile_does_not_exist') }} +
diff --git a/src/i18n/en.json b/src/i18n/en.json index 64753f1d..c482ecb6 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -383,7 +383,8 @@ "mute_progress": "Muting..." }, "user_profile": { - "timeline_title": "User Timeline" + "timeline_title": "User Timeline", + "profile_does_not_exist": "Sorry, this profile does not exist." }, "who_to_follow": { "more": "More", diff --git a/src/modules/users.js b/src/modules/users.js index 77df7168..eabfe5ae 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -140,7 +140,7 @@ const users = { getters, actions: { fetchUser (store, id) { - store.rootState.api.backendInteractor.fetchUser({ id }) + return store.rootState.api.backendInteractor.fetchUser({ id }) .then((user) => store.commit('addNewUsers', [user])) }, fetchBlocks (store) { diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 3d2e8823..d8716596 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -244,6 +244,12 @@ const denyUser = ({id, credentials}) => { const fetchUser = ({id, credentials}) => { let url = `${USER_URL}?user_id=${id}` return fetch(url, { headers: authHeaders(credentials) }) + .then((data) => { + if (!data.ok) { + throw Error(data.statusText) + } + return data + }) .then((data) => data.json()) .then((data) => parseUser(data)) } From b78227456ea6b1a80cd85988d3ef91cb654a881c Mon Sep 17 00:00:00 2001 From: taehoon Date: Tue, 26 Feb 2019 12:26:04 -0500 Subject: [PATCH 2/2] Better error handling --- src/components/user_profile/user_profile.js | 12 ++++++++++-- src/components/user_profile/user_profile.vue | 2 +- src/i18n/en.json | 3 ++- src/services/api/api.service.js | 15 +++++++++------ src/services/errors/errors.js | 14 ++++++++++++++ 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 src/services/errors/errors.js diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 44192e9a..ebf6c61a 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -1,3 +1,4 @@ +import get from 'lodash/get' import UserCardContent from '../user_card_content/user_card_content.vue' import UserCard from '../user_card/user_card.vue' import Timeline from '../timeline/timeline.vue' @@ -18,8 +19,15 @@ const UserProfile = { this.startFetchFavorites() if (!this.user.id) { this.$store.dispatch('fetchUser', this.fetchBy) - .catch(() => { - this.error = true + .catch((reason) => { + const errorMessage = get(reason, 'error.error') + if (errorMessage === 'No user with such user_id') { // Known error + this.error = this.$t('user_profile.profile_does_not_exist') + } else if (errorMessage) { + this.error = errorMessage + } else { + this.error = this.$t('user_profile.profile_loading_error') + } }) } }, diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index ccebe20b..ba1a7760 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -55,7 +55,7 @@
- {{ $t('user_profile.profile_does_not_exist') }} + {{ error }}
diff --git a/src/i18n/en.json b/src/i18n/en.json index c482ecb6..9fdd1692 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -384,7 +384,8 @@ }, "user_profile": { "timeline_title": "User Timeline", - "profile_does_not_exist": "Sorry, this profile does not exist." + "profile_does_not_exist": "Sorry, this profile does not exist.", + "profile_loading_error": "Sorry, there was an error loading this profile." }, "who_to_follow": { "more": "More", diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index d8716596..fbe5afa0 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -47,6 +47,7 @@ const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites' import { each, map } from 'lodash' import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js' import 'whatwg-fetch' +import { StatusCodeError } from '../errors/errors' const oldfetch = window.fetch @@ -244,13 +245,15 @@ const denyUser = ({id, credentials}) => { const fetchUser = ({id, credentials}) => { let url = `${USER_URL}?user_id=${id}` return fetch(url, { headers: authHeaders(credentials) }) - .then((data) => { - if (!data.ok) { - throw Error(data.statusText) - } - return data + .then((response) => { + return new Promise((resolve, reject) => response.json() + .then((json) => { + if (!response.ok) { + return reject(new StatusCodeError(response.status, json, { url }, response)) + } + return resolve(json) + })) }) - .then((data) => data.json()) .then((data) => parseUser(data)) } diff --git a/src/services/errors/errors.js b/src/services/errors/errors.js new file mode 100644 index 00000000..548f3c68 --- /dev/null +++ b/src/services/errors/errors.js @@ -0,0 +1,14 @@ +export function StatusCodeError (statusCode, body, options, response) { + this.name = 'StatusCodeError' + this.statusCode = statusCode + this.message = statusCode + ' - ' + (JSON && JSON.stringify ? JSON.stringify(body) : body) + this.error = body // legacy attribute + this.options = options + this.response = response + + if (Error.captureStackTrace) { // required for non-V8 environments + Error.captureStackTrace(this) + } +} +StatusCodeError.prototype = Object.create(Error.prototype) +StatusCodeError.prototype.constructor = StatusCodeError