diff --git a/backend/src/graphql/resolvers/groups.ts b/backend/src/graphql/resolvers/groups.ts index 9a524d2d3..da84e6aca 100644 --- a/backend/src/graphql/resolvers/groups.ts +++ b/backend/src/graphql/resolvers/groups.ts @@ -471,6 +471,9 @@ export default { }) ).records.map((r) => r.get('inviteCodes')) }, + currentlyPinnedPostsCount: async (parent, _args, context: Context, _resolveInfo) => { + return 0 + }, ...Resolver('Group', { undefinedToNull: ['deleted', 'disabled', 'locationName', 'about'], hasMany: { diff --git a/backend/src/graphql/types/type/Group.gql b/backend/src/graphql/types/type/Group.gql index 03b3e0eee..874739458 100644 --- a/backend/src/graphql/types/type/Group.gql +++ b/backend/src/graphql/types/type/Group.gql @@ -48,6 +48,8 @@ type Group { "inviteCodes to this group the current user has generated" inviteCodes: [InviteCode]! @neo4j_ignore + + currentlyPinnedPostsCount: Int! @neo4j_ignore } diff --git a/backend/src/middleware/permissionsMiddleware.ts b/backend/src/middleware/permissionsMiddleware.ts index 5fc087204..878dda879 100644 --- a/backend/src/middleware/permissionsMiddleware.ts +++ b/backend/src/middleware/permissionsMiddleware.ts @@ -434,7 +434,7 @@ export default shield( Room: isAuthenticated, Message: isAuthenticated, UnreadRooms: isAuthenticated, - PostsPinnedCounts: isAdmin, + PostsPinnedCounts: isAuthenticated, // Invite Code validateInviteCode: allow, diff --git a/webapp/components/ContentMenu/ContentMenu.vue b/webapp/components/ContentMenu/ContentMenu.vue index dc765c4a3..ee4b1eb0c 100644 --- a/webapp/components/ContentMenu/ContentMenu.vue +++ b/webapp/components/ContentMenu/ContentMenu.vue @@ -244,6 +244,27 @@ export default { } } + console.log(this.resourceType, this.resource) + if ( + this.resourceType === 'contribution' && + this.resource.group && + this.resource.group.myRole === 'owner' && + (this.canBeGroupPinned || this.resource.groupPinnedBy) + ) { + routes.push({ + label: this.resource.groupPinnedBy + ? this.$t(`post.menu.groupUnpin`) + : this.$t(`post.menu.groupPin`), + callback: () => { + this.$emit( + this.resource.groupPinnedBy ? 'unpinGroupPost' : 'pinGroupPost', + this.resource, + ) + }, + icon: this.resource.groupPinnedBy ? 'unlink' : 'link', + }) + } + return routes }, isModerator() { @@ -258,6 +279,14 @@ export default { (this.maxPinnedPosts > 1 && this.currentlyPinnedPosts < this.maxPinnedPosts) ) }, + canBeGroupPinned() { + return ( + this.maxPinnedPosts === 1 || + (this.maxPinnedPosts > 1 && + this.resource.group && + this.resource.group.currentlyPinnedPostsCount < this.maxPinnedPosts) + ) + }, }, methods: { openItem(route, toggleMenu) { diff --git a/webapp/components/PostTeaser/PostTeaser.vue b/webapp/components/PostTeaser/PostTeaser.vue index 222df0a76..5e1ec78d8 100644 --- a/webapp/components/PostTeaser/PostTeaser.vue +++ b/webapp/components/PostTeaser/PostTeaser.vue @@ -112,6 +112,8 @@ :is-owner="isAuthor" @pinPost="pinPost" @unpinPost="unpinPost" + @pinGroupPost="pinGroupPost" + @unpinGroupPost="unpinGroupPost" @pushPost="pushPost" @unpushPost="unpushPost" @toggleObservePost="toggleObservePost" @@ -229,6 +231,12 @@ export default { unpinPost(post) { this.$emit('unpinPost', post) }, + pinGroupPost(post) { + this.$emit('pinGroupPost', post) + }, + unpinGroupPost(post) { + this.$emit('unpinPost', post) + }, pushPost(post) { this.$emit('pushPost', post) }, diff --git a/webapp/components/_new/features/SearchResults/SearchResults.vue b/webapp/components/_new/features/SearchResults/SearchResults.vue index 71f94a489..17e74a4ed 100644 --- a/webapp/components/_new/features/SearchResults/SearchResults.vue +++ b/webapp/components/_new/features/SearchResults/SearchResults.vue @@ -48,6 +48,8 @@ @removePostFromList="posts = removePostFromList(post, posts)" @pinPost="pinPost(post, refetchPostList)" @unpinPost="unpinPost(post, refetchPostList)" + @pinGroupPost="pinGroupPost(post, refetchPostList)" + @unpinGroupPost="unpinGroupPost(post, refetchPostList)" @pushPost="pushPost(post, refetchPostList)" @unpushPost="unpushPost(post, refetchPostList)" @toggleObservePost=" diff --git a/webapp/graphql/PostMutations.js b/webapp/graphql/PostMutations.js index 13cb79ae3..b5ac06563 100644 --- a/webapp/graphql/PostMutations.js +++ b/webapp/graphql/PostMutations.js @@ -173,6 +173,40 @@ export default () => { } } `, + pinGroupPost: gql` + mutation ($id: ID!) { + pinGroupPost(id: $id) { + id + title + slug + content + contentExcerpt + language + pinnedBy { + id + name + role + } + } + } + `, + unpinGroupPost: gql` + mutation ($id: ID!) { + unpinGroupPost(id: $id) { + id + title + slug + content + contentExcerpt + language + pinnedBy { + id + name + role + } + } + } + `, pushPost: gql` mutation ($id: ID!) { pushPost(id: $id) { diff --git a/webapp/graphql/PostQuery.js b/webapp/graphql/PostQuery.js index d451eb256..ea5f16cfe 100644 --- a/webapp/graphql/PostQuery.js +++ b/webapp/graphql/PostQuery.js @@ -52,6 +52,8 @@ export default (i18n) => { name slug groupType + myRole + currentlyPinnedPostsCount } } } @@ -95,6 +97,8 @@ export const filterPosts = (i18n) => { name slug groupType + myRole + currentlyPinnedPostsCount } } } @@ -137,6 +141,8 @@ export const profilePagePosts = (i18n) => { name slug groupType + myRole + currentlyPinnedPostsCount } } } diff --git a/webapp/mixins/pinnedPosts.js b/webapp/mixins/pinnedPosts.js index 66022c1e8..7d6bdc404 100644 --- a/webapp/mixins/pinnedPosts.js +++ b/webapp/mixins/pinnedPosts.js @@ -14,6 +14,6 @@ export default { }), }, async created() { - if (this.isAdmin && this.maxPinnedPosts === 0) await this.fetchPinnedPostsCount() + /* if (this.isAdmin && this.maxPinnedPosts === 0) */ await this.fetchPinnedPostsCount() }, } diff --git a/webapp/mixins/postListActions.js b/webapp/mixins/postListActions.js index 73ac5562a..5375d2e00 100644 --- a/webapp/mixins/postListActions.js +++ b/webapp/mixins/postListActions.js @@ -38,6 +38,36 @@ export default { }) .catch((error) => this.$toast.error(error.message)) }, + pinGroupPost(post, refetchPostList = () => {}) { + this.$apollo + .mutate({ + mutation: PostMutations().pinGroupPost, + variables: { + id: post.id, + }, + }) + .then(() => { + this.$toast.success(this.$t('post.menu.groupPinnedSuccessfully')) + // this.storePinGroupPost() + refetchPostList() + }) + .catch((error) => this.$toast.error(error.message)) + }, + unpinGroupPost(post, refetchPostList = () => {}) { + this.$apollo + .mutate({ + mutation: PostMutations().unpinGroupPost, + variables: { + id: post.id, + }, + }) + .then(() => { + this.$toast.success(this.$t('post.menu.groupUnpinnedSuccessfully')) + // this.storeUnpinGroupPost() + refetchPostList() + }) + .catch((error) => this.$toast.error(error.message)) + }, pushPost(post, refetchPostList = () => {}) { this.$apollo .mutate({ diff --git a/webapp/pages/groups/_id/_slug.vue b/webapp/pages/groups/_id/_slug.vue index c2fb2c1a9..144f49b4a 100644 --- a/webapp/pages/groups/_id/_slug.vue +++ b/webapp/pages/groups/_id/_slug.vue @@ -246,6 +246,8 @@ @removePostFromList="posts = removePostFromList(post, posts)" @pinPost="pinPost(post, refetchPostList)" @unpinPost="unpinPost(post, refetchPostList)" + @pinGroupPost="pinGroupPost(post, refetchPostList)" + @unpinGroupPost="unpinGroupPost(post, refetchPostList)" @pushPost="pushPost(post, refetchPostList)" @unpushPost="unpushPost(post, refetchPostList)" @toggleObservePost=" diff --git a/webapp/pages/index.vue b/webapp/pages/index.vue index ee6185a03..98afb2724 100644 --- a/webapp/pages/index.vue +++ b/webapp/pages/index.vue @@ -116,6 +116,8 @@ @removePostFromList="posts = removePostFromList(post, posts)" @pinPost="pinPost(post, refetchPostList)" @unpinPost="unpinPost(post, refetchPostList)" + @pinGroupPost="pinGroupPost(post, refetchPostList)" + @unpinGroupPost="unpinGroupPost(post, refetchPostList)" @pushPost="pushPost(post, refetchPostList)" @unpushPost="unpushPost(post, refetchPostList)" @toggleObservePost=" diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 88616b115..4a89106d7 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -58,6 +58,8 @@ :is-owner="isAuthor" @pinPost="pinPost" @unpinPost="unpinPost" + @pinGroupPost="pinGroupPost" + @unpinGroupPost="unpinGroupPost" @pushPost="pushPost" @unpushPost="unpushPost" @toggleObservePost="toggleObservePost" diff --git a/webapp/pages/profile/_id/_slug.vue b/webapp/pages/profile/_id/_slug.vue index 83b80b3af..1c0ad08ac 100644 --- a/webapp/pages/profile/_id/_slug.vue +++ b/webapp/pages/profile/_id/_slug.vue @@ -160,6 +160,8 @@ @removePostFromList="posts = removePostFromList(post, posts)" @pinPost="pinPost(post, refetchPostList)" @unpinPost="unpinPost(post, refetchPostList)" + @pinGroupPost="pinGroupPost(post, refetchPostList)" + @unpinGroupPost="unpinGroupPost(post, refetchPostList)" @pushPost="pushPost(post, refetchPostList)" @unpushPost="unpushPost(post, refetchPostList)" @toggleObservePost="