diff --git a/components/Author.vue b/components/Author.vue index f1f57113b..54770d33d 100644 --- a/components/Author.vue +++ b/components/Author.vue @@ -107,7 +107,9 @@ @@ -139,21 +141,12 @@ export default { trunc: { type: Number, default: null }, showAuthorPopover: { type: Boolean, default: true } }, - data() { - return { - voted: false - } - }, computed: { itsMe() { return this.author.slug === this.$store.getters['auth/user'].slug }, fanCount() { let count = Number(this.author.followedByCount) || 0 - if (this.voted) { - // NOTE: this is used for presentation - count += 1 - } return count }, author() { diff --git a/components/FollowButton.vue b/components/FollowButton.vue index 3540726d2..f5c705a8d 100644 --- a/components/FollowButton.vue +++ b/components/FollowButton.vue @@ -2,12 +2,15 @@ - Folgen + {{ label }} @@ -18,37 +21,69 @@ export default { name: 'HcFollowButton', props: { - followId: { type: String, default: null } + followId: { type: String, default: null }, + isFollowed: { type: Boolean, default: false } }, data() { return { disabled: false, - loading: false + loading: false, + hovered: false + } + }, + computed: { + icon() { + if (this.isFollowed && this.hovered) { + return 'close' + } else { + return this.isFollowed ? 'check' : 'plus' + } + }, + label() { + if (this.isFollowed) { + return this.$t('followButton.following') + } else { + return this.$t('followButton.follow') + } + } + }, + watch: { + isFollowed() { + this.loading = false + this.hovered = false } }, methods: { - follow() { - this.loading = true + onHover() { + if (!this.disabled && !this.loading) { + this.hovered = true + } + }, + toggle() { + const follow = !this.isFollowed + const mutation = follow ? 'follow' : 'unfollow' + + this.hovered = false + + this.$emit('optimistic', follow) + this.$apollo .mutate({ mutation: gql` - mutation($myId: ID!, $followId: ID!) { - AddUserFollowing(from: { id: $myId }, to: { id: $followId }) { - from { - id - } - } + mutation($id: ID!) { + ${mutation}(id: $id, type: User) } `, variables: { - myId: this.$store.getters['auth/user'].id, - followId: this.followId + id: this.followId } }) - .then(() => { - this.loading = false - this.disabled = true - this.$emit('update') + .then(res => { + // this.$emit('optimistic', follow ? res.data.follow : follow) + this.$emit('update', follow) + }) + .catch(() => { + this.$emit('optimistic', !follow) }) } } diff --git a/components/ShoutButton.vue b/components/ShoutButton.vue index 075006b2e..02d7cb639 100644 --- a/components/ShoutButton.vue +++ b/components/ShoutButton.vue @@ -4,20 +4,25 @@ style="text-align: center" > - + {{ shoutedCount }}x - Empfohlen + {{ $t('shoutButton.shouted') }} @@ -28,41 +33,69 @@ import gql from 'graphql-tag' export default { props: { count: { type: Number, default: 0 }, - postId: { type: String, default: null } + postId: { type: String, default: null }, + isShouted: { type: Boolean, default: false }, + disabled: { type: Boolean, default: false } }, data() { return { loading: false, - disabled: false, - shoutedCount: this.count + shoutedCount: this.count, + shouted: false + } + }, + watch: { + isShouted: { + immediate: true, + handler: function(shouted) { + this.shouted = shouted + } } }, methods: { - shout() { - this.loading = true + toggle() { + const shout = !this.shouted + const mutation = shout ? 'shout' : 'unshout' + const count = shout ? this.shoutedCount + 1 : this.shoutedCount - 1 + + const backup = { + shoutedCount: this.shoutedCount, + shouted: this.shouted + } + + this.shoutedCount = count + this.shouted = shout + this.$apollo .mutate({ mutation: gql` - mutation($myId: ID!, $postId: ID!) { - AddUserShouted(from: { id: $myId }, to: { id: $postId }) { - from { - id - } - } + mutation($id: ID!) { + ${mutation}(id: $id, type: Post) } `, variables: { - myId: this.$store.getters['auth/user'].id, - postId: this.postId + id: this.postId } }) - .then(() => { + .then(res => { + if (res && res.data) { + this.$emit('update', shout) + } + }) + .catch(() => { + this.shoutedCount = backup.shoutedCount + this.shouted = backup.shouted + }) + .finally(() => { this.loading = false - this.disabled = true - this.shoutedCount++ - this.$emit('update') }) } } } + + diff --git a/graphql/UserProfileQuery.js b/graphql/UserProfileQuery.js index 4e0245b52..30431602b 100644 --- a/graphql/UserProfileQuery.js +++ b/graphql/UserProfileQuery.js @@ -29,6 +29,7 @@ export default app => { slug avatar followedByCount + followedByCurrentUser contributionsCount commentsCount badges { @@ -41,12 +42,14 @@ export default app => { } } followedByCount + followedByCurrentUser followedBy(first: 7) { id name slug avatar followedByCount + followedByCurrentUser contributionsCount commentsCount badges { diff --git a/locales/de.json b/locales/de.json index b3e6289ac..7a06b767e 100644 --- a/locales/de.json +++ b/locales/de.json @@ -17,6 +17,13 @@ "moreInfo": "Was ist Human Connection?", "hello": "Hallo" }, + "followButton": { + "follow": "Folgen", + "following": "Folge Ich" + }, + "shoutButton": { + "shouted": "empfohlen" + }, "profile": { "name": "Mein Profil", "memberSince": "Mitglied seit", diff --git a/locales/en.json b/locales/en.json index cfe634675..c49fd1318 100644 --- a/locales/en.json +++ b/locales/en.json @@ -17,6 +17,13 @@ "moreInfo": "What is Human Connection?", "hello": "Hello" }, + "followButton": { + "follow": "Follow", + "following": "Following" + }, + "shoutButton": { + "shouted": "shouted" + }, "profile": { "name": "My Profile", "memberSince": "Member since", diff --git a/pages/index.vue b/pages/index.vue index 7bc85b3a4..f4785b3ac 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -108,6 +108,7 @@ export default { shoutedCount commentsCount followedByCount + followedByCurrentUser location { name: name${this.$i18n.locale().toUpperCase()} } diff --git a/pages/post/_slug/index.vue b/pages/post/_slug/index.vue index 68655a31f..074db5d7b 100644 --- a/pages/post/_slug/index.vue +++ b/pages/post/_slug/index.vue @@ -28,7 +28,9 @@ @@ -188,9 +190,10 @@ export default { contributionsCount commentsCount followedByCount + followedByCurrentUser location { - name: name${this.$i18n.locale().toUpperCase()} - } + name: name${this.$i18n.locale().toUpperCase()} + } badges { id key @@ -215,6 +218,7 @@ export default { contributionsCount commentsCount followedByCount + followedByCurrentUser location { name: name${this.$i18n.locale().toUpperCase()} } @@ -231,6 +235,7 @@ export default { icon } shoutedCount + shoutedByCurrentUser } } `) diff --git a/pages/post/_slug/more-info.vue b/pages/post/_slug/more-info.vue index 847975757..d4de5f6f3 100644 --- a/pages/post/_slug/more-info.vue +++ b/pages/post/_slug/more-info.vue @@ -109,6 +109,7 @@ export default { avatar contributionsCount followedByCount + followedByCurrentUser commentsCount location { name: name${this.$i18n.locale().toUpperCase()} diff --git a/pages/profile/_slug.vue b/pages/profile/_slug.vue index 98d3b9f48..614187004 100644 --- a/pages/profile/_slug.vue +++ b/pages/profile/_slug.vue @@ -61,7 +61,7 @@ - + - +