commit: dc01f90dde55e2babf58878177308c11aa965006
parent: 24f3770fb5ca47b41a9fbf8711dd614fb50537ca
Author: Shpuld Shpludson <shp@cock.li>
Date:   Thu, 28 Feb 2019 17:19:14 +0000
Merge branch '386-display-invalid-user-profile' into 'develop'
Show error message when visit profile page of invalid user
Closes #386
See merge request pleroma/pleroma-fe!606
Diffstat:
6 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
@@ -1,9 +1,15 @@
+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'
 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 +19,16 @@ const UserProfile = {
     this.startFetchFavorites()
     if (!this.user.id) {
       this.$store.dispatch('fetchUser', this.fetchBy)
+        .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')
+          }
+        })
     }
   },
   destroyed () {
diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue
@@ -55,7 +55,8 @@
       </div>
     </div>
     <div class="panel-body">
-      <i class="icon-spin3 animate-spin"></i>
+      <span v-if="error">{{ error }}</span>
+      <i class="icon-spin3 animate-spin" v-else></i>
     </div>
   </div>
 </div>
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -390,7 +390,9 @@
     "mute_progress": "Muting..."
   },
   "user_profile": {
-    "timeline_title": "User Timeline"
+    "timeline_title": "User Timeline",
+    "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/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
@@ -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,7 +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) => data.json())
+    .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) => parseUser(data))
 }
 
diff --git a/src/services/errors/errors.js 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