diff --git a/backend/src/schema/resolvers/helpers/Resolver.js b/backend/src/schema/resolvers/helpers/Resolver.js index 655cf08a0..fd41205a3 100644 --- a/backend/src/schema/resolvers/helpers/Resolver.js +++ b/backend/src/schema/resolvers/helpers/Resolver.js @@ -15,10 +15,12 @@ export default function Resolver(type, options = {}) { const { idAttribute = 'id', undefinedToNull = [], + boolean = {}, count = {}, hasOne = {}, hasMany = {}, } = options + const _hasResolver = (resolvers, { key, connection }, { returnType }) => { return async (parent, params, context, resolveInfo) => { if (typeof parent[key] !== 'undefined') return parent[key] @@ -31,6 +33,26 @@ export default function Resolver(type, options = {}) { } } + const booleanResolver = obj => { + const resolvers = {} + for (const [key, condition] of Object.entries(obj)) { + resolvers[key] = async (parent, params, { cypherParams }, resolveInfo) => { + if (typeof parent[key] !== 'undefined') return parent[key] + const result = await instance.cypher( + ` + ${condition.replace('this', 'this {id: $parent.id}')} as ${key}`, + { + parent, + cypherParams, + }, + ) + const [record] = result.records + return record.get(key) + } + } + return resolvers + } + const countResolver = obj => { const resolvers = {} for (const [key, connection] of Object.entries(obj)) { @@ -67,6 +89,7 @@ export default function Resolver(type, options = {}) { } const result = { ...undefinedToNullResolver(undefinedToNull), + ...booleanResolver(boolean), ...countResolver(count), ...hasOneResolver(hasOne), ...hasManyResolver(hasMany), diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index 0824d62c0..767cde24b 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -110,18 +110,6 @@ export default { const [{ email }] = result.records.map(r => r.get('e').properties) return email }, - isBlocked: async (parent, params, context, resolveInfo) => { - if (typeof parent.isBlocked !== 'undefined') return parent.isBlocked - const result = await instance.cypher( - ` - MATCH (u:User { id: $currentUser.id })-[:BLOCKED]->(b:User {id: $parent.id}) - RETURN COUNT(u) >= 1 as isBlocked - `, - { parent, currentUser: context.user }, - ) - const [record] = result.records - return record.get('isBlocked') - }, ...Resolver('User', { undefinedToNull: [ 'actorId', @@ -132,6 +120,12 @@ export default { 'locationName', 'about', ], + boolean: { + followedByCurrentUser: + 'MATCH (this)<-[:FOLLOWS]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1', + isBlocked: + 'MATCH (this)<-[:BLOCKED]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1', + }, count: { contributionsCount: '-[:WROTE]->(related:Post)', friendsCount: '<-[:FRIENDS]->(related:User)', diff --git a/webapp/components/ContentMenu.vue b/webapp/components/ContentMenu.vue index 0ac885597..3b82486fe 100644 --- a/webapp/components/ContentMenu.vue +++ b/webapp/components/ContentMenu.vue @@ -122,13 +122,34 @@ export default { } } - if (this.isOwner && this.resourceType === 'user') { - routes.push({ - name: this.$t(`settings.name`), - path: '/settings', - icon: 'edit', - }) + if (this.resourceType === 'user') { + if (this.isOwner) { + routes.push({ + name: this.$t(`settings.name`), + path: '/settings', + icon: 'edit', + }) + } else { + if (this.resource.isBlocked) { + routes.push({ + name: this.$t(`settings.blocked-users.unblock`), + callback: () => { + this.$emit('unblock', this.resource) + }, + icon: 'user-plus', + }) + } else { + routes.push({ + name: this.$t(`settings.blocked-users.block`), + callback: () => { + this.$emit('block', this.resource) + }, + icon: 'user-times', + }) + } + } } + return routes }, isModerator() { diff --git a/webapp/graphql/UserProfile/User.js b/webapp/graphql/UserProfile/User.js index 897b5b91d..9febce142 100644 --- a/webapp/graphql/UserProfile/User.js +++ b/webapp/graphql/UserProfile/User.js @@ -46,6 +46,7 @@ export default i18n => { } followedByCount followedByCurrentUser + isBlocked followedBy(first: 7) { id slug diff --git a/webapp/graphql/settings/BlockedUsers.js b/webapp/graphql/settings/BlockedUsers.js index 2cfd7bfe3..e47355b18 100644 --- a/webapp/graphql/settings/BlockedUsers.js +++ b/webapp/graphql/settings/BlockedUsers.js @@ -1,6 +1,6 @@ import gql from 'graphql-tag' -export default () => { +export const BlockedUsers = () => { return gql(` { blockedUsers { @@ -15,3 +15,25 @@ export default () => { } `) } + +export const Block = () => { + return gql(`mutation($id:ID!) { + block(id: $id) { + id + name + isBlocked + followedByCurrentUser + } + }`) +} + +export const Unblock = () => { + return gql(`mutation($id:ID!) { + unblock(id: $id) { + id + name + isBlocked + followedByCurrentUser + } + }`) +} diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 2e89a72d0..5a77a85eb 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -202,7 +202,9 @@ "name": "Name", "slug": "Alias" }, - "empty": "Bislang hast du niemanden blockiert." + "empty": "Bislang hast du niemanden blockiert.", + "block": "Nutzer blockieren", + "unblock": "Nutzer entblocken" } }, "admin": { diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 7f8441c71..85e21abff 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -203,7 +203,9 @@ "name": "Name", "slug": "Slug" }, - "empty": "So far, you did not block anybody." + "empty": "So far, you did not block anybody.", + "block": "Block user", + "unblock": "Unblock user" } }, "admin": { diff --git a/webapp/pages/profile/_id/_slug.vue b/webapp/pages/profile/_id/_slug.vue index 8a04e873b..a807740d0 100644 --- a/webapp/pages/profile/_id/_slug.vue +++ b/webapp/pages/profile/_id/_slug.vue @@ -22,6 +22,8 @@ :resource="user" :is-owner="myProfile" class="user-content-menu" + @block="block" + @unblock="unblock" /> @@ -54,13 +56,18 @@ - +